ifc-expressions 2.3.0 → 3.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +255 -30
- package/dist/IfcExpression.d.ts +24 -26
- package/dist/IfcExpressionErrorListener.d.ts +3 -3
- package/dist/IfcExpressionOptions.d.ts +4 -0
- package/dist/autocomplete/CompletionItem.d.ts +24 -0
- package/dist/autocomplete/IfcExpressionAutocomplete.d.ts +11 -0
- package/dist/builtin/BuiltinRuntimeValueConverter.d.ts +7 -0
- package/dist/builtin/BuiltinVariableRegistry.d.ts +50 -0
- package/dist/cjs/IfcExpression.js +112 -37
- package/dist/cjs/IfcExpression.js.map +1 -1
- package/dist/cjs/IfcExpressionErrorListener.js +3 -8
- package/dist/cjs/IfcExpressionErrorListener.js.map +1 -1
- package/dist/cjs/IfcExpressionOptions.js +3 -0
- package/dist/cjs/IfcExpressionOptions.js.map +1 -0
- package/dist/cjs/autocomplete/CompletionItem.js +3 -0
- package/dist/cjs/autocomplete/CompletionItem.js.map +1 -0
- package/dist/cjs/autocomplete/IfcExpressionAutocomplete.js +654 -0
- package/dist/cjs/autocomplete/IfcExpressionAutocomplete.js.map +1 -0
- package/dist/cjs/builtin/BuiltinRuntimeValueConverter.js +124 -0
- package/dist/cjs/builtin/BuiltinRuntimeValueConverter.js.map +1 -0
- package/dist/cjs/builtin/BuiltinVariableRegistry.js +405 -0
- package/dist/cjs/builtin/BuiltinVariableRegistry.js.map +1 -0
- package/dist/cjs/compiler/ExprCompiler.js +44 -41
- package/dist/cjs/compiler/ExprCompiler.js.map +1 -1
- package/dist/cjs/compiler/ExprManager.js.map +1 -1
- package/dist/cjs/compiler/IfcExpressionValidationListener.js +85 -25
- package/dist/cjs/compiler/IfcExpressionValidationListener.js.map +1 -1
- package/dist/cjs/compiler/TypeManager.js.map +1 -1
- package/dist/cjs/context/IfcExpressionContext.js.map +1 -1
- package/dist/cjs/context/NopContext.js +3 -0
- package/dist/cjs/context/NopContext.js.map +1 -1
- package/dist/cjs/documentation/Documentation.js +11 -0
- package/dist/cjs/documentation/Documentation.js.map +1 -0
- package/dist/cjs/error/ExpressionTypeError.js.map +1 -1
- package/dist/cjs/error/IfcExpressionBuiltinConfigException.js +10 -0
- package/dist/cjs/error/IfcExpressionBuiltinConfigException.js.map +1 -0
- package/dist/cjs/error/InvalidSyntaxException.js.map +1 -1
- package/dist/cjs/error/NoSuchFunctionException.js.map +1 -1
- package/dist/cjs/error/NoSuchMemberException.js +13 -0
- package/dist/cjs/error/NoSuchMemberException.js.map +1 -0
- package/dist/cjs/error/ValidationException.js.map +1 -1
- package/dist/cjs/error/WrongFunctionArgumentTypeException.js.map +1 -1
- package/dist/cjs/expression/ExprKind.js +3 -0
- package/dist/cjs/expression/ExprKind.js.map +1 -1
- package/dist/cjs/expression/function/Func.js +18 -14
- package/dist/cjs/expression/function/Func.js.map +1 -1
- package/dist/cjs/expression/function/FuncArg.js +11 -5
- package/dist/cjs/expression/function/FuncArg.js.map +1 -1
- package/dist/cjs/expression/function/IfcExpressionFunctions.js +198 -42
- package/dist/cjs/expression/function/IfcExpressionFunctions.js.map +1 -1
- package/dist/cjs/expression/function/impl/CHOOSE.js.map +1 -1
- package/dist/cjs/expression/function/impl/IF.js.map +1 -1
- package/dist/cjs/expression/function/impl/MAP.js.map +1 -1
- package/dist/cjs/expression/function/impl/ReplacePattern.js +20 -2
- package/dist/cjs/expression/function/impl/ReplacePattern.js.map +1 -1
- package/dist/cjs/expression/reference/BuiltinFunctionCallExpr.js +59 -0
- package/dist/cjs/expression/reference/BuiltinFunctionCallExpr.js.map +1 -0
- package/dist/cjs/expression/reference/BuiltinPropertyAccessExpr.js +34 -0
- package/dist/cjs/expression/reference/BuiltinPropertyAccessExpr.js.map +1 -0
- package/dist/cjs/expression/reference/BuiltinRootReferenceExpr.js +29 -0
- package/dist/cjs/expression/reference/BuiltinRootReferenceExpr.js.map +1 -0
- package/dist/cjs/gen/parser/IfcExpressionLexer.js +126 -104
- package/dist/cjs/gen/parser/IfcExpressionLexer.js.map +1 -1
- package/dist/cjs/gen/parser/IfcExpressionListener.js +7 -4
- package/dist/cjs/gen/parser/IfcExpressionListener.js.map +1 -1
- package/dist/cjs/gen/parser/IfcExpressionParser.js +739 -682
- package/dist/cjs/gen/parser/IfcExpressionParser.js.map +1 -1
- package/dist/cjs/gen/parser/IfcExpressionVisitor.js +4 -4
- package/dist/cjs/gen/parser/IfcExpressionVisitor.js.map +1 -1
- package/dist/cjs/index.js +4 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/type/ContextObjectType.js +45 -0
- package/dist/cjs/type/ContextObjectType.js.map +1 -0
- package/dist/cjs/type/Types.js +4 -6
- package/dist/cjs/type/Types.js.map +1 -1
- package/dist/cjs/value/ContextObjectValue.js +23 -0
- package/dist/cjs/value/ContextObjectValue.js.map +1 -0
- package/dist/cjs/value/ExpressionValue.js.map +1 -1
- package/dist/cjs/value/Value.js.map +1 -1
- package/dist/compiler/ExprCompiler.d.ts +8 -3
- package/dist/compiler/ExprManager.d.ts +1 -1
- package/dist/compiler/IfcExpressionValidationListener.d.ts +9 -3
- package/dist/compiler/TypeManager.d.ts +1 -1
- package/dist/context/IfcExpressionContext.d.ts +3 -4
- package/dist/context/NopContext.d.ts +1 -0
- package/dist/documentation/Documentation.d.ts +12 -0
- package/dist/error/ExpressionTypeError.d.ts +1 -1
- package/dist/error/IfcExpressionBuiltinConfigException.d.ts +3 -0
- package/dist/error/InvalidSyntaxException.d.ts +1 -1
- package/dist/error/NoSuchFunctionException.d.ts +1 -1
- package/dist/error/NoSuchMemberException.d.ts +6 -0
- package/dist/error/ValidationException.d.ts +1 -1
- package/dist/error/WrongFunctionArgumentTypeException.d.ts +1 -1
- package/dist/expression/ExprKind.d.ts +3 -0
- package/dist/expression/function/Func.d.ts +7 -21
- package/dist/expression/function/FuncArg.d.ts +6 -5
- package/dist/expression/function/IfcExpressionFunctions.d.ts +1 -0
- package/dist/expression/function/impl/CHOOSE.d.ts +1 -1
- package/dist/expression/function/impl/IF.d.ts +1 -1
- package/dist/expression/function/impl/MAP.d.ts +1 -1
- package/dist/expression/reference/BuiltinFunctionCallExpr.d.ts +19 -0
- package/dist/expression/reference/BuiltinPropertyAccessExpr.d.ts +15 -0
- package/dist/expression/reference/BuiltinRootReferenceExpr.d.ts +14 -0
- package/dist/gen/parser/IfcExpressionLexer.d.ts +9 -8
- package/dist/gen/parser/IfcExpressionListener.d.ts +89 -59
- package/dist/gen/parser/IfcExpressionParser.d.ts +192 -169
- package/dist/gen/parser/IfcExpressionVisitor.d.ts +51 -35
- package/dist/index.d.ts +2 -2
- package/dist/mjs/IfcExpression.js +104 -32
- package/dist/mjs/IfcExpression.js.map +1 -1
- package/dist/mjs/IfcExpressionErrorListener.js +3 -8
- package/dist/mjs/IfcExpressionErrorListener.js.map +1 -1
- package/dist/mjs/IfcExpressionOptions.js +2 -0
- package/dist/mjs/IfcExpressionOptions.js.map +1 -0
- package/dist/mjs/autocomplete/CompletionItem.js +2 -0
- package/dist/mjs/autocomplete/CompletionItem.js.map +1 -0
- package/dist/mjs/autocomplete/IfcExpressionAutocomplete.js +650 -0
- package/dist/mjs/autocomplete/IfcExpressionAutocomplete.js.map +1 -0
- package/dist/mjs/builtin/BuiltinRuntimeValueConverter.js +117 -0
- package/dist/mjs/builtin/BuiltinRuntimeValueConverter.js.map +1 -0
- package/dist/mjs/builtin/BuiltinVariableRegistry.js +399 -0
- package/dist/mjs/builtin/BuiltinVariableRegistry.js.map +1 -0
- package/dist/mjs/compiler/ExprCompiler.js +43 -40
- package/dist/mjs/compiler/ExprCompiler.js.map +1 -1
- package/dist/mjs/compiler/ExprManager.js.map +1 -1
- package/dist/mjs/compiler/IfcExpressionValidationListener.js +85 -22
- package/dist/mjs/compiler/IfcExpressionValidationListener.js.map +1 -1
- package/dist/mjs/compiler/TypeManager.js.map +1 -1
- package/dist/mjs/context/IfcExpressionContext.js.map +1 -1
- package/dist/mjs/context/NopContext.js +3 -0
- package/dist/mjs/context/NopContext.js.map +1 -1
- package/dist/mjs/documentation/Documentation.js +7 -0
- package/dist/mjs/documentation/Documentation.js.map +1 -0
- package/dist/mjs/error/ExpressionTypeError.js.map +1 -1
- package/dist/mjs/error/IfcExpressionBuiltinConfigException.js +6 -0
- package/dist/mjs/error/IfcExpressionBuiltinConfigException.js.map +1 -0
- package/dist/mjs/error/InvalidSyntaxException.js.map +1 -1
- package/dist/mjs/error/NoSuchFunctionException.js.map +1 -1
- package/dist/mjs/error/NoSuchMemberException.js +9 -0
- package/dist/mjs/error/NoSuchMemberException.js.map +1 -0
- package/dist/mjs/error/ValidationException.js.map +1 -1
- package/dist/mjs/error/WrongFunctionArgumentTypeException.js.map +1 -1
- package/dist/mjs/expression/ExprKind.js +3 -0
- package/dist/mjs/expression/ExprKind.js.map +1 -1
- package/dist/mjs/expression/function/Func.js +18 -14
- package/dist/mjs/expression/function/Func.js.map +1 -1
- package/dist/mjs/expression/function/FuncArg.js +11 -5
- package/dist/mjs/expression/function/FuncArg.js.map +1 -1
- package/dist/mjs/expression/function/IfcExpressionFunctions.js +198 -42
- package/dist/mjs/expression/function/IfcExpressionFunctions.js.map +1 -1
- package/dist/mjs/expression/function/impl/CHOOSE.js.map +1 -1
- package/dist/mjs/expression/function/impl/IF.js.map +1 -1
- package/dist/mjs/expression/function/impl/MAP.js.map +1 -1
- package/dist/mjs/expression/function/impl/ReplacePattern.js +20 -2
- package/dist/mjs/expression/function/impl/ReplacePattern.js.map +1 -1
- package/dist/mjs/expression/reference/BuiltinFunctionCallExpr.js +55 -0
- package/dist/mjs/expression/reference/BuiltinFunctionCallExpr.js.map +1 -0
- package/dist/mjs/expression/reference/BuiltinPropertyAccessExpr.js +30 -0
- package/dist/mjs/expression/reference/BuiltinPropertyAccessExpr.js.map +1 -0
- package/dist/mjs/expression/reference/BuiltinRootReferenceExpr.js +25 -0
- package/dist/mjs/expression/reference/BuiltinRootReferenceExpr.js.map +1 -0
- package/dist/mjs/gen/parser/IfcExpressionLexer.js +101 -104
- package/dist/mjs/gen/parser/IfcExpressionLexer.js.map +1 -1
- package/dist/mjs/gen/parser/IfcExpressionListener.js +5 -3
- package/dist/mjs/gen/parser/IfcExpressionListener.js.map +1 -1
- package/dist/mjs/gen/parser/IfcExpressionParser.js +700 -670
- package/dist/mjs/gen/parser/IfcExpressionParser.js.map +1 -1
- package/dist/mjs/gen/parser/IfcExpressionVisitor.js +2 -3
- package/dist/mjs/gen/parser/IfcExpressionVisitor.js.map +1 -1
- package/dist/mjs/index.js +1 -1
- package/dist/mjs/index.js.map +1 -1
- package/dist/mjs/type/ContextObjectType.js +41 -0
- package/dist/mjs/type/ContextObjectType.js.map +1 -0
- package/dist/mjs/type/Types.js +4 -6
- package/dist/mjs/type/Types.js.map +1 -1
- package/dist/mjs/value/ContextObjectValue.js +19 -0
- package/dist/mjs/value/ContextObjectValue.js.map +1 -0
- package/dist/mjs/value/ExpressionValue.js.map +1 -1
- package/dist/mjs/value/Value.js.map +1 -1
- package/dist/type/ContextObjectType.d.ts +17 -0
- package/dist/type/Types.d.ts +2 -6
- package/dist/value/ContextObjectValue.d.ts +11 -0
- package/dist/value/ExpressionValue.d.ts +2 -1
- package/dist/value/Value.d.ts +1 -1
- package/package.json +5 -3
|
@@ -0,0 +1,650 @@
|
|
|
1
|
+
import { CharStream, CommonTokenStream, ParserRuleContext, Token, } from "antlr4ng";
|
|
2
|
+
import { CodeCompletionCore, } from "antlr4-c3";
|
|
3
|
+
import { BuiltinVariableRegistry, } from "../builtin/BuiltinVariableRegistry.js";
|
|
4
|
+
import { IfcExpressionLexer } from "../gen/parser/IfcExpressionLexer.js";
|
|
5
|
+
import { IfcExpressionParser, MethodCallChainEndContext, MethodCallChainInnerContext, MethodFunctionCallContext, MethodPropertyAccessContext, SEMethodCallContext, SEParenthesisContext, SEVariableRefContext, } from "../gen/parser/IfcExpressionParser.js";
|
|
6
|
+
import { IfcExpressionFunctions } from "../expression/function/IfcExpressionFunctions.js";
|
|
7
|
+
import { ContextObjectType } from "../type/ContextObjectType.js";
|
|
8
|
+
import { resolveLocalizedText, } from "../documentation/Documentation.js";
|
|
9
|
+
function isIdentifierChar(char) {
|
|
10
|
+
return typeof char === "string" && /[a-zA-Z0-9_\-$&]/.test(char);
|
|
11
|
+
}
|
|
12
|
+
function toBuiltinLabel(name) {
|
|
13
|
+
return name.startsWith("$") ? name : `$${name}`;
|
|
14
|
+
}
|
|
15
|
+
function normalizeForMatch(value) {
|
|
16
|
+
return value.toUpperCase();
|
|
17
|
+
}
|
|
18
|
+
function toCompletionTypeName(type) {
|
|
19
|
+
return type.getName().replace(/^\$/, "");
|
|
20
|
+
}
|
|
21
|
+
function isChainableType(type) {
|
|
22
|
+
return type instanceof ContextObjectType;
|
|
23
|
+
}
|
|
24
|
+
const unsupportedPrimitiveMethodFunctionNames = new Set([
|
|
25
|
+
"NAME",
|
|
26
|
+
"GUID",
|
|
27
|
+
"IFCCLASS",
|
|
28
|
+
"DESCRIPTION",
|
|
29
|
+
"VALUE",
|
|
30
|
+
]);
|
|
31
|
+
const preferredMethodLabels = new Map([
|
|
32
|
+
["MAP", "map"],
|
|
33
|
+
["CHOOSE", "choose"],
|
|
34
|
+
["AT", "at"],
|
|
35
|
+
["IF", "if"],
|
|
36
|
+
["ROUND", "round"],
|
|
37
|
+
["NAME", "name"],
|
|
38
|
+
["GUID", "guid"],
|
|
39
|
+
["IFCCLASS", "ifcClass"],
|
|
40
|
+
["DESCRIPTION", "description"],
|
|
41
|
+
["VALUE", "value"],
|
|
42
|
+
["PROPERTYSET", "propertySet"],
|
|
43
|
+
["PROPERTY", "property"],
|
|
44
|
+
["TYPE", "type"],
|
|
45
|
+
["NOT", "not"],
|
|
46
|
+
["TOSTRING", "toString"],
|
|
47
|
+
["TONUMERIC", "toNumeric"],
|
|
48
|
+
["TONUMBER", "toNumber"],
|
|
49
|
+
["TOBOOLEAN", "toBoolean"],
|
|
50
|
+
["TOLOGICAL", "toLogical"],
|
|
51
|
+
["NOTFOUNDASUNKNOWN", "notFoundAsUnknown"],
|
|
52
|
+
["TOIFCDATE", "toIfcDate"],
|
|
53
|
+
["TOIFCTIME", "toIfcTime"],
|
|
54
|
+
["TOIFCDATETIME", "toIfcDateTime"],
|
|
55
|
+
["TOIFCDURATION", "toIfcDuration"],
|
|
56
|
+
["TOIFCTIMESTAMP", "toIfcTimeStamp"],
|
|
57
|
+
["ADDDURATION", "addDuration"],
|
|
58
|
+
["TOLOWERCASE", "toLowerCase"],
|
|
59
|
+
["TOUPPERCASE", "toUpperCase"],
|
|
60
|
+
["SUBSTRING", "substring"],
|
|
61
|
+
["SPLIT", "split"],
|
|
62
|
+
["EXISTS", "exists"],
|
|
63
|
+
["AND", "and"],
|
|
64
|
+
["OR", "or"],
|
|
65
|
+
["XOR", "xor"],
|
|
66
|
+
["IMPLIES", "implies"],
|
|
67
|
+
["EQUALS", "equals"],
|
|
68
|
+
["GREATERTHAN", "greaterThan"],
|
|
69
|
+
["GREATERTHANOREQUAL", "greaterThanOrEqual"],
|
|
70
|
+
["LESSTHAN", "lessThan"],
|
|
71
|
+
["LESSTHANOREQUAL", "lessThanOrEqual"],
|
|
72
|
+
["CONTAINS", "contains"],
|
|
73
|
+
["MATCHES", "matches"],
|
|
74
|
+
["REGEXCONTAINS", "regexContains"],
|
|
75
|
+
["REGEXMATCHES", "regexMatches"],
|
|
76
|
+
["REPLACE", "replace"],
|
|
77
|
+
["REGEXREPLACE", "regexReplace"],
|
|
78
|
+
]);
|
|
79
|
+
const emptyExpressionStarterFunctionNames = [
|
|
80
|
+
"IF",
|
|
81
|
+
"EXISTS",
|
|
82
|
+
"ROUND",
|
|
83
|
+
"CONTAINS",
|
|
84
|
+
"MATCHES",
|
|
85
|
+
"REPLACE",
|
|
86
|
+
"TOSTRING",
|
|
87
|
+
"TONUMERIC",
|
|
88
|
+
"TOBOOLEAN",
|
|
89
|
+
];
|
|
90
|
+
function isExtendableTokenType(tokenType) {
|
|
91
|
+
return tokenType === IfcExpressionParser.IDENTIFIER;
|
|
92
|
+
}
|
|
93
|
+
function findCaretTokenIndex(tokens, cursorOffset) {
|
|
94
|
+
if (tokens.length === 0) {
|
|
95
|
+
return 0;
|
|
96
|
+
}
|
|
97
|
+
const cursor = Math.max(0, cursorOffset);
|
|
98
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
99
|
+
const token = tokens[i];
|
|
100
|
+
if (token.type === Token.EOF) {
|
|
101
|
+
return token.tokenIndex;
|
|
102
|
+
}
|
|
103
|
+
if (cursor < token.start) {
|
|
104
|
+
return token.tokenIndex;
|
|
105
|
+
}
|
|
106
|
+
if (cursor <= token.stop) {
|
|
107
|
+
return token.tokenIndex;
|
|
108
|
+
}
|
|
109
|
+
if (cursor === token.stop + 1) {
|
|
110
|
+
if (isExtendableTokenType(token.type)) {
|
|
111
|
+
return token.tokenIndex;
|
|
112
|
+
}
|
|
113
|
+
const nextToken = tokens[i + 1];
|
|
114
|
+
return nextToken?.tokenIndex ?? token.tokenIndex;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return tokens[tokens.length - 1].tokenIndex;
|
|
118
|
+
}
|
|
119
|
+
function parseAutocompleteInput(input, cursorOffset) {
|
|
120
|
+
const chars = CharStream.fromString(input);
|
|
121
|
+
const lexer = new IfcExpressionLexer(chars);
|
|
122
|
+
const tokenStream = new CommonTokenStream(lexer);
|
|
123
|
+
const parser = new IfcExpressionParser(tokenStream);
|
|
124
|
+
lexer.removeErrorListeners();
|
|
125
|
+
parser.removeErrorListeners();
|
|
126
|
+
const parseTree = parser.expr();
|
|
127
|
+
tokenStream.fill();
|
|
128
|
+
const tokens = tokenStream.getTokens();
|
|
129
|
+
return {
|
|
130
|
+
parser,
|
|
131
|
+
parseTree,
|
|
132
|
+
tokens,
|
|
133
|
+
caretTokenIndex: findCaretTokenIndex(tokens, cursorOffset),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
function findBuiltinRootReplaceRange(input, cursorOffset) {
|
|
137
|
+
const cursor = Math.max(0, Math.min(cursorOffset, input.length));
|
|
138
|
+
let i = cursor - 1;
|
|
139
|
+
while (i >= 0 && isIdentifierChar(input[i]) && input[i] !== "$") {
|
|
140
|
+
i--;
|
|
141
|
+
}
|
|
142
|
+
if (i >= 0 && input[i] === "$") {
|
|
143
|
+
return { from: i, to: cursor };
|
|
144
|
+
}
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
function findIdentifierReplaceRange(input, cursorOffset) {
|
|
148
|
+
const cursor = Math.max(0, Math.min(cursorOffset, input.length));
|
|
149
|
+
let from = cursor;
|
|
150
|
+
while (from > 0 && isIdentifierChar(input[from - 1])) {
|
|
151
|
+
from--;
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
from,
|
|
155
|
+
to: cursor,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function findMemberReplaceRange(input, cursorOffset) {
|
|
159
|
+
const range = findIdentifierReplaceRange(input, cursorOffset);
|
|
160
|
+
if (range.from === 0 || input[range.from - 1] !== ".") {
|
|
161
|
+
return undefined;
|
|
162
|
+
}
|
|
163
|
+
return range;
|
|
164
|
+
}
|
|
165
|
+
function findFunctionReplaceRange(input, cursorOffset) {
|
|
166
|
+
const range = findIdentifierReplaceRange(input, cursorOffset);
|
|
167
|
+
const prefixChar = range.from > 0 ? input[range.from - 1] : undefined;
|
|
168
|
+
const hasIdentifierFragment = range.from < range.to || isIdentifierChar(input[Math.max(0, range.to)]);
|
|
169
|
+
if (!hasIdentifierFragment || prefixChar === "." || prefixChar === "$") {
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
172
|
+
return range;
|
|
173
|
+
}
|
|
174
|
+
function countExprListArguments(exprList) {
|
|
175
|
+
if (!exprList) {
|
|
176
|
+
return 0;
|
|
177
|
+
}
|
|
178
|
+
const rest = exprList.exprList();
|
|
179
|
+
return 1 + (rest ? countExprListArguments(rest) : 0);
|
|
180
|
+
}
|
|
181
|
+
function toMethodAccessorStep(methodAccessor) {
|
|
182
|
+
if (methodAccessor instanceof MethodPropertyAccessContext) {
|
|
183
|
+
const identifier = methodAccessor.IDENTIFIER()?.getText();
|
|
184
|
+
if (!identifier) {
|
|
185
|
+
return undefined;
|
|
186
|
+
}
|
|
187
|
+
return {
|
|
188
|
+
name: identifier,
|
|
189
|
+
kind: "property",
|
|
190
|
+
startTokenIndex: methodAccessor.start?.tokenIndex ?? -1,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
if (methodAccessor instanceof MethodFunctionCallContext) {
|
|
194
|
+
const functionCall = methodAccessor.functionCall();
|
|
195
|
+
const name = functionCall.IDENTIFIER()?.getText();
|
|
196
|
+
if (!name) {
|
|
197
|
+
return undefined;
|
|
198
|
+
}
|
|
199
|
+
return {
|
|
200
|
+
name,
|
|
201
|
+
kind: "function",
|
|
202
|
+
argumentCount: countExprListArguments(functionCall.exprList()),
|
|
203
|
+
startTokenIndex: functionCall.start?.tokenIndex ?? -1,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
return undefined;
|
|
207
|
+
}
|
|
208
|
+
function collectMethodCallChainSteps(methodCallChain) {
|
|
209
|
+
if (methodCallChain instanceof MethodCallChainInnerContext) {
|
|
210
|
+
const current = toMethodAccessorStep(methodCallChain.methodAccessor());
|
|
211
|
+
const rest = collectMethodCallChainSteps(methodCallChain.methodCallChain());
|
|
212
|
+
if (!current || !rest) {
|
|
213
|
+
return undefined;
|
|
214
|
+
}
|
|
215
|
+
return [current, ...rest];
|
|
216
|
+
}
|
|
217
|
+
if (methodCallChain instanceof MethodCallChainEndContext) {
|
|
218
|
+
const current = toMethodAccessorStep(methodCallChain.methodAccessor());
|
|
219
|
+
return current ? [current] : undefined;
|
|
220
|
+
}
|
|
221
|
+
const dot = methodCallChain.getToken(IfcExpressionParser.DOT, 0);
|
|
222
|
+
if (dot) {
|
|
223
|
+
return [
|
|
224
|
+
{
|
|
225
|
+
kind: "incomplete",
|
|
226
|
+
startTokenIndex: dot.symbol.tokenIndex + 1,
|
|
227
|
+
},
|
|
228
|
+
];
|
|
229
|
+
}
|
|
230
|
+
return [];
|
|
231
|
+
}
|
|
232
|
+
function getMemberResultType(definition) {
|
|
233
|
+
return definition.kind === "property"
|
|
234
|
+
? definition.valueType
|
|
235
|
+
: definition.returnType;
|
|
236
|
+
}
|
|
237
|
+
function resolveCompletedAccessorStep(currentType, step) {
|
|
238
|
+
if (!(currentType instanceof ContextObjectType)) {
|
|
239
|
+
return undefined;
|
|
240
|
+
}
|
|
241
|
+
const memberDefinition = currentType.getMemberDefinition(step.name);
|
|
242
|
+
if (!memberDefinition) {
|
|
243
|
+
return undefined;
|
|
244
|
+
}
|
|
245
|
+
if (step.kind === "property") {
|
|
246
|
+
return memberDefinition.kind === "property"
|
|
247
|
+
? memberDefinition.valueType
|
|
248
|
+
: undefined;
|
|
249
|
+
}
|
|
250
|
+
if (memberDefinition.kind !== "function") {
|
|
251
|
+
return undefined;
|
|
252
|
+
}
|
|
253
|
+
if (memberDefinition.argumentTypes.length !== step.argumentCount) {
|
|
254
|
+
return undefined;
|
|
255
|
+
}
|
|
256
|
+
return memberDefinition.returnType;
|
|
257
|
+
}
|
|
258
|
+
function resolveSingleExprType(singleExpr, builtinVariableRegistry) {
|
|
259
|
+
if (singleExpr instanceof SEVariableRefContext) {
|
|
260
|
+
const identifier = singleExpr.variableRef()?.IDENTIFIER()?.getText();
|
|
261
|
+
return identifier
|
|
262
|
+
? builtinVariableRegistry.getDefinition(`$${identifier}`)?.type
|
|
263
|
+
: undefined;
|
|
264
|
+
}
|
|
265
|
+
if (singleExpr instanceof SEParenthesisContext) {
|
|
266
|
+
return resolveSingleExprType(singleExpr.singleExpr(), builtinVariableRegistry);
|
|
267
|
+
}
|
|
268
|
+
if (singleExpr instanceof SEMethodCallContext) {
|
|
269
|
+
const baseType = resolveSingleExprType(singleExpr.singleExpr(), builtinVariableRegistry);
|
|
270
|
+
const steps = collectMethodCallChainSteps(singleExpr.methodCallChain());
|
|
271
|
+
if (!baseType || !steps) {
|
|
272
|
+
return undefined;
|
|
273
|
+
}
|
|
274
|
+
let currentType = baseType;
|
|
275
|
+
for (const step of steps) {
|
|
276
|
+
if (step.kind === "incomplete") {
|
|
277
|
+
return undefined;
|
|
278
|
+
}
|
|
279
|
+
currentType = resolveCompletedAccessorStep(currentType, step);
|
|
280
|
+
if (!currentType) {
|
|
281
|
+
return undefined;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return currentType;
|
|
285
|
+
}
|
|
286
|
+
return undefined;
|
|
287
|
+
}
|
|
288
|
+
function findReceiverTypeForMemberSlot(node, startTokenIndex, builtinVariableRegistry) {
|
|
289
|
+
if (node instanceof SEMethodCallContext) {
|
|
290
|
+
const steps = collectMethodCallChainSteps(node.methodCallChain());
|
|
291
|
+
if (steps) {
|
|
292
|
+
const slotIndex = steps.findIndex((step) => step.startTokenIndex === startTokenIndex);
|
|
293
|
+
if (slotIndex >= 0) {
|
|
294
|
+
let currentType = resolveSingleExprType(node.singleExpr(), builtinVariableRegistry);
|
|
295
|
+
for (const step of steps.slice(0, slotIndex)) {
|
|
296
|
+
if (!currentType || step.kind === "incomplete") {
|
|
297
|
+
return undefined;
|
|
298
|
+
}
|
|
299
|
+
currentType = resolveCompletedAccessorStep(currentType, step);
|
|
300
|
+
}
|
|
301
|
+
return currentType;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
for (let i = 0; i < node.getChildCount(); i++) {
|
|
306
|
+
const child = node.getChild(i);
|
|
307
|
+
if (child instanceof ParserRuleContext) {
|
|
308
|
+
const receiverType = findReceiverTypeForMemberSlot(child, startTokenIndex, builtinVariableRegistry);
|
|
309
|
+
if (receiverType) {
|
|
310
|
+
return receiverType;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return undefined;
|
|
315
|
+
}
|
|
316
|
+
function isEmptyExpressionInput(input) {
|
|
317
|
+
return input.trim().length === 0;
|
|
318
|
+
}
|
|
319
|
+
function toFunctionInsertText(name) {
|
|
320
|
+
return `${name}()`;
|
|
321
|
+
}
|
|
322
|
+
function buildSignatureLabel(name, argumentLabels) {
|
|
323
|
+
return `${name}(${argumentLabels.join(", ")})`;
|
|
324
|
+
}
|
|
325
|
+
function buildFunctionDocumentation(name, localizer, displayName = name) {
|
|
326
|
+
const func = IfcExpressionFunctions.getFunction(name);
|
|
327
|
+
const documentation = func?.getDocumentation();
|
|
328
|
+
if (!func || !documentation) {
|
|
329
|
+
return undefined;
|
|
330
|
+
}
|
|
331
|
+
const fallback = `${func.getSignatureLabel(displayName)}: ${documentation.fallback}`;
|
|
332
|
+
return localizer ? localizer.t(documentation.key, fallback) : fallback;
|
|
333
|
+
}
|
|
334
|
+
function buildMemberDocumentation(definition, localizer) {
|
|
335
|
+
if (!definition.documentation) {
|
|
336
|
+
return undefined;
|
|
337
|
+
}
|
|
338
|
+
const fallback = definition.kind === "property"
|
|
339
|
+
? `${definition.name}: ${definition.documentation.fallback}`
|
|
340
|
+
: `${buildSignatureLabel(definition.name, (definition.argumentDocumentation ?? []).map((argument, index) => argument.label.fallback ?? `arg${index}`))}: ${definition.documentation.fallback}`;
|
|
341
|
+
return localizer
|
|
342
|
+
? localizer.t(definition.documentation.key, fallback)
|
|
343
|
+
: fallback;
|
|
344
|
+
}
|
|
345
|
+
function buildRootDocumentation(name, documentation, localizer) {
|
|
346
|
+
const key = documentation?.key ?? `builtin.${name}.summary`;
|
|
347
|
+
const fallback = documentation?.fallback ??
|
|
348
|
+
`${name}: built-in value from the evaluation context`;
|
|
349
|
+
return localizer ? localizer.t(key, fallback) : fallback;
|
|
350
|
+
}
|
|
351
|
+
function findActiveCallFrame(tokens, cursorOffset) {
|
|
352
|
+
const stack = [];
|
|
353
|
+
let previousSignificantToken;
|
|
354
|
+
for (const token of tokens) {
|
|
355
|
+
if (token.type === Token.EOF || token.start >= cursorOffset) {
|
|
356
|
+
break;
|
|
357
|
+
}
|
|
358
|
+
if (token.type === IfcExpressionParser.WS ||
|
|
359
|
+
token.type === IfcExpressionParser.NEWLINE) {
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
if (token.type === IfcExpressionParser.T__1) {
|
|
363
|
+
stack.push(previousSignificantToken?.type === IfcExpressionParser.IDENTIFIER
|
|
364
|
+
? {
|
|
365
|
+
kind: "function",
|
|
366
|
+
name: previousSignificantToken.text ?? undefined,
|
|
367
|
+
argumentIndex: 0,
|
|
368
|
+
startTokenIndex: previousSignificantToken.tokenIndex,
|
|
369
|
+
}
|
|
370
|
+
: { kind: "group", argumentIndex: 0 });
|
|
371
|
+
}
|
|
372
|
+
else if (token.type === IfcExpressionParser.T__10) {
|
|
373
|
+
stack.push({ kind: "array", argumentIndex: 0 });
|
|
374
|
+
}
|
|
375
|
+
else if (token.type === IfcExpressionParser.T__2 ||
|
|
376
|
+
token.type === IfcExpressionParser.T__11) {
|
|
377
|
+
stack.pop();
|
|
378
|
+
}
|
|
379
|
+
else if (token.type === IfcExpressionParser.T__9) {
|
|
380
|
+
const currentFrame = stack[stack.length - 1];
|
|
381
|
+
if (currentFrame?.kind === "function") {
|
|
382
|
+
currentFrame.argumentIndex += 1;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
previousSignificantToken = token;
|
|
386
|
+
}
|
|
387
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
388
|
+
if (stack[i].kind === "function") {
|
|
389
|
+
return stack[i];
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
return undefined;
|
|
393
|
+
}
|
|
394
|
+
function buildMemberSignatureLabel(definition) {
|
|
395
|
+
return buildSignatureLabel(definition.name, (definition.argumentDocumentation ?? []).map((argument, index) => argument.label.fallback ?? `arg${index}`));
|
|
396
|
+
}
|
|
397
|
+
function buildActiveMemberHelp(parseTree, builtinVariableRegistry, activeFrame, localizer) {
|
|
398
|
+
if (activeFrame.startTokenIndex === undefined || !activeFrame.name) {
|
|
399
|
+
return undefined;
|
|
400
|
+
}
|
|
401
|
+
const receiverType = findReceiverTypeForMemberSlot(parseTree, activeFrame.startTokenIndex, builtinVariableRegistry);
|
|
402
|
+
if (!(receiverType instanceof ContextObjectType)) {
|
|
403
|
+
return undefined;
|
|
404
|
+
}
|
|
405
|
+
const memberDefinition = receiverType.getMemberDefinition(activeFrame.name);
|
|
406
|
+
if (memberDefinition?.kind !== "function" ||
|
|
407
|
+
!memberDefinition.documentation) {
|
|
408
|
+
return undefined;
|
|
409
|
+
}
|
|
410
|
+
const label = buildMemberSignatureLabel(memberDefinition);
|
|
411
|
+
const fallback = memberDefinition.documentation.fallback.startsWith(`${label}: `)
|
|
412
|
+
? memberDefinition.documentation.fallback
|
|
413
|
+
: `${label}: ${memberDefinition.documentation.fallback}`;
|
|
414
|
+
const activeArgument = memberDefinition.argumentDocumentation?.[activeFrame.argumentIndex];
|
|
415
|
+
return {
|
|
416
|
+
label,
|
|
417
|
+
documentation: localizer
|
|
418
|
+
? localizer.t(memberDefinition.documentation.key, fallback)
|
|
419
|
+
: fallback,
|
|
420
|
+
activeParameterIndex: activeFrame.argumentIndex,
|
|
421
|
+
activeParameterLabel: activeArgument
|
|
422
|
+
? resolveLocalizedText(activeArgument.label, localizer) ??
|
|
423
|
+
activeArgument.label.fallback
|
|
424
|
+
: undefined,
|
|
425
|
+
activeParameterDocumentation: activeArgument
|
|
426
|
+
? resolveLocalizedText(activeArgument.documentation, localizer)
|
|
427
|
+
: undefined,
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
function buildActiveHelp(parseTree, builtinVariableRegistry, tokens, cursorOffset, localizer) {
|
|
431
|
+
const activeFrame = findActiveCallFrame(tokens, cursorOffset);
|
|
432
|
+
if (!activeFrame?.name) {
|
|
433
|
+
return undefined;
|
|
434
|
+
}
|
|
435
|
+
const memberHelp = buildActiveMemberHelp(parseTree, builtinVariableRegistry, activeFrame, localizer);
|
|
436
|
+
if (memberHelp) {
|
|
437
|
+
return memberHelp;
|
|
438
|
+
}
|
|
439
|
+
const func = IfcExpressionFunctions.getFunction(activeFrame.name);
|
|
440
|
+
const documentation = func?.getDocumentation();
|
|
441
|
+
if (!func || !documentation) {
|
|
442
|
+
return undefined;
|
|
443
|
+
}
|
|
444
|
+
const activeArgument = func.getFormalArguments()[activeFrame.argumentIndex];
|
|
445
|
+
const label = func.getSignatureLabel(activeFrame.name);
|
|
446
|
+
const fallback = `${label}: ${documentation.fallback}`;
|
|
447
|
+
return {
|
|
448
|
+
label,
|
|
449
|
+
documentation: localizer
|
|
450
|
+
? localizer.t(documentation.key, fallback)
|
|
451
|
+
: fallback,
|
|
452
|
+
activeParameterIndex: activeFrame.argumentIndex,
|
|
453
|
+
activeParameterLabel: activeArgument
|
|
454
|
+
? resolveLocalizedText(activeArgument.displayLabel, localizer) ??
|
|
455
|
+
activeArgument.displayLabel?.fallback ??
|
|
456
|
+
activeArgument.name
|
|
457
|
+
: undefined,
|
|
458
|
+
activeParameterDocumentation: activeArgument
|
|
459
|
+
? resolveLocalizedText(activeArgument.documentation, localizer)
|
|
460
|
+
: undefined,
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
function toFunctionItem(name, localizer, label = name) {
|
|
464
|
+
const insertText = toFunctionInsertText(label);
|
|
465
|
+
return {
|
|
466
|
+
kind: "builtinFunction",
|
|
467
|
+
label,
|
|
468
|
+
insertText,
|
|
469
|
+
cursorOffset: insertText.length - 1,
|
|
470
|
+
documentation: buildFunctionDocumentation(name, localizer, label),
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
function getPreferredMethodLabel(name) {
|
|
474
|
+
return preferredMethodLabels.get(name) ?? name;
|
|
475
|
+
}
|
|
476
|
+
function isApplicablePrimitiveMethodFunction(name, receiverType) {
|
|
477
|
+
if (unsupportedPrimitiveMethodFunctionNames.has(name)) {
|
|
478
|
+
return false;
|
|
479
|
+
}
|
|
480
|
+
const func = IfcExpressionFunctions.getFunction(name);
|
|
481
|
+
const firstArgument = func?.getFormalArguments()[0];
|
|
482
|
+
if (!func || !firstArgument) {
|
|
483
|
+
return false;
|
|
484
|
+
}
|
|
485
|
+
const firstArgumentType = firstArgument.getType();
|
|
486
|
+
return (firstArgumentType.isAssignableFrom(receiverType) ||
|
|
487
|
+
firstArgumentType.overlapsWith(receiverType));
|
|
488
|
+
}
|
|
489
|
+
function getPrimitiveMethodItems(receiverType, localizer) {
|
|
490
|
+
return IfcExpressionFunctions.getBuiltinFunctionNames()
|
|
491
|
+
.filter((name) => isApplicablePrimitiveMethodFunction(name, receiverType))
|
|
492
|
+
.map((name) => toFunctionItem(name, localizer, getPreferredMethodLabel(name)));
|
|
493
|
+
}
|
|
494
|
+
function toBuiltinRootItem(name, builtinVariableRegistry, localizer) {
|
|
495
|
+
const normalizedName = name.startsWith("$") ? name : `${name}`;
|
|
496
|
+
const definition = builtinVariableRegistry.getDefinition(normalizedName);
|
|
497
|
+
if (!definition) {
|
|
498
|
+
return undefined;
|
|
499
|
+
}
|
|
500
|
+
return {
|
|
501
|
+
kind: "builtinRoot",
|
|
502
|
+
label: toBuiltinLabel(definition.name),
|
|
503
|
+
documentation: buildRootDocumentation(definition.name, definition.documentation, localizer),
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
function toEmptyExpressionStarterItem(name, builtinVariableRegistry, localizer) {
|
|
507
|
+
if (name.startsWith("$")) {
|
|
508
|
+
return toBuiltinRootItem(name, builtinVariableRegistry, localizer);
|
|
509
|
+
}
|
|
510
|
+
return IfcExpressionFunctions.getFunction(name)
|
|
511
|
+
? toFunctionItem(name, localizer)
|
|
512
|
+
: undefined;
|
|
513
|
+
}
|
|
514
|
+
function getEmptyExpressionStarterItems(builtinVariableRegistry, localizer, starterNames = [
|
|
515
|
+
...builtinVariableRegistry
|
|
516
|
+
.getDefinitions()
|
|
517
|
+
.map((definition) => toBuiltinLabel(definition.name)),
|
|
518
|
+
...emptyExpressionStarterFunctionNames,
|
|
519
|
+
]) {
|
|
520
|
+
return starterNames
|
|
521
|
+
.map((name) => toEmptyExpressionStarterItem(name, builtinVariableRegistry, localizer))
|
|
522
|
+
.filter((item) => item !== undefined);
|
|
523
|
+
}
|
|
524
|
+
function toMemberItem(definition, localizer) {
|
|
525
|
+
if (definition.kind === "property") {
|
|
526
|
+
return {
|
|
527
|
+
kind: "builtinMemberProperty",
|
|
528
|
+
label: definition.name,
|
|
529
|
+
returnTypeName: toCompletionTypeName(definition.valueType),
|
|
530
|
+
chainable: isChainableType(definition.valueType),
|
|
531
|
+
documentation: buildMemberDocumentation(definition, localizer),
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
const insertText = toFunctionInsertText(definition.name);
|
|
535
|
+
return {
|
|
536
|
+
kind: "builtinMemberFunction",
|
|
537
|
+
label: definition.name,
|
|
538
|
+
insertText,
|
|
539
|
+
cursorOffset: insertText.length - 1,
|
|
540
|
+
argumentTypeNames: definition.argumentTypes.map((type) => type.getName()),
|
|
541
|
+
returnTypeName: toCompletionTypeName(definition.returnType),
|
|
542
|
+
chainable: isChainableType(definition.returnType),
|
|
543
|
+
documentation: buildMemberDocumentation(definition, localizer),
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
function collectRuleCandidates(parser, caretTokenIndex, parseTree) {
|
|
547
|
+
const completionCore = new CodeCompletionCore(parser);
|
|
548
|
+
completionCore.preferredRules = new Set([
|
|
549
|
+
IfcExpressionParser.RULE_variableRef,
|
|
550
|
+
IfcExpressionParser.RULE_methodAccessor,
|
|
551
|
+
]);
|
|
552
|
+
return completionCore.collectCandidates(caretTokenIndex, parseTree);
|
|
553
|
+
}
|
|
554
|
+
function getMemberRuleCandidate(ruleCandidates) {
|
|
555
|
+
return ruleCandidates.get(IfcExpressionParser.RULE_methodAccessor);
|
|
556
|
+
}
|
|
557
|
+
function hasBuiltinRootRuleCandidate(ruleCandidates) {
|
|
558
|
+
return ruleCandidates.has(IfcExpressionParser.RULE_variableRef);
|
|
559
|
+
}
|
|
560
|
+
function hasIdentifierTokenCandidate(tokenCandidates) {
|
|
561
|
+
return tokenCandidates.has(IfcExpressionParser.IDENTIFIER);
|
|
562
|
+
}
|
|
563
|
+
export class IfcExpressionAutocomplete {
|
|
564
|
+
static complete(input, cursorOffset, options = {}) {
|
|
565
|
+
const builtinVariableRegistry = options.builtinVariableRegistry ??
|
|
566
|
+
BuiltinVariableRegistry.getDefaultRegistry();
|
|
567
|
+
if (isEmptyExpressionInput(input)) {
|
|
568
|
+
return {
|
|
569
|
+
items: getEmptyExpressionStarterItems(builtinVariableRegistry, options.localizer, options.emptyExpressionStarters),
|
|
570
|
+
replaceFrom: 0,
|
|
571
|
+
replaceTo: input.length,
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
const parsed = parseAutocompleteInput(input, cursorOffset);
|
|
575
|
+
const candidates = collectRuleCandidates(parsed.parser, parsed.caretTokenIndex, parsed.parseTree);
|
|
576
|
+
const ruleCandidates = candidates.rules;
|
|
577
|
+
const activeHelp = buildActiveHelp(parsed.parseTree, builtinVariableRegistry, parsed.tokens, cursorOffset, options.localizer);
|
|
578
|
+
const memberCandidate = getMemberRuleCandidate(ruleCandidates);
|
|
579
|
+
if (memberCandidate) {
|
|
580
|
+
const range = findMemberReplaceRange(input, cursorOffset);
|
|
581
|
+
if (!range) {
|
|
582
|
+
return {
|
|
583
|
+
items: [],
|
|
584
|
+
replaceFrom: cursorOffset,
|
|
585
|
+
replaceTo: cursorOffset,
|
|
586
|
+
activeHelp,
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
const receiverType = findReceiverTypeForMemberSlot(parsed.parseTree, memberCandidate.startTokenIndex, builtinVariableRegistry);
|
|
590
|
+
const typedPrefix = normalizeForMatch(input.slice(range.from, range.to));
|
|
591
|
+
const items = (receiverType instanceof ContextObjectType
|
|
592
|
+
? receiverType
|
|
593
|
+
.getMemberDefinitions()
|
|
594
|
+
.map((definition) => toMemberItem(definition, options.localizer))
|
|
595
|
+
: receiverType
|
|
596
|
+
? getPrimitiveMethodItems(receiverType, options.localizer)
|
|
597
|
+
: [])
|
|
598
|
+
.filter((item) => normalizeForMatch(item.label).startsWith(typedPrefix))
|
|
599
|
+
.sort((left, right) => left.label.localeCompare(right.label));
|
|
600
|
+
return {
|
|
601
|
+
items,
|
|
602
|
+
replaceFrom: range.from,
|
|
603
|
+
replaceTo: range.to,
|
|
604
|
+
activeHelp,
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
const functionRange = findFunctionReplaceRange(input, cursorOffset);
|
|
608
|
+
if (functionRange && hasIdentifierTokenCandidate(candidates.tokens)) {
|
|
609
|
+
const typedPrefix = normalizeForMatch(input.slice(functionRange.from, functionRange.to));
|
|
610
|
+
const items = IfcExpressionFunctions.getBuiltinFunctionNames()
|
|
611
|
+
.map((name) => toFunctionItem(name, options.localizer))
|
|
612
|
+
.filter((item) => normalizeForMatch(item.label).startsWith(typedPrefix))
|
|
613
|
+
.sort((left, right) => left.label.localeCompare(right.label));
|
|
614
|
+
if (items.length > 0) {
|
|
615
|
+
return {
|
|
616
|
+
items,
|
|
617
|
+
replaceFrom: functionRange.from,
|
|
618
|
+
replaceTo: functionRange.to,
|
|
619
|
+
activeHelp,
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
const range = findBuiltinRootReplaceRange(input, cursorOffset);
|
|
624
|
+
if (!range || !hasBuiltinRootRuleCandidate(ruleCandidates)) {
|
|
625
|
+
return {
|
|
626
|
+
items: [],
|
|
627
|
+
replaceFrom: cursorOffset,
|
|
628
|
+
replaceTo: cursorOffset,
|
|
629
|
+
activeHelp,
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
const typedPrefix = normalizeForMatch(input.slice(range.from, range.to));
|
|
633
|
+
const items = builtinVariableRegistry
|
|
634
|
+
.getDefinitions()
|
|
635
|
+
.map((definition) => ({
|
|
636
|
+
kind: "builtinRoot",
|
|
637
|
+
label: toBuiltinLabel(definition.name),
|
|
638
|
+
documentation: buildRootDocumentation(definition.name, definition.documentation, options.localizer),
|
|
639
|
+
}))
|
|
640
|
+
.filter((item) => normalizeForMatch(item.label).startsWith(typedPrefix))
|
|
641
|
+
.sort((left, right) => left.label.localeCompare(right.label));
|
|
642
|
+
return {
|
|
643
|
+
items,
|
|
644
|
+
replaceFrom: range.from,
|
|
645
|
+
replaceTo: range.to,
|
|
646
|
+
activeHelp,
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
//# sourceMappingURL=IfcExpressionAutocomplete.js.map
|