@player-tools/typescript-expression-plugin 0.4.2-next.1 → 0.5.0-next.0
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/dist/cjs/index.cjs +389 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/{index.esm.js → index.legacy-esm.js} +103 -115
- package/dist/index.mjs +358 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +25 -28
- package/src/__tests__/service.test.ts +185 -0
- package/src/index.ts +5 -5
- package/src/logger.ts +2 -2
- package/src/service.ts +18 -18
- package/src/transforms.ts +7 -7
- package/src/utils.ts +9 -9
- package/src/virtual-service-host.ts +4 -4
- package/{dist → types}/index.d.ts +3 -4
- package/types/logger.d.ts +8 -0
- package/types/service.d.ts +31 -0
- package/types/transforms.d.ts +2 -0
- package/types/utils.d.ts +14 -0
- package/types/virtual-service-host.d.ts +20 -0
- package/dist/index.cjs.js +0 -392
package/src/logger.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Logger } from
|
|
2
|
-
import
|
|
1
|
+
import type { Logger } from "typescript-template-language-service-decorator";
|
|
2
|
+
import ts from "typescript/lib/tsserverlibrary";
|
|
3
3
|
|
|
4
4
|
export class LSPLogger implements Logger {
|
|
5
5
|
private readonly info: ts.server.PluginCreateInfo;
|
package/src/service.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import
|
|
1
|
+
import ts from "typescript/lib/tsserverlibrary";
|
|
2
2
|
import type {
|
|
3
3
|
TemplateLanguageService,
|
|
4
4
|
TemplateContext,
|
|
5
5
|
Logger,
|
|
6
|
-
} from
|
|
7
|
-
import type { FunctionType, TSManifest, NodeType } from
|
|
8
|
-
import { createTSDocString } from
|
|
9
|
-
import { XLRSDK } from
|
|
10
|
-
import type { ExpressionNode } from
|
|
11
|
-
import { parseExpression } from
|
|
6
|
+
} from "typescript-template-language-service-decorator";
|
|
7
|
+
import type { FunctionType, TSManifest, NodeType } from "@player-tools/xlr";
|
|
8
|
+
import { createTSDocString } from "@player-tools/xlr-utils";
|
|
9
|
+
import { XLRSDK } from "@player-tools/xlr-sdk";
|
|
10
|
+
import type { ExpressionNode } from "@player-ui/player";
|
|
11
|
+
import { parseExpression } from "@player-ui/player";
|
|
12
12
|
import {
|
|
13
13
|
getTokenAtPosition,
|
|
14
14
|
toTSLocation,
|
|
15
15
|
convertExprToJSONNode,
|
|
16
|
-
} from
|
|
17
|
-
import { toFunction } from
|
|
16
|
+
} from "./utils";
|
|
17
|
+
import { toFunction } from "./transforms";
|
|
18
18
|
|
|
19
19
|
interface ExpressionEntry {
|
|
20
20
|
/**
|
|
@@ -86,8 +86,8 @@ export class ExpressionLanguageService implements TemplateLanguageService {
|
|
|
86
86
|
);
|
|
87
87
|
|
|
88
88
|
if (
|
|
89
|
-
type.type ===
|
|
90
|
-
typeInfo?.capability ===
|
|
89
|
+
type.type === "function" &&
|
|
90
|
+
typeInfo?.capability === "Expressions" &&
|
|
91
91
|
source
|
|
92
92
|
) {
|
|
93
93
|
expressions.set(type.name, {
|
|
@@ -134,7 +134,7 @@ export class ExpressionLanguageService implements TemplateLanguageService {
|
|
|
134
134
|
const parsed = parseExpression(line, { strict: false });
|
|
135
135
|
const token = getTokenAtPosition(parsed, position);
|
|
136
136
|
|
|
137
|
-
if (token?.type ===
|
|
137
|
+
if (token?.type === "Compound" && token.error) {
|
|
138
138
|
// We hit the end of the expression, and it's expecting more
|
|
139
139
|
// so provide all the completions
|
|
140
140
|
this._expressions.forEach((exp) => {
|
|
@@ -150,7 +150,7 @@ export class ExpressionLanguageService implements TemplateLanguageService {
|
|
|
150
150
|
return completionInfo;
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
if (token?.type ===
|
|
153
|
+
if (token?.type === "Identifier") {
|
|
154
154
|
// get the relevant start of the identifier
|
|
155
155
|
const start = token.location?.start ?? { character: 0 };
|
|
156
156
|
const wordFromStart = line.slice(start.character, position.character);
|
|
@@ -186,8 +186,8 @@ export class ExpressionLanguageService implements TemplateLanguageService {
|
|
|
186
186
|
|
|
187
187
|
documentation: [
|
|
188
188
|
{
|
|
189
|
-
kind:
|
|
190
|
-
text: expression?.type.description ??
|
|
189
|
+
kind: "text",
|
|
190
|
+
text: expression?.type.description ?? "",
|
|
191
191
|
},
|
|
192
192
|
],
|
|
193
193
|
displayParts: expression ? createTSDocString(expression.type) : [],
|
|
@@ -203,7 +203,7 @@ export class ExpressionLanguageService implements TemplateLanguageService {
|
|
|
203
203
|
const parsed = parseExpression(context.text, { strict: false });
|
|
204
204
|
const token = getTokenAtPosition(parsed, position);
|
|
205
205
|
|
|
206
|
-
if (token?.type ===
|
|
206
|
+
if (token?.type === "Identifier") {
|
|
207
207
|
const expression = this._expressions.get(token.name);
|
|
208
208
|
|
|
209
209
|
if (expression) {
|
|
@@ -254,13 +254,13 @@ export class ExpressionLanguageService implements TemplateLanguageService {
|
|
|
254
254
|
): ts.Diagnostic[] {
|
|
255
255
|
const diags: ts.Diagnostic[] = [];
|
|
256
256
|
|
|
257
|
-
if (node.type ===
|
|
257
|
+
if (node.type === "Compound") {
|
|
258
258
|
node.body.forEach((n) => {
|
|
259
259
|
diags.push(...this.getDiagnosticsForNode(context, n));
|
|
260
260
|
});
|
|
261
261
|
}
|
|
262
262
|
|
|
263
|
-
if (node.type ===
|
|
263
|
+
if (node.type === "CallExpression") {
|
|
264
264
|
// Check that the expression is valid
|
|
265
265
|
const exprName = node.callTarget.name;
|
|
266
266
|
const expression = this._expressions.get(exprName);
|
package/src/transforms.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import type { FunctionType, FunctionTypeParameters } from
|
|
2
|
-
import { simpleTransformGenerator } from
|
|
1
|
+
import type { FunctionType, FunctionTypeParameters } from "@player-tools/xlr";
|
|
2
|
+
import { simpleTransformGenerator } from "@player-tools/xlr-sdk";
|
|
3
3
|
|
|
4
4
|
export const toFunction = simpleTransformGenerator(
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
"ref",
|
|
6
|
+
"Expressions",
|
|
7
7
|
(exp) => {
|
|
8
|
-
if (!exp.genericArguments || exp.ref !==
|
|
8
|
+
if (!exp.genericArguments || exp.ref !== "ExpressionHandler") {
|
|
9
9
|
return exp;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
const [args, returnType] = exp.genericArguments;
|
|
13
13
|
|
|
14
14
|
const parameters: Array<FunctionTypeParameters> = (
|
|
15
|
-
args.type ===
|
|
15
|
+
args.type === "tuple" ? args.elementTypes : []
|
|
16
16
|
).map((elementType, index) => {
|
|
17
17
|
return {
|
|
18
18
|
name:
|
|
@@ -36,7 +36,7 @@ export const toFunction = simpleTransformGenerator(
|
|
|
36
36
|
|
|
37
37
|
return {
|
|
38
38
|
...exp,
|
|
39
|
-
type:
|
|
39
|
+
type: "function",
|
|
40
40
|
parameters,
|
|
41
41
|
returnType,
|
|
42
42
|
} as FunctionType as any;
|
package/src/utils.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Position } from
|
|
2
|
-
import type { ExpressionNode, NodeLocation } from
|
|
3
|
-
import { parseTree } from
|
|
4
|
-
import type { Node } from
|
|
1
|
+
import type { Position } from "vscode-languageserver-types";
|
|
2
|
+
import type { ExpressionNode, NodeLocation } from "@player-ui/player";
|
|
3
|
+
import { parseTree } from "jsonc-parser";
|
|
4
|
+
import type { Node } from "jsonc-parser";
|
|
5
5
|
|
|
6
6
|
/** Check if the vscode position overlaps with the expression location */
|
|
7
7
|
export function isInRange(position: Position, location: NodeLocation) {
|
|
@@ -16,7 +16,7 @@ export function getTokenAtPosition(
|
|
|
16
16
|
node: ExpressionNode,
|
|
17
17
|
position: Position
|
|
18
18
|
): ExpressionNode | undefined {
|
|
19
|
-
if (node.type ===
|
|
19
|
+
if (node.type === "CallExpression") {
|
|
20
20
|
const anyArgs = node.args.find((arg) => {
|
|
21
21
|
return getTokenAtPosition(arg, position);
|
|
22
22
|
});
|
|
@@ -31,7 +31,7 @@ export function getTokenAtPosition(
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
if (node.type ===
|
|
34
|
+
if (node.type === "Assignment") {
|
|
35
35
|
const asTarget =
|
|
36
36
|
getTokenAtPosition(node.left, position) ??
|
|
37
37
|
getTokenAtPosition(node.right, position);
|
|
@@ -67,14 +67,14 @@ export function toTSLocation(node: ExpressionNode): ts.TextSpan {
|
|
|
67
67
|
export function convertExprToValue(exprNode: ExpressionNode): any {
|
|
68
68
|
let val;
|
|
69
69
|
|
|
70
|
-
if (exprNode.type ===
|
|
70
|
+
if (exprNode.type === "Literal") {
|
|
71
71
|
val = exprNode.value;
|
|
72
|
-
} else if (exprNode.type ===
|
|
72
|
+
} else if (exprNode.type === "Object") {
|
|
73
73
|
val = {};
|
|
74
74
|
exprNode.attributes.forEach((prop) => {
|
|
75
75
|
val[convertExprToValue(prop.key)] = convertExprToValue(prop.value);
|
|
76
76
|
});
|
|
77
|
-
} else if (exprNode.type ===
|
|
77
|
+
} else if (exprNode.type === "ArrayExpression") {
|
|
78
78
|
val = exprNode.elements.map(convertExprToValue);
|
|
79
79
|
}
|
|
80
80
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import ts from "typescript/lib/tsserverlibrary";
|
|
2
2
|
|
|
3
3
|
export default class VirtualServiceHost implements ts.LanguageServiceHost {
|
|
4
4
|
private readonly files = new Map<string, string>();
|
|
@@ -36,7 +36,7 @@ export default class VirtualServiceHost implements ts.LanguageServiceHost {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
getScriptVersion() {
|
|
39
|
-
return
|
|
39
|
+
return "0";
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
getScriptSnapshot(fileName: string) {
|
|
@@ -55,13 +55,13 @@ export default class VirtualServiceHost implements ts.LanguageServiceHost {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
fileExists(path: string): boolean {
|
|
58
|
-
return path.includes(
|
|
58
|
+
return path.includes("node_modules")
|
|
59
59
|
? this.typescript.sys.fileExists(path)
|
|
60
60
|
: this.files.has(path);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
readFile(path: string, encoding?: string | undefined): string | undefined {
|
|
64
|
-
return path.includes(
|
|
64
|
+
return path.includes("node_modules")
|
|
65
65
|
? this.typescript.sys.readFile(path, encoding)
|
|
66
66
|
: this.files.get(path);
|
|
67
67
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import ts from "typescript/lib/tsserverlibrary";
|
|
3
2
|
interface InitParams {
|
|
4
3
|
typescript: typeof ts;
|
|
5
4
|
}
|
|
6
5
|
declare function init(mod: InitParams): ts.server.PluginModule;
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
export default init;
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Logger } from "typescript-template-language-service-decorator";
|
|
2
|
+
import ts from "typescript/lib/tsserverlibrary";
|
|
3
|
+
export declare class LSPLogger implements Logger {
|
|
4
|
+
private readonly info;
|
|
5
|
+
constructor(info: ts.server.PluginCreateInfo);
|
|
6
|
+
log(msg: string): void;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import ts from "typescript/lib/tsserverlibrary";
|
|
2
|
+
import type { TemplateLanguageService, TemplateContext, Logger } from "typescript-template-language-service-decorator";
|
|
3
|
+
import type { TSManifest } from "@player-tools/xlr";
|
|
4
|
+
export interface ExpressionLanguageServiceConfig {
|
|
5
|
+
/**
|
|
6
|
+
* The list of XLR enabled plugins to load
|
|
7
|
+
*/
|
|
8
|
+
plugins: Array<TSManifest>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Language server to check Player expression syntax and usage
|
|
12
|
+
*/
|
|
13
|
+
export declare class ExpressionLanguageService implements TemplateLanguageService {
|
|
14
|
+
private logger?;
|
|
15
|
+
private _plugins;
|
|
16
|
+
private _expressions;
|
|
17
|
+
private xlr;
|
|
18
|
+
constructor(options?: {
|
|
19
|
+
logger?: Logger;
|
|
20
|
+
} & Partial<ExpressionLanguageServiceConfig>);
|
|
21
|
+
setConfig(config: ExpressionLanguageServiceConfig): void;
|
|
22
|
+
private reduceExpression;
|
|
23
|
+
getCompletionsAtPosition(context: TemplateContext, position: ts.LineAndCharacter): ts.CompletionInfo;
|
|
24
|
+
getCompletionEntryDetails(context: TemplateContext, position: ts.LineAndCharacter, name: string): ts.CompletionEntryDetails;
|
|
25
|
+
getQuickInfoAtPosition(context: TemplateContext, position: ts.LineAndCharacter): ts.QuickInfo | undefined;
|
|
26
|
+
private checkNode;
|
|
27
|
+
private getDiagnosticsForNode;
|
|
28
|
+
getSemanticDiagnostics(context: TemplateContext): ts.Diagnostic[];
|
|
29
|
+
getSyntacticDiagnostics(context: TemplateContext): ts.Diagnostic[];
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=service.d.ts.map
|
package/types/utils.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Position } from "vscode-languageserver-types";
|
|
2
|
+
import type { ExpressionNode, NodeLocation } from "@player-ui/player";
|
|
3
|
+
import type { Node } from "jsonc-parser";
|
|
4
|
+
/** Check if the vscode position overlaps with the expression location */
|
|
5
|
+
export declare function isInRange(position: Position, location: NodeLocation): boolean;
|
|
6
|
+
/** Find the closest marked token at the given position */
|
|
7
|
+
export declare function getTokenAtPosition(node: ExpressionNode, position: Position): ExpressionNode | undefined;
|
|
8
|
+
/** Get the location info that TS expects for it's diags */
|
|
9
|
+
export declare function toTSLocation(node: ExpressionNode): ts.TextSpan;
|
|
10
|
+
/** ExpressionNode -> raw value */
|
|
11
|
+
export declare function convertExprToValue(exprNode: ExpressionNode): any;
|
|
12
|
+
/** ExpressionNode -> JSONC Node */
|
|
13
|
+
export declare function convertExprToJSONNode(exprNode: ExpressionNode): Node | undefined;
|
|
14
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import ts from "typescript/lib/tsserverlibrary";
|
|
2
|
+
export default class VirtualServiceHost implements ts.LanguageServiceHost {
|
|
3
|
+
private readonly files;
|
|
4
|
+
private readonly typescript;
|
|
5
|
+
private readonly compilerOptions;
|
|
6
|
+
private readonly workspacePath;
|
|
7
|
+
constructor(typescript: typeof ts, compilerOptions: ts.CompilerOptions, workspacePath: string);
|
|
8
|
+
withFile<T>(fileName: string, content: string, callback: () => T): T;
|
|
9
|
+
getCompilationSettings(): ts.CompilerOptions;
|
|
10
|
+
getScriptFileNames(): string[];
|
|
11
|
+
getScriptKind(): ts.ScriptKind;
|
|
12
|
+
getScriptVersion(): string;
|
|
13
|
+
getScriptSnapshot(fileName: string): ts.IScriptSnapshot | undefined;
|
|
14
|
+
getCurrentDirectory(): string;
|
|
15
|
+
getDefaultLibFileName(options: ts.CompilerOptions): string;
|
|
16
|
+
fileExists(path: string): boolean;
|
|
17
|
+
readFile(path: string, encoding?: string | undefined): string | undefined;
|
|
18
|
+
useCaseSensitiveFileNames(): boolean;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=virtual-service-host.d.ts.map
|