Skip to content

Commit e479595

Browse files
authored
Merge pull request #11 from valtzu/node-type-constants
Use node type constants
2 parents 638c20d + 57d753a commit e479595

File tree

9 files changed

+145
-77
lines changed

9 files changed

+145
-77
lines changed

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
/node_modules
2-
package-lock.json
2+
/package-lock.json
33
/dist
44
/src/*.js
55
/test/*.js
6-
/src/*.d.ts

src/complete.ts

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,26 @@ import { EditorState } from "@codemirror/state";
55
import { SyntaxNode } from "@lezer/common";
66
import { getExpressionLanguageConfig, keywords, resolveTypes } from "./utils";
77
import { syntaxTree } from "@codemirror/language";
8+
import {
9+
Arguments,
10+
BinaryExpression,
11+
Expression,
12+
Function,
13+
MethodAccess,
14+
OperatorKeyword,
15+
PropertyAccess,
16+
TernaryExpression,
17+
UnaryExpression,
18+
Variable,
19+
String,
20+
BlockComment,
21+
ArrayAccess,
22+
Call,
23+
Application,
24+
Property,
25+
Method,
26+
Array,
27+
} from "./syntax.grammar.terms";
828

929
const autocompleteFunction = (x: ELFunction): Completion => ({
1030
label: `${x.name}(${x.args?.map(x => x.name)?.join(',') || ''})`,
@@ -56,11 +76,11 @@ function completeIdentifier(state: EditorState, config: ExpressionLanguageConfig
5676
}
5777

5878
function completeMember(state: EditorState, config: ExpressionLanguageConfig, tree: SyntaxNode, from: number, to: number, explicit: boolean): CompletionResult | null {
59-
if (tree.parent?.name != 'ObjectAccess' || !tree.parent.firstChild) {
79+
if (!(tree.parent?.type.is(PropertyAccess) || tree.parent?.type.is(MethodAccess)) || !tree.parent?.firstChild) {
6080
return null;
6181
}
6282

63-
const types = resolveTypes(state, tree.parent.firstChild.node, config, false);
83+
const types = resolveTypes(state, tree.parent.firstChild.node, config);
6484
if (!types?.size) {
6585
return null;
6686
}
@@ -89,31 +109,31 @@ export function expressionLanguageCompletion(context: CompletionContext): Comple
89109
const prevNode = tree.resolveInner(pos, lastChar === ')' ? 0 : -1);
90110
const config = getExpressionLanguageConfig(state);
91111

92-
const isIdentifier = (node: SyntaxNode | undefined) => ['Variable', 'Function'].includes(node?.name ?? '');
93-
const isMember = (node: SyntaxNode | undefined) => ['Property', 'Method'].includes(node?.name ?? '');
112+
const isIdentifier = (node: SyntaxNode | undefined) => node?.type.is(Variable) || node?.type.is(Function);
113+
const isMember = (node: SyntaxNode | undefined) => node?.type.is(Property) || node?.type.is(Method);
94114

95-
if (prevNode.name == 'String' || prevNode.name == 'BlockComment') {
115+
if (prevNode.type.is(String) || prevNode.type.is(BlockComment)) {
96116
return null;
97117
}
98118

99-
if (prevNode.parent?.name == 'ObjectAccess' && ['ObjectAccess', 'ArrayAccess', 'Variable', 'Call', 'Application'].includes(prevNode.parent.firstChild?.name || '')) {
119+
if ((prevNode.parent?.type.is(PropertyAccess) || prevNode.parent?.type.is(MethodAccess)) && [PropertyAccess, MethodAccess, ArrayAccess, Variable, Call, Application].includes(prevNode.parent.firstChild?.type.id)) {
100120
return completeMember(state, config, prevNode, isIdentifier(prevNode) || isMember(prevNode) ? prevNode.from : pos, pos, explicit);
101121
}
102122

103123
if (
104-
['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression'].includes(prevNode.name) && prevNode.lastChild && !prevNode.lastChild?.type.isError
105-
|| ['Arguments', 'Array'].includes(prevNode.name) && prevNode.lastChild && !prevNode.lastChild?.type.isError
106-
|| ['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression'].includes(prevNode.parent?.name ?? '') && prevNode.type.isError
107-
|| ['Variable', 'Function'].includes(prevNode.parent?.name ?? '') && prevNode.type.isError
124+
[Expression, UnaryExpression, BinaryExpression, TernaryExpression].includes(prevNode.type.id) && prevNode.lastChild && !prevNode.lastChild?.type.isError
125+
|| [Arguments, Array].includes(prevNode.type.id) && prevNode.lastChild && !prevNode.lastChild?.type.isError
126+
|| [Expression, UnaryExpression, BinaryExpression, TernaryExpression].includes(prevNode.parent?.type.id) && prevNode.type.isError
127+
|| [Variable, Function].includes(prevNode.parent?.type.id) && prevNode.type.isError
108128
) {
109-
return completeOperatorKeyword(state, config, prevNode, !['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression', 'Arguments'].includes(prevNode.name) ? prevNode.from : pos, pos, explicit);
129+
return completeOperatorKeyword(state, config, prevNode, ![Expression, UnaryExpression, BinaryExpression, TernaryExpression, Arguments].includes(prevNode.type.id) ? prevNode.from : pos, pos, explicit);
110130
}
111131

112132
if (
113-
!/[0-9]/.test(lastChar) && !['OperatorKeyword'].includes(prevNode.name ?? '') && (
114-
['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression'].includes(prevNode.name) && prevNode.lastChild?.type.isError
115-
|| ['Expression', 'UnaryExpression', 'BinaryExpression', 'TernaryExpression', 'Arguments'].includes(prevNode.parent?.name ?? '') && !prevNode.type.isError
116-
|| ['Arguments', 'Array'].includes(prevNode.name ?? '')
133+
!/[0-9]/.test(lastChar) && !prevNode.type.is(OperatorKeyword) && (
134+
[Expression, UnaryExpression, BinaryExpression, TernaryExpression].includes(prevNode.type.id) && prevNode.lastChild?.type.isError
135+
|| [Expression, UnaryExpression, BinaryExpression, TernaryExpression, Arguments].includes(prevNode.parent?.type.id ?? -1) && !prevNode.type.isError
136+
|| prevNode.type.is(Arguments) || prevNode.type.is(Array)
117137
)
118138
) {
119139
return completeIdentifier(state, config, prevNode, isIdentifier(prevNode) ? prevNode.from : pos, pos);

src/linter.ts

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Diagnostic, linter } from "@codemirror/lint";
33
import { syntaxTree } from "@codemirror/language";
44
import { getExpressionLanguageConfig, resolveFunctionDefinition, resolveIdentifier, resolveTypes } from "./utils";
55
import { ELScalar } from "./types";
6+
import { Arguments, Method, Property, Variable, Function, BlockComment } from "./syntax.grammar.terms";
67

78
/**
89
* @internal
@@ -12,11 +13,11 @@ export const expressionLanguageLinterSource = (state: EditorState) => {
1213
let diagnostics: Diagnostic[] = [];
1314

1415
syntaxTree(state).cursor().iterate(node => {
15-
const { from, to, name } = node;
16+
const { from, to, type: { id } } = node;
1617

1718
let identifier: string | undefined;
18-
switch (name) {
19-
case '⚠':
19+
switch (id) {
20+
case 0:
2021
if (state.doc.length === 0 || from === 0) {
2122
// Don't show error on empty doc (even though it is an error)
2223
return;
@@ -31,14 +32,14 @@ export const expressionLanguageLinterSource = (state: EditorState) => {
3132
}
3233

3334
return;
34-
case 'Arguments':
35+
case Arguments:
3536
const args = resolveFunctionDefinition(node.node.prevSibling, state, config)?.args;
3637
if (!args) {
3738
return;
3839
}
3940

4041
for (let n = node.node.firstChild, i = 0; n != null; n = n.nextSibling) {
41-
if (n.name === 'BlockComment') {
42+
if (n.type.is(BlockComment)) {
4243
continue;
4344
}
4445

@@ -47,7 +48,7 @@ export const expressionLanguageLinterSource = (state: EditorState) => {
4748
continue;
4849
}
4950

50-
const typesUsed = Array.from(resolveTypes(state, n, config, true));
51+
const typesUsed = Array.from(resolveTypes(state, n, config));
5152
const typesExpected = args[i].type;
5253

5354
if (typesExpected && !typesExpected.includes(ELScalar.Any) && !typesUsed.some(x => typesExpected.includes(x))) {
@@ -57,22 +58,22 @@ export const expressionLanguageLinterSource = (state: EditorState) => {
5758
}
5859

5960
break;
60-
case 'Property':
61-
case 'Method':
61+
case Property:
62+
case Method:
6263
const leftArgument = node.node.parent?.firstChild?.node;
63-
const types = Array.from(resolveTypes(state, leftArgument, config, true));
64+
const types = Array.from(resolveTypes(state, leftArgument, config));
6465
identifier = state.sliceDoc(from, to);
6566

66-
if (!types.find(type => resolveIdentifier(name, identifier, config.types?.[type]))) {
67+
if (!types.find(type => resolveIdentifier(id, identifier, config.types?.[type]))) {
6768
diagnostics.push({ from, to, severity: 'error', message: `${node.name} "${identifier}" not found in ${types.join('|')}` });
6869
}
6970

7071
break;
7172

72-
case 'Variable':
73-
case 'Function':
73+
case Variable:
74+
case Function:
7475
identifier = state.sliceDoc(from, node.node.firstChild ? node.node.firstChild.from - 1 : to);
75-
if (!resolveIdentifier(name, identifier, config)) {
76+
if (!resolveIdentifier(id, identifier, config)) {
7677
diagnostics.push({ from, to, severity: 'error', message: `${node.node.name} "${identifier}" not found` });
7778
}
7879

src/syntax.grammar

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
@top Expression { expression }
2222

2323
expression {
24-
ObjectAccess<Property> |
24+
PropertyAccess |
2525
ArrayAccess |
2626
Call |
2727
Number |
@@ -34,9 +34,10 @@ expression {
3434
TernaryExpression |
3535
BinaryExpression |
3636
UnaryExpression |
37-
Application { "(" expression ")" }
37+
Application
3838
}
3939

40+
Application { "(" expression ")" }
4041
Variable { word }
4142
Function { word }
4243
Property { word }
@@ -66,17 +67,23 @@ BinaryExpression {
6667
expression !right (OperatorKeyword | Operator) expression
6768
}
6869

69-
ObjectAccess<member> {
70-
expression !left ( MemberOf | NullSafeMemberOf ) member
70+
PropertyAccess {
71+
expression !left ( MemberOf | NullSafeMemberOf ) Property
72+
}
73+
74+
MethodAccess {
75+
expression !left ( MemberOf | NullSafeMemberOf ) Method
7176
}
7277

7378
call<callable> {
74-
callable Arguments { "(" list ")" }
79+
callable Arguments
7580
}
7681

82+
Arguments { "(" list ")" }
83+
7784
Call {
7885
call<Function> |
79-
call<ObjectAccess<Method>>
86+
call<MethodAccess>
8087
}
8188

8289
TernaryExpression {

src/syntax.grammar.terms.d.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
export declare const Application: number;
2+
export declare const Arguments: number;
3+
export declare const Array: number;
4+
export declare const ArrayAccess: number;
5+
export declare const BinaryExpression: number;
6+
export declare const BlockComment: number;
7+
export declare const Boolean: number;
8+
export declare const Call: number;
9+
export declare const Expression: number;
10+
export declare const Function: number;
11+
export declare const MemberOf: number;
12+
export declare const Method: number;
13+
export declare const MethodAccess: number;
14+
export declare const Null: number;
15+
export declare const NullSafeMemberOf: number;
16+
export declare const Number: number;
17+
export declare const Object: number;
18+
export declare const Operator: number;
19+
export declare const OperatorKeyword: number;
20+
export declare const Property: number;
21+
export declare const PropertyAccess: number;
22+
export declare const String: number;
23+
export declare const TernaryExpression: number;
24+
export declare const UnaryExpression: number;
25+
export declare const UnaryOperator: number;
26+
export declare const Variable: number;

src/tooltip.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { SyntaxNode } from "@lezer/common";
22
import { EditorState, StateField } from "@codemirror/state";
3-
import { EditorView, hoverTooltip, showTooltip, Tooltip } from "@codemirror/view";
3+
import { hoverTooltip, showTooltip, Tooltip } from "@codemirror/view";
44
import { syntaxTree } from "@codemirror/language";
55
import { createInfoElement, getExpressionLanguageConfig, keywords, resolveFunctionDefinition, resolveTypes } from "./utils";
6+
import { Arguments, Function, Method, MethodAccess, OperatorKeyword, Property, PropertyAccess, Variable } from "./syntax.grammar.terms";
67

78
function getNodeOrdinal(node: SyntaxNode) {
89
let ordinal = -1;
@@ -16,7 +17,7 @@ function getNodeOrdinal(node: SyntaxNode) {
1617
function resolveArguments(node: SyntaxNode) {
1718
let c: SyntaxNode | null = node;
1819

19-
while (c && c.name !== 'Arguments') {
20+
while (c && !c.type.is(Arguments)) {
2021
c = c.parent;
2122
}
2223

@@ -81,7 +82,7 @@ export const keywordTooltip = hoverTooltip((view, pos, side) => {
8182
const config = getExpressionLanguageConfig(view.state);
8283
const tree: SyntaxNode = syntaxTree(view.state).resolveInner(pos, side);
8384

84-
if (tree.name === 'OperatorKeyword') {
85+
if (tree.type.is(OperatorKeyword)) {
8586
const name = view.state.sliceDoc(tree.from, tree.to);
8687
const info = keywords.find(x => x.name === name)?.info;
8788
if (info) {
@@ -94,15 +95,15 @@ export const keywordTooltip = hoverTooltip((view, pos, side) => {
9495
}
9596
}
9697

97-
if (!['Function', 'Variable', 'Method', 'Property'].includes(tree.name)) {
98+
if (![Function, Variable, Method, Property].includes(tree.type.id)) {
9899
return null;
99100
}
100101

101102
const skipEmpty = (x: any) => x;
102103
let info: string;
103-
if (tree.parent?.firstChild && tree.parent?.name === 'ObjectAccess' && tree.prevSibling) {
104+
if (tree.parent?.firstChild && (tree.parent?.type.is(PropertyAccess) || tree.parent?.type.is(MethodAccess)) && tree.prevSibling) {
104105
const node = tree.parent.firstChild;
105-
const types = Array.from(resolveTypes(view.state, node, config, true));
106+
const types = Array.from(resolveTypes(view.state, node, config));
106107
const name = view.state.sliceDoc(tree.from, tree.to);
107108
info = [
108109
...types.map(type => config.types?.[type]?.identifiers?.find(x => x.name === name)?.info).filter(skipEmpty),

0 commit comments

Comments
 (0)