@player-tools/typescript-expression-plugin 0.5.2-next.1 → 0.5.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/typescript-expression-plugin/src/index.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/typescript-expression-plugin/src/service.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/typescript-expression-plugin/src/utils.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/typescript-expression-plugin/src/transforms.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/typescript-expression-plugin/src/logger.ts"],"sourcesContent":["import ts from \"typescript/lib/tsserverlibrary\";\nimport { decorateWithTemplateLanguageService } from \"typescript-template-language-service-decorator\";\nimport { ExpressionLanguageService } from \"./service\";\nimport { LSPLogger } from \"./logger\";\n\ninterface InitParams {\n typescript: typeof ts;\n}\nclass Plugin implements ts.server.PluginModule {\n private readonly initOptions: InitParams;\n private logger?: LSPLogger;\n private templateService?: ExpressionLanguageService;\n\n constructor(initOptions: InitParams) {\n this.initOptions = initOptions;\n }\n\n create(info: ts.server.PluginCreateInfo): ts.LanguageService {\n const logger = new LSPLogger(info);\n this.logger = logger;\n\n const templateService = new ExpressionLanguageService({ logger });\n this.templateService = templateService;\n\n return decorateWithTemplateLanguageService(\n this.initOptions.typescript,\n info.languageService,\n info.project,\n templateService,\n {\n tags: [\"e\", \"expr\", \"expression\"],\n enableForStringWithSubstitutions: true,\n },\n { logger }\n );\n }\n\n onConfigurationChanged(config: any) {\n this.templateService?.setConfig(config);\n }\n}\n\nfunction init(mod: InitParams): ts.server.PluginModule {\n return new Plugin(mod);\n}\n\nexport default init;\n// export = init;\n","import ts from \"typescript/lib/tsserverlibrary\";\nimport type {\n TemplateLanguageService,\n TemplateContext,\n Logger,\n} from \"typescript-template-language-service-decorator\";\nimport type { FunctionType, TSManifest, NodeType } from \"@player-tools/xlr\";\nimport { createTSDocString } from \"@player-tools/xlr-utils\";\nimport { XLRSDK } from \"@player-tools/xlr-sdk\";\nimport type { ExpressionNode } from \"@player-ui/player\";\nimport { parseExpression } from \"@player-ui/player\";\nimport {\n getTokenAtPosition,\n toTSLocation,\n convertExprToJSONNode,\n} from \"./utils\";\nimport { toFunction } from \"./transforms\";\n\ninterface ExpressionEntry {\n /**\n * The name of the expression\n */\n name: string;\n /**\n * The description of the expression\n */\n description?: string;\n /**\n * The XLR type of the expression\n */\n type: FunctionType;\n /**\n * The XLR enabled plugin the expression was sourced from\n */\n source: TSManifest;\n}\n\nexport interface ExpressionLanguageServiceConfig {\n /**\n * The list of XLR enabled plugins to load\n */\n plugins: Array<TSManifest>;\n}\n\n/**\n * Language server to check Player expression syntax and usage\n */\nexport class ExpressionLanguageService implements TemplateLanguageService {\n private logger?: Logger;\n private _plugins: Array<TSManifest> = [];\n private _expressions: Map<string, ExpressionEntry>;\n private xlr: XLRSDK;\n\n constructor(\n options?: { logger?: Logger } & Partial<ExpressionLanguageServiceConfig>\n ) {\n this.logger = options?.logger;\n this._plugins = options?.plugins ?? [];\n this.xlr = new XLRSDK();\n\n this._plugins.forEach((p) => {\n this.xlr.loadDefinitionsFromModule(p, undefined, [toFunction]);\n });\n this._expressions = this.reduceExpression();\n }\n\n setConfig(config: ExpressionLanguageServiceConfig) {\n this._plugins = config.plugins;\n this.xlr = new XLRSDK();\n\n this._plugins.forEach((p) => {\n this.xlr.loadDefinitionsFromModule(p, undefined, [toFunction]);\n });\n this._expressions = this.reduceExpression();\n }\n\n private reduceExpression(): Map<string, ExpressionEntry> {\n // Overlaps in names will be resolved by the last plugin to be loaded\n // So use a map to ensure no duplicates\n const expressions = new Map<string, ExpressionEntry>();\n\n this.xlr.listTypes().forEach((type) => {\n const typeInfo = this.xlr.getTypeInfo(type.name);\n const source = this._plugins.find(\n (value) => value.pluginName === typeInfo?.plugin\n );\n\n if (\n type.type === \"function\" &&\n typeInfo?.capability === \"Expressions\" &&\n source\n ) {\n expressions.set(type.name, {\n name: type.name,\n description: type.description,\n type: type as FunctionType,\n source,\n });\n }\n });\n\n return expressions;\n }\n\n getCompletionsAtPosition(\n context: TemplateContext,\n position: ts.LineAndCharacter\n ): ts.CompletionInfo {\n const completionInfo: ts.CompletionInfo = {\n isGlobalCompletion: false,\n isMemberCompletion: false,\n isNewIdentifierLocation: true,\n entries: [],\n };\n\n if (context.text.length === 0) {\n // This happens for the start of an expression (e``)\n // Provide all the completions in this case\n\n this._expressions.forEach((exp) => {\n completionInfo.entries.push({\n name: exp.name,\n kind: ts.ScriptElementKind.functionElement,\n sortText: exp.name,\n isRecommended: true,\n insertText: `${exp.name}()`,\n });\n });\n\n return completionInfo;\n }\n\n const line = context.text.split(/\\n/g)[position.line];\n const parsed = parseExpression(line, { strict: false });\n const token = getTokenAtPosition(parsed, position);\n\n if (token?.type === \"Compound\" && token.error) {\n // We hit the end of the expression, and it's expecting more\n // so provide all the completions\n this._expressions.forEach((exp) => {\n completionInfo.entries.push({\n name: exp.name,\n kind: ts.ScriptElementKind.functionElement,\n sortText: exp.name,\n isRecommended: true,\n insertText: `${exp.name}()`,\n });\n });\n\n return completionInfo;\n }\n\n if (token?.type === \"Identifier\") {\n // get the relevant start of the identifier\n const start = token.location?.start ?? { character: 0 };\n const wordFromStart = line.slice(start.character, position.character);\n const allCompletions = Array.from(this._expressions.keys()).filter(\n (key) => key.startsWith(wordFromStart)\n );\n\n allCompletions.forEach((c) => {\n completionInfo.entries.push({\n name: c,\n kind: ts.ScriptElementKind.functionElement,\n sortText: c,\n isRecommended: true,\n insertText: `${c}()`,\n });\n });\n }\n\n return completionInfo;\n }\n\n getCompletionEntryDetails(\n context: TemplateContext,\n position: ts.LineAndCharacter,\n name: string\n ): ts.CompletionEntryDetails {\n const expression = this._expressions.get(name);\n\n const completionDetails: ts.CompletionEntryDetails = {\n name,\n kind: ts.ScriptElementKind.functionElement,\n kindModifiers: ts.ScriptElementKindModifier.none,\n\n documentation: [\n {\n kind: \"text\",\n text: expression?.type.description ?? \"\",\n },\n ],\n displayParts: expression ? createTSDocString(expression.type) : [],\n };\n\n return completionDetails;\n }\n\n getQuickInfoAtPosition(\n context: TemplateContext,\n position: ts.LineAndCharacter\n ): ts.QuickInfo | undefined {\n const parsed = parseExpression(context.text, { strict: false });\n const token = getTokenAtPosition(parsed, position);\n\n if (token?.type === \"Identifier\") {\n const expression = this._expressions.get(token.name);\n\n if (expression) {\n const completionDetails = this.getCompletionEntryDetails(\n context,\n position,\n expression.name\n );\n\n return {\n ...completionDetails,\n textSpan: toTSLocation(token),\n };\n }\n }\n\n return undefined;\n }\n\n private checkNode(\n context: TemplateContext,\n node: ExpressionNode,\n xlrType: NodeType\n ): ts.Diagnostic[] {\n const diagnostics: ts.Diagnostic[] = [];\n const asJsonNodeValue = convertExprToJSONNode(node);\n\n if (asJsonNodeValue) {\n const xlrDiags = this.xlr.validateByType(xlrType, asJsonNodeValue);\n\n xlrDiags.forEach((d) => {\n diagnostics.push({\n file: context.node.getSourceFile(),\n ...toTSLocation(node),\n messageText: d.message,\n category: ts.DiagnosticCategory.Error,\n code: 1,\n });\n });\n }\n\n return diagnostics;\n }\n\n private getDiagnosticsForNode(\n context: TemplateContext,\n node: ExpressionNode\n ): ts.Diagnostic[] {\n const diags: ts.Diagnostic[] = [];\n\n if (node.type === \"Compound\") {\n node.body.forEach((n) => {\n diags.push(...this.getDiagnosticsForNode(context, n));\n });\n }\n\n if (node.type === \"CallExpression\") {\n // Check that the expression is valid\n const exprName = node.callTarget.name;\n const expression = this._expressions.get(exprName);\n\n node.args.forEach((n) => {\n diags.push(...this.getDiagnosticsForNode(context, n));\n });\n\n if (expression) {\n // Double check the arguments match what we expect\n const expectedArgs = expression.type.parameters;\n const actualArgs = node.args;\n\n actualArgs.forEach((actualArg, index) => {\n const expectedArg = expectedArgs[index];\n\n if (expectedArg) {\n // Check that the type satisfies the expected type\n diags.push(...this.checkNode(context, actualArg, expectedArg.type));\n }\n });\n\n if (expectedArgs.length > actualArgs.length) {\n const requiredArgs = expectedArgs.filter((a) => !a.optional);\n if (actualArgs.length < requiredArgs.length) {\n diags.push({\n category: ts.DiagnosticCategory.Error,\n code: 1,\n file: context.node.getSourceFile(),\n ...toTSLocation(node.callTarget),\n messageText: `Expected ${requiredArgs.length} argument(s), got ${actualArgs.length}`,\n });\n }\n }\n } else {\n diags.push({\n category: ts.DiagnosticCategory.Error,\n code: 1,\n file: context.node.getSourceFile(),\n ...toTSLocation(node.callTarget),\n messageText: `Unknown expression ${exprName}`,\n });\n }\n }\n\n return diags;\n }\n\n getSemanticDiagnostics(context: TemplateContext): ts.Diagnostic[] {\n // Shortcut any type-checking if we don't have any info about what expressions are registered\n if (this._plugins.length === 0) {\n return [];\n }\n\n const parsed = parseExpression(context.text.trim(), { strict: false });\n return this.getDiagnosticsForNode(context, parsed);\n }\n\n getSyntacticDiagnostics(context: TemplateContext): ts.Diagnostic[] {\n const parsed = parseExpression(context.text.trim(), { strict: false });\n\n if (parsed.error) {\n return [\n {\n category: ts.DiagnosticCategory.Error,\n code: 1,\n file: context.node.getSourceFile(),\n ...toTSLocation(parsed),\n messageText: parsed.error.message,\n },\n ];\n }\n\n return [];\n }\n}\n","import type { Position } from \"vscode-languageserver-types\";\nimport type { ExpressionNode, NodeLocation } from \"@player-ui/player\";\nimport { parseTree } from \"jsonc-parser\";\nimport type { Node } from \"jsonc-parser\";\n\n/** Check if the vscode position overlaps with the expression location */\nexport function isInRange(position: Position, location: NodeLocation) {\n return (\n position.character >= location.start.character &&\n position.character <= location.end.character\n );\n}\n\n/** Find the closest marked token at the given position */\nexport function getTokenAtPosition(\n node: ExpressionNode,\n position: Position\n): ExpressionNode | undefined {\n if (node.type === \"CallExpression\") {\n const anyArgs = node.args.find((arg) => {\n return getTokenAtPosition(arg, position);\n });\n\n if (anyArgs) {\n return anyArgs;\n }\n\n const asTarget = getTokenAtPosition(node.callTarget, position);\n if (asTarget) {\n return asTarget;\n }\n }\n\n if (node.type === \"Assignment\") {\n const asTarget =\n getTokenAtPosition(node.left, position) ??\n getTokenAtPosition(node.right, position);\n if (asTarget) {\n return asTarget;\n }\n }\n\n // Lastly check for yourself\n if (node.location && isInRange(position, node.location)) {\n return node;\n }\n}\n\n/** Get the location info that TS expects for it's diags */\nexport function toTSLocation(node: ExpressionNode): ts.TextSpan {\n const start = node.location?.start.character;\n const end = node.location?.end.character;\n if (start === undefined || end === undefined) {\n return {\n start: 0,\n length: 0,\n };\n }\n\n return {\n start,\n length: end - start,\n };\n}\n\n/** ExpressionNode -> raw value */\nexport function convertExprToValue(exprNode: ExpressionNode): any {\n let val;\n\n if (exprNode.type === \"Literal\") {\n val = exprNode.value;\n } else if (exprNode.type === \"Object\") {\n val = {};\n exprNode.attributes.forEach((prop) => {\n val[convertExprToValue(prop.key)] = convertExprToValue(prop.value);\n });\n } else if (exprNode.type === \"ArrayExpression\") {\n val = exprNode.elements.map(convertExprToValue);\n }\n\n return val;\n}\n\n/** ExpressionNode -> JSONC Node */\nexport function convertExprToJSONNode(\n exprNode: ExpressionNode\n): Node | undefined {\n const val = convertExprToValue(exprNode);\n if (val === undefined) {\n return undefined;\n }\n\n return parseTree(JSON.stringify(val));\n}\n","import type { FunctionType, FunctionTypeParameters } from \"@player-tools/xlr\";\nimport { simpleTransformGenerator } from \"@player-tools/xlr-sdk\";\n\nexport const toFunction = simpleTransformGenerator(\n \"ref\",\n \"Expressions\",\n (exp) => {\n if (!exp.genericArguments || exp.ref !== \"ExpressionHandler\") {\n return exp;\n }\n\n const [args, returnType] = exp.genericArguments;\n\n const parameters: Array<FunctionTypeParameters> = (\n args.type === \"tuple\" ? args.elementTypes : []\n ).map((elementType, index) => {\n return {\n name:\n elementType.name ??\n elementType.type.name ??\n elementType.type.title ??\n `arg_${index}`,\n\n type: {\n name:\n elementType.name ??\n elementType.type.name ??\n elementType.type.title ??\n `arg_${index}`,\n ...elementType.type,\n },\n optional:\n elementType.optional === true ? elementType.optional : undefined,\n };\n });\n\n return {\n ...exp,\n type: \"function\",\n parameters,\n returnType,\n } as FunctionType as any;\n }\n);\n","import type { Logger } from \"typescript-template-language-service-decorator\";\nimport ts from \"typescript/lib/tsserverlibrary\";\n\nexport class LSPLogger implements Logger {\n private readonly info: ts.server.PluginCreateInfo;\n\n constructor(info: ts.server.PluginCreateInfo) {\n this.info = info;\n }\n\n log(msg: string) {\n this.info.project.projectService.logger.info(`[player-expr-lsp] ${msg}`);\n }\n}\n"],"mappings":"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","names":["import_xlr_sdk","ts"]}
1
+ {"version":3,"sources":["../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/typescript-expression-plugin/src/index.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/typescript-expression-plugin/src/service.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/typescript-expression-plugin/src/utils.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/typescript-expression-plugin/src/transforms.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/typescript-expression-plugin/src/logger.ts"],"sourcesContent":["import ts from \"typescript/lib/tsserverlibrary\";\nimport { decorateWithTemplateLanguageService } from \"typescript-template-language-service-decorator\";\nimport { ExpressionLanguageService } from \"./service\";\nimport { LSPLogger } from \"./logger\";\n\ninterface InitParams {\n typescript: typeof ts;\n}\nclass Plugin implements ts.server.PluginModule {\n private readonly initOptions: InitParams;\n private logger?: LSPLogger;\n private templateService?: ExpressionLanguageService;\n\n constructor(initOptions: InitParams) {\n this.initOptions = initOptions;\n }\n\n create(info: ts.server.PluginCreateInfo): ts.LanguageService {\n const logger = new LSPLogger(info);\n this.logger = logger;\n\n const templateService = new ExpressionLanguageService({ logger });\n this.templateService = templateService;\n\n return decorateWithTemplateLanguageService(\n this.initOptions.typescript,\n info.languageService,\n info.project,\n templateService,\n {\n tags: [\"e\", \"expr\", \"expression\"],\n enableForStringWithSubstitutions: true,\n },\n { logger }\n );\n }\n\n onConfigurationChanged(config: any) {\n this.templateService?.setConfig(config);\n }\n}\n\nfunction init(mod: InitParams): ts.server.PluginModule {\n return new Plugin(mod);\n}\n\nexport default init;\n// export = init;\n","import ts from \"typescript/lib/tsserverlibrary\";\nimport type {\n TemplateLanguageService,\n TemplateContext,\n Logger,\n} from \"typescript-template-language-service-decorator\";\nimport type { FunctionType, TSManifest, NodeType } from \"@player-tools/xlr\";\nimport { createTSDocString } from \"@player-tools/xlr-utils\";\nimport { XLRSDK } from \"@player-tools/xlr-sdk\";\nimport type { ExpressionNode } from \"@player-ui/player\";\nimport { parseExpression } from \"@player-ui/player\";\nimport {\n getTokenAtPosition,\n toTSLocation,\n convertExprToJSONNode,\n} from \"./utils\";\nimport { toFunction } from \"./transforms\";\n\ninterface ExpressionEntry {\n /**\n * The name of the expression\n */\n name: string;\n /**\n * The description of the expression\n */\n description?: string;\n /**\n * The XLR type of the expression\n */\n type: FunctionType;\n /**\n * The XLR enabled plugin the expression was sourced from\n */\n source: TSManifest;\n}\n\nexport interface ExpressionLanguageServiceConfig {\n /**\n * The list of XLR enabled plugins to load\n */\n plugins: Array<TSManifest>;\n}\n\n/**\n * Language server to check Player expression syntax and usage\n */\nexport class ExpressionLanguageService implements TemplateLanguageService {\n private logger?: Logger;\n private _plugins: Array<TSManifest> = [];\n private _expressions: Map<string, ExpressionEntry>;\n private xlr: XLRSDK;\n\n constructor(\n options?: { logger?: Logger } & Partial<ExpressionLanguageServiceConfig>\n ) {\n this.logger = options?.logger;\n this._plugins = options?.plugins ?? [];\n this.xlr = new XLRSDK();\n\n this._plugins.forEach((p) => {\n this.xlr.loadDefinitionsFromModule(p, undefined, [toFunction]);\n });\n this._expressions = this.reduceExpression();\n }\n\n setConfig(config: ExpressionLanguageServiceConfig) {\n this._plugins = config.plugins;\n this.xlr = new XLRSDK();\n\n this._plugins.forEach((p) => {\n this.xlr.loadDefinitionsFromModule(p, undefined, [toFunction]);\n });\n this._expressions = this.reduceExpression();\n }\n\n private reduceExpression(): Map<string, ExpressionEntry> {\n // Overlaps in names will be resolved by the last plugin to be loaded\n // So use a map to ensure no duplicates\n const expressions = new Map<string, ExpressionEntry>();\n\n this.xlr.listTypes().forEach((type) => {\n const typeInfo = this.xlr.getTypeInfo(type.name);\n const source = this._plugins.find(\n (value) => value.pluginName === typeInfo?.plugin\n );\n\n if (\n type.type === \"function\" &&\n typeInfo?.capability === \"Expressions\" &&\n source\n ) {\n expressions.set(type.name, {\n name: type.name,\n description: type.description,\n type: type as FunctionType,\n source,\n });\n }\n });\n\n return expressions;\n }\n\n getCompletionsAtPosition(\n context: TemplateContext,\n position: ts.LineAndCharacter\n ): ts.CompletionInfo {\n const completionInfo: ts.CompletionInfo = {\n isGlobalCompletion: false,\n isMemberCompletion: false,\n isNewIdentifierLocation: true,\n entries: [],\n };\n\n if (context.text.length === 0) {\n // This happens for the start of an expression (e``)\n // Provide all the completions in this case\n\n this._expressions.forEach((exp) => {\n completionInfo.entries.push({\n name: exp.name,\n kind: ts.ScriptElementKind.functionElement,\n sortText: exp.name,\n isRecommended: true,\n insertText: `${exp.name}()`,\n });\n });\n\n return completionInfo;\n }\n\n const line = context.text.split(/\\n/g)[position.line];\n const parsed = parseExpression(line, { strict: false });\n const token = getTokenAtPosition(parsed, position);\n\n if (token?.type === \"Compound\" && token.error) {\n // We hit the end of the expression, and it's expecting more\n // so provide all the completions\n this._expressions.forEach((exp) => {\n completionInfo.entries.push({\n name: exp.name,\n kind: ts.ScriptElementKind.functionElement,\n sortText: exp.name,\n isRecommended: true,\n insertText: `${exp.name}()`,\n });\n });\n\n return completionInfo;\n }\n\n if (token?.type === \"Identifier\") {\n // get the relevant start of the identifier\n const start = token.location?.start ?? { character: 0 };\n const wordFromStart = line.slice(start.character, position.character);\n const allCompletions = Array.from(this._expressions.keys()).filter(\n (key) => key.startsWith(wordFromStart)\n );\n\n allCompletions.forEach((c) => {\n completionInfo.entries.push({\n name: c,\n kind: ts.ScriptElementKind.functionElement,\n sortText: c,\n isRecommended: true,\n insertText: `${c}()`,\n });\n });\n }\n\n return completionInfo;\n }\n\n getCompletionEntryDetails(\n context: TemplateContext,\n position: ts.LineAndCharacter,\n name: string\n ): ts.CompletionEntryDetails {\n const expression = this._expressions.get(name);\n\n const completionDetails: ts.CompletionEntryDetails = {\n name,\n kind: ts.ScriptElementKind.functionElement,\n kindModifiers: ts.ScriptElementKindModifier.none,\n\n documentation: [\n {\n kind: \"text\",\n text: expression?.type.description ?? \"\",\n },\n ],\n displayParts: expression ? createTSDocString(expression.type) : [],\n };\n\n return completionDetails;\n }\n\n getQuickInfoAtPosition(\n context: TemplateContext,\n position: ts.LineAndCharacter\n ): ts.QuickInfo | undefined {\n const parsed = parseExpression(context.text, { strict: false });\n const token = getTokenAtPosition(parsed, position);\n\n if (token?.type === \"Identifier\") {\n const expression = this._expressions.get(token.name);\n\n if (expression) {\n const completionDetails = this.getCompletionEntryDetails(\n context,\n position,\n expression.name\n );\n\n return {\n ...completionDetails,\n textSpan: toTSLocation(token),\n };\n }\n }\n\n return undefined;\n }\n\n private checkNode(\n context: TemplateContext,\n node: ExpressionNode,\n xlrType: NodeType\n ): ts.Diagnostic[] {\n const diagnostics: ts.Diagnostic[] = [];\n const asJsonNodeValue = convertExprToJSONNode(node);\n\n if (asJsonNodeValue) {\n const xlrDiags = this.xlr.validateByType(xlrType, asJsonNodeValue);\n\n xlrDiags.forEach((d) => {\n diagnostics.push({\n file: context.node.getSourceFile(),\n ...toTSLocation(node),\n messageText: d.message,\n category: ts.DiagnosticCategory.Error,\n code: 1,\n });\n });\n }\n\n return diagnostics;\n }\n\n private getDiagnosticsForNode(\n context: TemplateContext,\n node: ExpressionNode\n ): ts.Diagnostic[] {\n const diags: ts.Diagnostic[] = [];\n\n if (node.type === \"Compound\") {\n node.body.forEach((n) => {\n diags.push(...this.getDiagnosticsForNode(context, n));\n });\n }\n\n if (node.type === \"CallExpression\") {\n // Check that the expression is valid\n const exprName = node.callTarget.name;\n const expression = this._expressions.get(exprName);\n\n node.args.forEach((n) => {\n diags.push(...this.getDiagnosticsForNode(context, n));\n });\n\n if (expression) {\n // Double check the arguments match what we expect\n const expectedArgs = expression.type.parameters;\n const actualArgs = node.args;\n\n actualArgs.forEach((actualArg, index) => {\n const expectedArg = expectedArgs[index];\n\n if (expectedArg) {\n // Check that the type satisfies the expected type\n diags.push(...this.checkNode(context, actualArg, expectedArg.type));\n }\n });\n\n if (expectedArgs.length > actualArgs.length) {\n const requiredArgs = expectedArgs.filter((a) => !a.optional);\n if (actualArgs.length < requiredArgs.length) {\n diags.push({\n category: ts.DiagnosticCategory.Error,\n code: 1,\n file: context.node.getSourceFile(),\n ...toTSLocation(node.callTarget),\n messageText: `Expected ${requiredArgs.length} argument(s), got ${actualArgs.length}`,\n });\n }\n }\n } else {\n diags.push({\n category: ts.DiagnosticCategory.Error,\n code: 1,\n file: context.node.getSourceFile(),\n ...toTSLocation(node.callTarget),\n messageText: `Unknown expression ${exprName}`,\n });\n }\n }\n\n return diags;\n }\n\n getSemanticDiagnostics(context: TemplateContext): ts.Diagnostic[] {\n // Shortcut any type-checking if we don't have any info about what expressions are registered\n if (this._plugins.length === 0) {\n return [];\n }\n\n const parsed = parseExpression(context.text.trim(), { strict: false });\n return this.getDiagnosticsForNode(context, parsed);\n }\n\n getSyntacticDiagnostics(context: TemplateContext): ts.Diagnostic[] {\n const parsed = parseExpression(context.text.trim(), { strict: false });\n\n if (parsed.error) {\n return [\n {\n category: ts.DiagnosticCategory.Error,\n code: 1,\n file: context.node.getSourceFile(),\n ...toTSLocation(parsed),\n messageText: parsed.error.message,\n },\n ];\n }\n\n return [];\n }\n}\n","import type { TextSpan } from \"typescript\";\nimport type { Position } from \"vscode-languageserver-types\";\nimport type { ExpressionNode, NodeLocation } from \"@player-ui/player\";\nimport { parseTree } from \"jsonc-parser\";\nimport type { Node } from \"jsonc-parser\";\n\n/** Check if the vscode position overlaps with the expression location */\nexport function isInRange(position: Position, location: NodeLocation) {\n return (\n position.character >= location.start.character &&\n position.character <= location.end.character\n );\n}\n\n/** Find the closest marked token at the given position */\nexport function getTokenAtPosition(\n node: ExpressionNode,\n position: Position\n): ExpressionNode | undefined {\n if (node.type === \"CallExpression\") {\n const anyArgs = node.args.find((arg) => {\n return getTokenAtPosition(arg, position);\n });\n\n if (anyArgs) {\n return anyArgs;\n }\n\n const asTarget = getTokenAtPosition(node.callTarget, position);\n if (asTarget) {\n return asTarget;\n }\n }\n\n if (node.type === \"Assignment\") {\n const asTarget =\n getTokenAtPosition(node.left, position) ??\n getTokenAtPosition(node.right, position);\n if (asTarget) {\n return asTarget;\n }\n }\n\n // Lastly check for yourself\n if (node.location && isInRange(position, node.location)) {\n return node;\n }\n}\n\n/** Get the location info that TS expects for it's diags */\nexport function toTSLocation(node: ExpressionNode): TextSpan {\n const start = node.location?.start.character;\n const end = node.location?.end.character;\n if (start === undefined || end === undefined) {\n return {\n start: 0,\n length: 0,\n };\n }\n\n return {\n start,\n length: end - start,\n };\n}\n\n/** ExpressionNode -> raw value */\nexport function convertExprToValue(exprNode: ExpressionNode): any {\n let val;\n\n if (exprNode.type === \"Literal\") {\n val = exprNode.value;\n } else if (exprNode.type === \"Object\") {\n val = {};\n exprNode.attributes.forEach((prop) => {\n val[convertExprToValue(prop.key)] = convertExprToValue(prop.value);\n });\n } else if (exprNode.type === \"ArrayExpression\") {\n val = exprNode.elements.map(convertExprToValue);\n }\n\n return val;\n}\n\n/** ExpressionNode -> JSONC Node */\nexport function convertExprToJSONNode(\n exprNode: ExpressionNode\n): Node | undefined {\n const val = convertExprToValue(exprNode);\n if (val === undefined) {\n return undefined;\n }\n\n return parseTree(JSON.stringify(val));\n}\n","import type { FunctionType, FunctionTypeParameters } from \"@player-tools/xlr\";\nimport { simpleTransformGenerator } from \"@player-tools/xlr-sdk\";\n\nexport const toFunction = simpleTransformGenerator(\n \"ref\",\n \"Expressions\",\n (exp) => {\n if (!exp.genericArguments || exp.ref !== \"ExpressionHandler\") {\n return exp;\n }\n\n const [args, returnType] = exp.genericArguments;\n\n const parameters: Array<FunctionTypeParameters> = (\n args.type === \"tuple\" ? args.elementTypes : []\n ).map((elementType, index) => {\n return {\n name:\n elementType.name ??\n elementType.type.name ??\n elementType.type.title ??\n `arg_${index}`,\n\n type: {\n name:\n elementType.name ??\n elementType.type.name ??\n elementType.type.title ??\n `arg_${index}`,\n ...elementType.type,\n },\n optional:\n elementType.optional === true ? elementType.optional : undefined,\n };\n });\n\n return {\n ...exp,\n type: \"function\",\n parameters,\n returnType,\n } as FunctionType as any;\n }\n);\n","import type { Logger } from \"typescript-template-language-service-decorator\";\nimport ts from \"typescript/lib/tsserverlibrary\";\n\nexport class LSPLogger implements Logger {\n private readonly info: ts.server.PluginCreateInfo;\n\n constructor(info: ts.server.PluginCreateInfo) {\n this.info = info;\n }\n\n log(msg: string) {\n this.info.project.projectService.logger.info(`[player-expr-lsp] ${msg}`);\n }\n}\n"],"mappings":"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","names":["import_xlr_sdk","ts"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/typescript-expression-plugin/src/index.ts","../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/typescript-expression-plugin/src/service.ts","../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/typescript-expression-plugin/src/utils.ts","../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/typescript-expression-plugin/src/transforms.ts","../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/typescript-expression-plugin/src/logger.ts"],"sourcesContent":["import ts from \"typescript/lib/tsserverlibrary\";\nimport { decorateWithTemplateLanguageService } from \"typescript-template-language-service-decorator\";\nimport { ExpressionLanguageService } from \"./service\";\nimport { LSPLogger } from \"./logger\";\n\ninterface InitParams {\n typescript: typeof ts;\n}\nclass Plugin implements ts.server.PluginModule {\n private readonly initOptions: InitParams;\n private logger?: LSPLogger;\n private templateService?: ExpressionLanguageService;\n\n constructor(initOptions: InitParams) {\n this.initOptions = initOptions;\n }\n\n create(info: ts.server.PluginCreateInfo): ts.LanguageService {\n const logger = new LSPLogger(info);\n this.logger = logger;\n\n const templateService = new ExpressionLanguageService({ logger });\n this.templateService = templateService;\n\n return decorateWithTemplateLanguageService(\n this.initOptions.typescript,\n info.languageService,\n info.project,\n templateService,\n {\n tags: [\"e\", \"expr\", \"expression\"],\n enableForStringWithSubstitutions: true,\n },\n { logger }\n );\n }\n\n onConfigurationChanged(config: any) {\n this.templateService?.setConfig(config);\n }\n}\n\nfunction init(mod: InitParams): ts.server.PluginModule {\n return new Plugin(mod);\n}\n\nexport default init;\n// export = init;\n","import ts from \"typescript/lib/tsserverlibrary\";\nimport type {\n TemplateLanguageService,\n TemplateContext,\n Logger,\n} from \"typescript-template-language-service-decorator\";\nimport type { FunctionType, TSManifest, NodeType } from \"@player-tools/xlr\";\nimport { createTSDocString } from \"@player-tools/xlr-utils\";\nimport { XLRSDK } from \"@player-tools/xlr-sdk\";\nimport type { ExpressionNode } from \"@player-ui/player\";\nimport { parseExpression } from \"@player-ui/player\";\nimport {\n getTokenAtPosition,\n toTSLocation,\n convertExprToJSONNode,\n} from \"./utils\";\nimport { toFunction } from \"./transforms\";\n\ninterface ExpressionEntry {\n /**\n * The name of the expression\n */\n name: string;\n /**\n * The description of the expression\n */\n description?: string;\n /**\n * The XLR type of the expression\n */\n type: FunctionType;\n /**\n * The XLR enabled plugin the expression was sourced from\n */\n source: TSManifest;\n}\n\nexport interface ExpressionLanguageServiceConfig {\n /**\n * The list of XLR enabled plugins to load\n */\n plugins: Array<TSManifest>;\n}\n\n/**\n * Language server to check Player expression syntax and usage\n */\nexport class ExpressionLanguageService implements TemplateLanguageService {\n private logger?: Logger;\n private _plugins: Array<TSManifest> = [];\n private _expressions: Map<string, ExpressionEntry>;\n private xlr: XLRSDK;\n\n constructor(\n options?: { logger?: Logger } & Partial<ExpressionLanguageServiceConfig>\n ) {\n this.logger = options?.logger;\n this._plugins = options?.plugins ?? [];\n this.xlr = new XLRSDK();\n\n this._plugins.forEach((p) => {\n this.xlr.loadDefinitionsFromModule(p, undefined, [toFunction]);\n });\n this._expressions = this.reduceExpression();\n }\n\n setConfig(config: ExpressionLanguageServiceConfig) {\n this._plugins = config.plugins;\n this.xlr = new XLRSDK();\n\n this._plugins.forEach((p) => {\n this.xlr.loadDefinitionsFromModule(p, undefined, [toFunction]);\n });\n this._expressions = this.reduceExpression();\n }\n\n private reduceExpression(): Map<string, ExpressionEntry> {\n // Overlaps in names will be resolved by the last plugin to be loaded\n // So use a map to ensure no duplicates\n const expressions = new Map<string, ExpressionEntry>();\n\n this.xlr.listTypes().forEach((type) => {\n const typeInfo = this.xlr.getTypeInfo(type.name);\n const source = this._plugins.find(\n (value) => value.pluginName === typeInfo?.plugin\n );\n\n if (\n type.type === \"function\" &&\n typeInfo?.capability === \"Expressions\" &&\n source\n ) {\n expressions.set(type.name, {\n name: type.name,\n description: type.description,\n type: type as FunctionType,\n source,\n });\n }\n });\n\n return expressions;\n }\n\n getCompletionsAtPosition(\n context: TemplateContext,\n position: ts.LineAndCharacter\n ): ts.CompletionInfo {\n const completionInfo: ts.CompletionInfo = {\n isGlobalCompletion: false,\n isMemberCompletion: false,\n isNewIdentifierLocation: true,\n entries: [],\n };\n\n if (context.text.length === 0) {\n // This happens for the start of an expression (e``)\n // Provide all the completions in this case\n\n this._expressions.forEach((exp) => {\n completionInfo.entries.push({\n name: exp.name,\n kind: ts.ScriptElementKind.functionElement,\n sortText: exp.name,\n isRecommended: true,\n insertText: `${exp.name}()`,\n });\n });\n\n return completionInfo;\n }\n\n const line = context.text.split(/\\n/g)[position.line];\n const parsed = parseExpression(line, { strict: false });\n const token = getTokenAtPosition(parsed, position);\n\n if (token?.type === \"Compound\" && token.error) {\n // We hit the end of the expression, and it's expecting more\n // so provide all the completions\n this._expressions.forEach((exp) => {\n completionInfo.entries.push({\n name: exp.name,\n kind: ts.ScriptElementKind.functionElement,\n sortText: exp.name,\n isRecommended: true,\n insertText: `${exp.name}()`,\n });\n });\n\n return completionInfo;\n }\n\n if (token?.type === \"Identifier\") {\n // get the relevant start of the identifier\n const start = token.location?.start ?? { character: 0 };\n const wordFromStart = line.slice(start.character, position.character);\n const allCompletions = Array.from(this._expressions.keys()).filter(\n (key) => key.startsWith(wordFromStart)\n );\n\n allCompletions.forEach((c) => {\n completionInfo.entries.push({\n name: c,\n kind: ts.ScriptElementKind.functionElement,\n sortText: c,\n isRecommended: true,\n insertText: `${c}()`,\n });\n });\n }\n\n return completionInfo;\n }\n\n getCompletionEntryDetails(\n context: TemplateContext,\n position: ts.LineAndCharacter,\n name: string\n ): ts.CompletionEntryDetails {\n const expression = this._expressions.get(name);\n\n const completionDetails: ts.CompletionEntryDetails = {\n name,\n kind: ts.ScriptElementKind.functionElement,\n kindModifiers: ts.ScriptElementKindModifier.none,\n\n documentation: [\n {\n kind: \"text\",\n text: expression?.type.description ?? \"\",\n },\n ],\n displayParts: expression ? createTSDocString(expression.type) : [],\n };\n\n return completionDetails;\n }\n\n getQuickInfoAtPosition(\n context: TemplateContext,\n position: ts.LineAndCharacter\n ): ts.QuickInfo | undefined {\n const parsed = parseExpression(context.text, { strict: false });\n const token = getTokenAtPosition(parsed, position);\n\n if (token?.type === \"Identifier\") {\n const expression = this._expressions.get(token.name);\n\n if (expression) {\n const completionDetails = this.getCompletionEntryDetails(\n context,\n position,\n expression.name\n );\n\n return {\n ...completionDetails,\n textSpan: toTSLocation(token),\n };\n }\n }\n\n return undefined;\n }\n\n private checkNode(\n context: TemplateContext,\n node: ExpressionNode,\n xlrType: NodeType\n ): ts.Diagnostic[] {\n const diagnostics: ts.Diagnostic[] = [];\n const asJsonNodeValue = convertExprToJSONNode(node);\n\n if (asJsonNodeValue) {\n const xlrDiags = this.xlr.validateByType(xlrType, asJsonNodeValue);\n\n xlrDiags.forEach((d) => {\n diagnostics.push({\n file: context.node.getSourceFile(),\n ...toTSLocation(node),\n messageText: d.message,\n category: ts.DiagnosticCategory.Error,\n code: 1,\n });\n });\n }\n\n return diagnostics;\n }\n\n private getDiagnosticsForNode(\n context: TemplateContext,\n node: ExpressionNode\n ): ts.Diagnostic[] {\n const diags: ts.Diagnostic[] = [];\n\n if (node.type === \"Compound\") {\n node.body.forEach((n) => {\n diags.push(...this.getDiagnosticsForNode(context, n));\n });\n }\n\n if (node.type === \"CallExpression\") {\n // Check that the expression is valid\n const exprName = node.callTarget.name;\n const expression = this._expressions.get(exprName);\n\n node.args.forEach((n) => {\n diags.push(...this.getDiagnosticsForNode(context, n));\n });\n\n if (expression) {\n // Double check the arguments match what we expect\n const expectedArgs = expression.type.parameters;\n const actualArgs = node.args;\n\n actualArgs.forEach((actualArg, index) => {\n const expectedArg = expectedArgs[index];\n\n if (expectedArg) {\n // Check that the type satisfies the expected type\n diags.push(...this.checkNode(context, actualArg, expectedArg.type));\n }\n });\n\n if (expectedArgs.length > actualArgs.length) {\n const requiredArgs = expectedArgs.filter((a) => !a.optional);\n if (actualArgs.length < requiredArgs.length) {\n diags.push({\n category: ts.DiagnosticCategory.Error,\n code: 1,\n file: context.node.getSourceFile(),\n ...toTSLocation(node.callTarget),\n messageText: `Expected ${requiredArgs.length} argument(s), got ${actualArgs.length}`,\n });\n }\n }\n } else {\n diags.push({\n category: ts.DiagnosticCategory.Error,\n code: 1,\n file: context.node.getSourceFile(),\n ...toTSLocation(node.callTarget),\n messageText: `Unknown expression ${exprName}`,\n });\n }\n }\n\n return diags;\n }\n\n getSemanticDiagnostics(context: TemplateContext): ts.Diagnostic[] {\n // Shortcut any type-checking if we don't have any info about what expressions are registered\n if (this._plugins.length === 0) {\n return [];\n }\n\n const parsed = parseExpression(context.text.trim(), { strict: false });\n return this.getDiagnosticsForNode(context, parsed);\n }\n\n getSyntacticDiagnostics(context: TemplateContext): ts.Diagnostic[] {\n const parsed = parseExpression(context.text.trim(), { strict: false });\n\n if (parsed.error) {\n return [\n {\n category: ts.DiagnosticCategory.Error,\n code: 1,\n file: context.node.getSourceFile(),\n ...toTSLocation(parsed),\n messageText: parsed.error.message,\n },\n ];\n }\n\n return [];\n }\n}\n","import type { Position } from \"vscode-languageserver-types\";\nimport type { ExpressionNode, NodeLocation } from \"@player-ui/player\";\nimport { parseTree } from \"jsonc-parser\";\nimport type { Node } from \"jsonc-parser\";\n\n/** Check if the vscode position overlaps with the expression location */\nexport function isInRange(position: Position, location: NodeLocation) {\n return (\n position.character >= location.start.character &&\n position.character <= location.end.character\n );\n}\n\n/** Find the closest marked token at the given position */\nexport function getTokenAtPosition(\n node: ExpressionNode,\n position: Position\n): ExpressionNode | undefined {\n if (node.type === \"CallExpression\") {\n const anyArgs = node.args.find((arg) => {\n return getTokenAtPosition(arg, position);\n });\n\n if (anyArgs) {\n return anyArgs;\n }\n\n const asTarget = getTokenAtPosition(node.callTarget, position);\n if (asTarget) {\n return asTarget;\n }\n }\n\n if (node.type === \"Assignment\") {\n const asTarget =\n getTokenAtPosition(node.left, position) ??\n getTokenAtPosition(node.right, position);\n if (asTarget) {\n return asTarget;\n }\n }\n\n // Lastly check for yourself\n if (node.location && isInRange(position, node.location)) {\n return node;\n }\n}\n\n/** Get the location info that TS expects for it's diags */\nexport function toTSLocation(node: ExpressionNode): ts.TextSpan {\n const start = node.location?.start.character;\n const end = node.location?.end.character;\n if (start === undefined || end === undefined) {\n return {\n start: 0,\n length: 0,\n };\n }\n\n return {\n start,\n length: end - start,\n };\n}\n\n/** ExpressionNode -> raw value */\nexport function convertExprToValue(exprNode: ExpressionNode): any {\n let val;\n\n if (exprNode.type === \"Literal\") {\n val = exprNode.value;\n } else if (exprNode.type === \"Object\") {\n val = {};\n exprNode.attributes.forEach((prop) => {\n val[convertExprToValue(prop.key)] = convertExprToValue(prop.value);\n });\n } else if (exprNode.type === \"ArrayExpression\") {\n val = exprNode.elements.map(convertExprToValue);\n }\n\n return val;\n}\n\n/** ExpressionNode -> JSONC Node */\nexport function convertExprToJSONNode(\n exprNode: ExpressionNode\n): Node | undefined {\n const val = convertExprToValue(exprNode);\n if (val === undefined) {\n return undefined;\n }\n\n return parseTree(JSON.stringify(val));\n}\n","import type { FunctionType, FunctionTypeParameters } from \"@player-tools/xlr\";\nimport { simpleTransformGenerator } from \"@player-tools/xlr-sdk\";\n\nexport const toFunction = simpleTransformGenerator(\n \"ref\",\n \"Expressions\",\n (exp) => {\n if (!exp.genericArguments || exp.ref !== \"ExpressionHandler\") {\n return exp;\n }\n\n const [args, returnType] = exp.genericArguments;\n\n const parameters: Array<FunctionTypeParameters> = (\n args.type === \"tuple\" ? args.elementTypes : []\n ).map((elementType, index) => {\n return {\n name:\n elementType.name ??\n elementType.type.name ??\n elementType.type.title ??\n `arg_${index}`,\n\n type: {\n name:\n elementType.name ??\n elementType.type.name ??\n elementType.type.title ??\n `arg_${index}`,\n ...elementType.type,\n },\n optional:\n elementType.optional === true ? elementType.optional : undefined,\n };\n });\n\n return {\n ...exp,\n type: \"function\",\n parameters,\n returnType,\n } as FunctionType as any;\n }\n);\n","import type { Logger } from \"typescript-template-language-service-decorator\";\nimport ts from \"typescript/lib/tsserverlibrary\";\n\nexport class LSPLogger implements Logger {\n private readonly info: ts.server.PluginCreateInfo;\n\n constructor(info: ts.server.PluginCreateInfo) {\n this.info = info;\n }\n\n log(msg: string) {\n this.info.project.projectService.logger.info(`[player-expr-lsp] ${msg}`);\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/typescript-expression-plugin/src/index.ts","../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/typescript-expression-plugin/src/service.ts","../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/typescript-expression-plugin/src/utils.ts","../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/typescript-expression-plugin/src/transforms.ts","../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/language/typescript-expression-plugin/src/logger.ts"],"sourcesContent":["import ts from \"typescript/lib/tsserverlibrary\";\nimport { decorateWithTemplateLanguageService } from \"typescript-template-language-service-decorator\";\nimport { ExpressionLanguageService } from \"./service\";\nimport { LSPLogger } from \"./logger\";\n\ninterface InitParams {\n typescript: typeof ts;\n}\nclass Plugin implements ts.server.PluginModule {\n private readonly initOptions: InitParams;\n private logger?: LSPLogger;\n private templateService?: ExpressionLanguageService;\n\n constructor(initOptions: InitParams) {\n this.initOptions = initOptions;\n }\n\n create(info: ts.server.PluginCreateInfo): ts.LanguageService {\n const logger = new LSPLogger(info);\n this.logger = logger;\n\n const templateService = new ExpressionLanguageService({ logger });\n this.templateService = templateService;\n\n return decorateWithTemplateLanguageService(\n this.initOptions.typescript,\n info.languageService,\n info.project,\n templateService,\n {\n tags: [\"e\", \"expr\", \"expression\"],\n enableForStringWithSubstitutions: true,\n },\n { logger }\n );\n }\n\n onConfigurationChanged(config: any) {\n this.templateService?.setConfig(config);\n }\n}\n\nfunction init(mod: InitParams): ts.server.PluginModule {\n return new Plugin(mod);\n}\n\nexport default init;\n// export = init;\n","import ts from \"typescript/lib/tsserverlibrary\";\nimport type {\n TemplateLanguageService,\n TemplateContext,\n Logger,\n} from \"typescript-template-language-service-decorator\";\nimport type { FunctionType, TSManifest, NodeType } from \"@player-tools/xlr\";\nimport { createTSDocString } from \"@player-tools/xlr-utils\";\nimport { XLRSDK } from \"@player-tools/xlr-sdk\";\nimport type { ExpressionNode } from \"@player-ui/player\";\nimport { parseExpression } from \"@player-ui/player\";\nimport {\n getTokenAtPosition,\n toTSLocation,\n convertExprToJSONNode,\n} from \"./utils\";\nimport { toFunction } from \"./transforms\";\n\ninterface ExpressionEntry {\n /**\n * The name of the expression\n */\n name: string;\n /**\n * The description of the expression\n */\n description?: string;\n /**\n * The XLR type of the expression\n */\n type: FunctionType;\n /**\n * The XLR enabled plugin the expression was sourced from\n */\n source: TSManifest;\n}\n\nexport interface ExpressionLanguageServiceConfig {\n /**\n * The list of XLR enabled plugins to load\n */\n plugins: Array<TSManifest>;\n}\n\n/**\n * Language server to check Player expression syntax and usage\n */\nexport class ExpressionLanguageService implements TemplateLanguageService {\n private logger?: Logger;\n private _plugins: Array<TSManifest> = [];\n private _expressions: Map<string, ExpressionEntry>;\n private xlr: XLRSDK;\n\n constructor(\n options?: { logger?: Logger } & Partial<ExpressionLanguageServiceConfig>\n ) {\n this.logger = options?.logger;\n this._plugins = options?.plugins ?? [];\n this.xlr = new XLRSDK();\n\n this._plugins.forEach((p) => {\n this.xlr.loadDefinitionsFromModule(p, undefined, [toFunction]);\n });\n this._expressions = this.reduceExpression();\n }\n\n setConfig(config: ExpressionLanguageServiceConfig) {\n this._plugins = config.plugins;\n this.xlr = new XLRSDK();\n\n this._plugins.forEach((p) => {\n this.xlr.loadDefinitionsFromModule(p, undefined, [toFunction]);\n });\n this._expressions = this.reduceExpression();\n }\n\n private reduceExpression(): Map<string, ExpressionEntry> {\n // Overlaps in names will be resolved by the last plugin to be loaded\n // So use a map to ensure no duplicates\n const expressions = new Map<string, ExpressionEntry>();\n\n this.xlr.listTypes().forEach((type) => {\n const typeInfo = this.xlr.getTypeInfo(type.name);\n const source = this._plugins.find(\n (value) => value.pluginName === typeInfo?.plugin\n );\n\n if (\n type.type === \"function\" &&\n typeInfo?.capability === \"Expressions\" &&\n source\n ) {\n expressions.set(type.name, {\n name: type.name,\n description: type.description,\n type: type as FunctionType,\n source,\n });\n }\n });\n\n return expressions;\n }\n\n getCompletionsAtPosition(\n context: TemplateContext,\n position: ts.LineAndCharacter\n ): ts.CompletionInfo {\n const completionInfo: ts.CompletionInfo = {\n isGlobalCompletion: false,\n isMemberCompletion: false,\n isNewIdentifierLocation: true,\n entries: [],\n };\n\n if (context.text.length === 0) {\n // This happens for the start of an expression (e``)\n // Provide all the completions in this case\n\n this._expressions.forEach((exp) => {\n completionInfo.entries.push({\n name: exp.name,\n kind: ts.ScriptElementKind.functionElement,\n sortText: exp.name,\n isRecommended: true,\n insertText: `${exp.name}()`,\n });\n });\n\n return completionInfo;\n }\n\n const line = context.text.split(/\\n/g)[position.line];\n const parsed = parseExpression(line, { strict: false });\n const token = getTokenAtPosition(parsed, position);\n\n if (token?.type === \"Compound\" && token.error) {\n // We hit the end of the expression, and it's expecting more\n // so provide all the completions\n this._expressions.forEach((exp) => {\n completionInfo.entries.push({\n name: exp.name,\n kind: ts.ScriptElementKind.functionElement,\n sortText: exp.name,\n isRecommended: true,\n insertText: `${exp.name}()`,\n });\n });\n\n return completionInfo;\n }\n\n if (token?.type === \"Identifier\") {\n // get the relevant start of the identifier\n const start = token.location?.start ?? { character: 0 };\n const wordFromStart = line.slice(start.character, position.character);\n const allCompletions = Array.from(this._expressions.keys()).filter(\n (key) => key.startsWith(wordFromStart)\n );\n\n allCompletions.forEach((c) => {\n completionInfo.entries.push({\n name: c,\n kind: ts.ScriptElementKind.functionElement,\n sortText: c,\n isRecommended: true,\n insertText: `${c}()`,\n });\n });\n }\n\n return completionInfo;\n }\n\n getCompletionEntryDetails(\n context: TemplateContext,\n position: ts.LineAndCharacter,\n name: string\n ): ts.CompletionEntryDetails {\n const expression = this._expressions.get(name);\n\n const completionDetails: ts.CompletionEntryDetails = {\n name,\n kind: ts.ScriptElementKind.functionElement,\n kindModifiers: ts.ScriptElementKindModifier.none,\n\n documentation: [\n {\n kind: \"text\",\n text: expression?.type.description ?? \"\",\n },\n ],\n displayParts: expression ? createTSDocString(expression.type) : [],\n };\n\n return completionDetails;\n }\n\n getQuickInfoAtPosition(\n context: TemplateContext,\n position: ts.LineAndCharacter\n ): ts.QuickInfo | undefined {\n const parsed = parseExpression(context.text, { strict: false });\n const token = getTokenAtPosition(parsed, position);\n\n if (token?.type === \"Identifier\") {\n const expression = this._expressions.get(token.name);\n\n if (expression) {\n const completionDetails = this.getCompletionEntryDetails(\n context,\n position,\n expression.name\n );\n\n return {\n ...completionDetails,\n textSpan: toTSLocation(token),\n };\n }\n }\n\n return undefined;\n }\n\n private checkNode(\n context: TemplateContext,\n node: ExpressionNode,\n xlrType: NodeType\n ): ts.Diagnostic[] {\n const diagnostics: ts.Diagnostic[] = [];\n const asJsonNodeValue = convertExprToJSONNode(node);\n\n if (asJsonNodeValue) {\n const xlrDiags = this.xlr.validateByType(xlrType, asJsonNodeValue);\n\n xlrDiags.forEach((d) => {\n diagnostics.push({\n file: context.node.getSourceFile(),\n ...toTSLocation(node),\n messageText: d.message,\n category: ts.DiagnosticCategory.Error,\n code: 1,\n });\n });\n }\n\n return diagnostics;\n }\n\n private getDiagnosticsForNode(\n context: TemplateContext,\n node: ExpressionNode\n ): ts.Diagnostic[] {\n const diags: ts.Diagnostic[] = [];\n\n if (node.type === \"Compound\") {\n node.body.forEach((n) => {\n diags.push(...this.getDiagnosticsForNode(context, n));\n });\n }\n\n if (node.type === \"CallExpression\") {\n // Check that the expression is valid\n const exprName = node.callTarget.name;\n const expression = this._expressions.get(exprName);\n\n node.args.forEach((n) => {\n diags.push(...this.getDiagnosticsForNode(context, n));\n });\n\n if (expression) {\n // Double check the arguments match what we expect\n const expectedArgs = expression.type.parameters;\n const actualArgs = node.args;\n\n actualArgs.forEach((actualArg, index) => {\n const expectedArg = expectedArgs[index];\n\n if (expectedArg) {\n // Check that the type satisfies the expected type\n diags.push(...this.checkNode(context, actualArg, expectedArg.type));\n }\n });\n\n if (expectedArgs.length > actualArgs.length) {\n const requiredArgs = expectedArgs.filter((a) => !a.optional);\n if (actualArgs.length < requiredArgs.length) {\n diags.push({\n category: ts.DiagnosticCategory.Error,\n code: 1,\n file: context.node.getSourceFile(),\n ...toTSLocation(node.callTarget),\n messageText: `Expected ${requiredArgs.length} argument(s), got ${actualArgs.length}`,\n });\n }\n }\n } else {\n diags.push({\n category: ts.DiagnosticCategory.Error,\n code: 1,\n file: context.node.getSourceFile(),\n ...toTSLocation(node.callTarget),\n messageText: `Unknown expression ${exprName}`,\n });\n }\n }\n\n return diags;\n }\n\n getSemanticDiagnostics(context: TemplateContext): ts.Diagnostic[] {\n // Shortcut any type-checking if we don't have any info about what expressions are registered\n if (this._plugins.length === 0) {\n return [];\n }\n\n const parsed = parseExpression(context.text.trim(), { strict: false });\n return this.getDiagnosticsForNode(context, parsed);\n }\n\n getSyntacticDiagnostics(context: TemplateContext): ts.Diagnostic[] {\n const parsed = parseExpression(context.text.trim(), { strict: false });\n\n if (parsed.error) {\n return [\n {\n category: ts.DiagnosticCategory.Error,\n code: 1,\n file: context.node.getSourceFile(),\n ...toTSLocation(parsed),\n messageText: parsed.error.message,\n },\n ];\n }\n\n return [];\n }\n}\n","import type { TextSpan } from \"typescript\";\nimport type { Position } from \"vscode-languageserver-types\";\nimport type { ExpressionNode, NodeLocation } from \"@player-ui/player\";\nimport { parseTree } from \"jsonc-parser\";\nimport type { Node } from \"jsonc-parser\";\n\n/** Check if the vscode position overlaps with the expression location */\nexport function isInRange(position: Position, location: NodeLocation) {\n return (\n position.character >= location.start.character &&\n position.character <= location.end.character\n );\n}\n\n/** Find the closest marked token at the given position */\nexport function getTokenAtPosition(\n node: ExpressionNode,\n position: Position\n): ExpressionNode | undefined {\n if (node.type === \"CallExpression\") {\n const anyArgs = node.args.find((arg) => {\n return getTokenAtPosition(arg, position);\n });\n\n if (anyArgs) {\n return anyArgs;\n }\n\n const asTarget = getTokenAtPosition(node.callTarget, position);\n if (asTarget) {\n return asTarget;\n }\n }\n\n if (node.type === \"Assignment\") {\n const asTarget =\n getTokenAtPosition(node.left, position) ??\n getTokenAtPosition(node.right, position);\n if (asTarget) {\n return asTarget;\n }\n }\n\n // Lastly check for yourself\n if (node.location && isInRange(position, node.location)) {\n return node;\n }\n}\n\n/** Get the location info that TS expects for it's diags */\nexport function toTSLocation(node: ExpressionNode): TextSpan {\n const start = node.location?.start.character;\n const end = node.location?.end.character;\n if (start === undefined || end === undefined) {\n return {\n start: 0,\n length: 0,\n };\n }\n\n return {\n start,\n length: end - start,\n };\n}\n\n/** ExpressionNode -> raw value */\nexport function convertExprToValue(exprNode: ExpressionNode): any {\n let val;\n\n if (exprNode.type === \"Literal\") {\n val = exprNode.value;\n } else if (exprNode.type === \"Object\") {\n val = {};\n exprNode.attributes.forEach((prop) => {\n val[convertExprToValue(prop.key)] = convertExprToValue(prop.value);\n });\n } else if (exprNode.type === \"ArrayExpression\") {\n val = exprNode.elements.map(convertExprToValue);\n }\n\n return val;\n}\n\n/** ExpressionNode -> JSONC Node */\nexport function convertExprToJSONNode(\n exprNode: ExpressionNode\n): Node | undefined {\n const val = convertExprToValue(exprNode);\n if (val === undefined) {\n return undefined;\n }\n\n return parseTree(JSON.stringify(val));\n}\n","import type { FunctionType, FunctionTypeParameters } from \"@player-tools/xlr\";\nimport { simpleTransformGenerator } from \"@player-tools/xlr-sdk\";\n\nexport const toFunction = simpleTransformGenerator(\n \"ref\",\n \"Expressions\",\n (exp) => {\n if (!exp.genericArguments || exp.ref !== \"ExpressionHandler\") {\n return exp;\n }\n\n const [args, returnType] = exp.genericArguments;\n\n const parameters: Array<FunctionTypeParameters> = (\n args.type === \"tuple\" ? args.elementTypes : []\n ).map((elementType, index) => {\n return {\n name:\n elementType.name ??\n elementType.type.name ??\n elementType.type.title ??\n `arg_${index}`,\n\n type: {\n name:\n elementType.name ??\n elementType.type.name ??\n elementType.type.title ??\n `arg_${index}`,\n ...elementType.type,\n },\n optional:\n elementType.optional === true ? elementType.optional : undefined,\n };\n });\n\n return {\n ...exp,\n type: \"function\",\n parameters,\n returnType,\n } as FunctionType as any;\n }\n);\n","import type { Logger } from \"typescript-template-language-service-decorator\";\nimport ts from \"typescript/lib/tsserverlibrary\";\n\nexport class LSPLogger implements Logger {\n private readonly info: ts.server.PluginCreateInfo;\n\n constructor(info: ts.server.PluginCreateInfo) {\n this.info = info;\n }\n\n log(msg: string) {\n this.info.project.projectService.logger.info(`[player-expr-lsp] ${msg}`);\n }\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,23 +1,27 @@
1
1
  {
2
2
  "name": "@player-tools/typescript-expression-plugin",
3
- "version": "0.5.2-next.1",
3
+ "version": "0.5.2",
4
4
  "main": "dist/cjs/index.cjs",
5
5
  "dependencies": {
6
- "@player-tools/xlr": "0.5.2-next.1",
7
- "@player-tools/xlr-sdk": "0.5.2-next.1",
8
- "@player-tools/xlr-utils": "0.5.2-next.1",
9
- "@player-ui/player": "0.7.1-next.0",
6
+ "@player-tools/xlr": "0.5.2",
7
+ "@player-tools/xlr-sdk": "0.5.2",
8
+ "@player-tools/xlr-utils": "0.5.2",
9
+ "@player-ui/player": "0.7.2-next.4",
10
10
  "jsonc-parser": "^2.3.1",
11
11
  "typescript-template-language-service-decorator": "^2.3.1",
12
12
  "vscode-languageserver-types": "^3.15.1",
13
- "typescript": "4.8.4",
13
+ "typescript": "^5.4.4",
14
14
  "tslib": "^2.6.2"
15
15
  },
16
+ "devDependencies": {
17
+ "@player-tools/static-xlrs": "workspace:*"
18
+ },
16
19
  "module": "dist/index.legacy-esm.js",
17
20
  "types": "types/index.d.ts",
18
21
  "sideEffects": false,
19
22
  "exports": {
20
23
  "./package.json": "./package.json",
24
+ "./dist/index.css": "./dist/index.css",
21
25
  ".": {
22
26
  "types": "./types/index.d.ts",
23
27
  "import": "./dist/index.mjs",
package/src/utils.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { TextSpan } from "typescript";
1
2
  import type { Position } from "vscode-languageserver-types";
2
3
  import type { ExpressionNode, NodeLocation } from "@player-ui/player";
3
4
  import { parseTree } from "jsonc-parser";
@@ -47,7 +48,7 @@ export function getTokenAtPosition(
47
48
  }
48
49
 
49
50
  /** Get the location info that TS expects for it's diags */
50
- export function toTSLocation(node: ExpressionNode): ts.TextSpan {
51
+ export function toTSLocation(node: ExpressionNode): TextSpan {
51
52
  const start = node.location?.start.character;
52
53
  const end = node.location?.end.character;
53
54
  if (start === undefined || end === undefined) {
package/types/utils.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { TextSpan } from "typescript";
1
2
  import type { Position } from "vscode-languageserver-types";
2
3
  import type { ExpressionNode, NodeLocation } from "@player-ui/player";
3
4
  import type { Node } from "jsonc-parser";
@@ -6,7 +7,7 @@ export declare function isInRange(position: Position, location: NodeLocation): b
6
7
  /** Find the closest marked token at the given position */
7
8
  export declare function getTokenAtPosition(node: ExpressionNode, position: Position): ExpressionNode | undefined;
8
9
  /** Get the location info that TS expects for it's diags */
9
- export declare function toTSLocation(node: ExpressionNode): ts.TextSpan;
10
+ export declare function toTSLocation(node: ExpressionNode): TextSpan;
10
11
  /** ExpressionNode -> raw value */
11
12
  export declare function convertExprToValue(exprNode: ExpressionNode): any;
12
13
  /** ExpressionNode -> JSONC Node */