@platformos/platformos-language-server-common 0.0.8 → 0.0.9
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/CHANGELOG.md +10 -0
- package/dist/PropertyShapeInference.js +4 -0
- package/dist/PropertyShapeInference.js.map +1 -1
- package/dist/TypeSystem.js +19 -9
- package/dist/TypeSystem.js.map +1 -1
- package/dist/completions/params/LiquidCompletionParams.js +2 -1
- package/dist/completions/params/LiquidCompletionParams.js.map +1 -1
- package/dist/documents/DocumentManager.js +5 -1
- package/dist/documents/DocumentManager.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/uri.d.ts +2 -1
- package/dist/utils/uri.js +5 -5
- package/dist/utils/uri.js.map +1 -1
- package/package.json +4 -4
- package/src/ClientCapabilities.ts +1 -1
- package/src/PropertyShapeInference.ts +6 -1
- package/src/TypeSystem.spec.ts +19 -0
- package/src/TypeSystem.ts +23 -10
- package/src/codeActions/providers/FixAllProvider.spec.ts +1 -1
- package/src/codeActions/providers/FixProvider.spec.ts +11 -11
- package/src/codeActions/providers/SuggestionProvider.spec.ts +2 -2
- package/src/commands/providers/ApplyFixesProvider.ts +2 -2
- package/src/commands/providers/ApplySuggestionProvider.ts +2 -2
- package/src/commands/providers/RunChecksProvider.ts +2 -2
- package/src/completions/CompletionsProvider.ts +1 -1
- package/src/completions/params/LiquidCompletionParams.ts +4 -3
- package/src/completions/providers/LiquidTagsCompletionProvider.spec.ts +2 -2
- package/src/completions/providers/PartialCompletionProvider.spec.ts +2 -2
- package/src/completions/providers/RenderPartialParameterCompletionProvider.spec.ts +11 -11
- package/src/completions/providers/RenderPartialParameterCompletionProvider.ts +2 -2
- package/src/completions/providers/TranslationCompletionProvider.ts +3 -3
- package/src/diagnostics/runChecks.spec.ts +6 -6
- package/src/documentLinks/DocumentLinksProvider.ts +7 -7
- package/src/documents/DocumentManager.spec.ts +34 -22
- package/src/documents/DocumentManager.ts +6 -1
- package/src/hover/providers/LiquidDocTagHoverProvider.spec.ts +1 -1
- package/src/hover/providers/RenderPartialHoverProvider.spec.ts +10 -10
- package/src/hover/providers/RenderPartialParameterHoverProvider.spec.ts +9 -9
- package/src/hover/providers/RenderPartialParameterHoverProvider.ts +2 -2
- package/src/index.ts +2 -2
- package/src/rename/RenameProvider.ts +1 -1
- package/src/rename/providers/LiquidVariableRenameProvider.spec.ts +1 -1
- package/src/rename/providers/LiquidVariableRenameProvider.ts +3 -3
- package/src/renamed/handlers/AssetRenameHandler.spec.ts +25 -25
- package/src/renamed/handlers/AssetRenameHandler.ts +1 -1
- package/src/renamed/handlers/PartialRenameHandler.spec.ts +7 -7
- package/src/renamed/handlers/PartialRenameHandler.ts +5 -5
- package/src/server/safe.ts +1 -1
- package/src/server/startServer.spec.ts +3 -3
- package/src/server/startServer.ts +4 -5
- package/src/utils/debounce.ts +1 -1
- package/src/utils/liquidDoc.ts +5 -5
- package/src/utils/uri.ts +5 -3
- package/src/renamed/handlers/utils.ts +0 -22
package/dist/utils/uri.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
+
import { isPartial } from '@platformos/platformos-common';
|
|
2
|
+
export { isPartial };
|
|
1
3
|
export declare const partialName: (uri: string) => string;
|
|
2
|
-
export declare const isPartial: (uri: string) => boolean;
|
|
3
4
|
export declare const assetName: (uri: string) => string;
|
|
4
5
|
export declare const isAsset: (uri: string) => boolean;
|
package/dist/utils/uri.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isAsset = exports.assetName = exports.
|
|
3
|
+
exports.isAsset = exports.assetName = exports.partialName = exports.isPartial = void 0;
|
|
4
4
|
const platformos_check_common_1 = require("@platformos/platformos-check-common");
|
|
5
|
+
const platformos_common_1 = require("@platformos/platformos-common");
|
|
6
|
+
Object.defineProperty(exports, "isPartial", { enumerable: true, get: function () { return platformos_common_1.isPartial; } });
|
|
5
7
|
const partialName = (uri) => platformos_check_common_1.path.basename(uri, '.liquid');
|
|
6
8
|
exports.partialName = partialName;
|
|
7
|
-
|
|
8
|
-
exports.isPartial = isPartial;
|
|
9
|
-
// asset urls have their `.liquid`` removed (if present) and require the other extension */
|
|
9
|
+
// asset urls have their `.liquid` removed (if present) and require the other extension
|
|
10
10
|
const assetName = (uri) => platformos_check_common_1.path.basename(uri, '.liquid');
|
|
11
11
|
exports.assetName = assetName;
|
|
12
|
-
const isAsset = (uri) =>
|
|
12
|
+
const isAsset = (uri) => (0, platformos_common_1.getFileType)(uri) === platformos_common_1.PlatformOSFileType.Asset;
|
|
13
13
|
exports.isAsset = isAsset;
|
|
14
14
|
//# sourceMappingURL=uri.js.map
|
package/dist/utils/uri.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uri.js","sourceRoot":"","sources":["../../src/utils/uri.ts"],"names":[],"mappings":";;;AAAA,iFAA2D;
|
|
1
|
+
{"version":3,"file":"uri.js","sourceRoot":"","sources":["../../src/utils/uri.ts"],"names":[],"mappings":";;;AAAA,iFAA2D;AAC3D,qEAA2F;AAElF,0FAFA,6BAAS,OAEA;AAEX,MAAM,WAAW,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,8BAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;AAA7D,QAAA,WAAW,eAAkD;AAE1E,uFAAuF;AAChF,MAAM,SAAS,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,8BAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;AAA3D,QAAA,SAAS,aAAkD;AACjE,MAAM,OAAO,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,IAAA,+BAAW,EAAC,GAAG,CAAC,KAAK,sCAAkB,CAAC,KAAK,CAAC;AAAzE,QAAA,OAAO,WAAkE"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformos/platformos-language-server-common",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"author": "platformOS",
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
"type-check": "tsc --noEmit -p ./tsconfig.json"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@platformos/liquid-html-parser": "^0.0.
|
|
31
|
-
"@platformos/platformos-check-common": "0.0.
|
|
32
|
-
"@platformos/platformos-graph": "0.0.
|
|
30
|
+
"@platformos/liquid-html-parser": "^0.0.9",
|
|
31
|
+
"@platformos/platformos-check-common": "0.0.9",
|
|
32
|
+
"@platformos/platformos-graph": "0.0.9",
|
|
33
33
|
"@vscode/web-custom-data": "^0.4.6",
|
|
34
34
|
"vscode-json-languageservice": "^5.7.1",
|
|
35
35
|
"vscode-languageserver": "^9.0.1",
|
|
@@ -48,7 +48,7 @@ export class ClientCapabilities {
|
|
|
48
48
|
const direct = this.initializationOptions?.[key];
|
|
49
49
|
if (direct !== undefined) return direct;
|
|
50
50
|
|
|
51
|
-
// {
|
|
51
|
+
// { platformosCheck: { checkOnSave: true } }
|
|
52
52
|
const nested = pathGet<T>(this.initializationOptions, key);
|
|
53
53
|
if (nested !== undefined) return nested;
|
|
54
54
|
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
JsonHashLiteral,
|
|
15
15
|
JsonArrayLiteral,
|
|
16
16
|
LiquidExpression,
|
|
17
|
+
LiquidVariable,
|
|
17
18
|
NodeTypes,
|
|
18
19
|
} from '@platformos/liquid-html-parser';
|
|
19
20
|
|
|
@@ -164,9 +165,13 @@ function getJsonKeyName(key: LiquidExpression): string | undefined {
|
|
|
164
165
|
}
|
|
165
166
|
|
|
166
167
|
function inferShapeFromExpression(
|
|
167
|
-
expr: LiquidExpression,
|
|
168
|
+
expr: LiquidExpression | LiquidVariable,
|
|
168
169
|
resolveExpression?: ExpressionShapeResolver,
|
|
169
170
|
): PropertyShape {
|
|
171
|
+
if (expr.type === NodeTypes.LiquidVariable) {
|
|
172
|
+
// A filtered expression's output type can't be statically inferred
|
|
173
|
+
return { kind: 'primitive' };
|
|
174
|
+
}
|
|
170
175
|
switch (expr.type) {
|
|
171
176
|
case NodeTypes.JsonHashLiteral:
|
|
172
177
|
case NodeTypes.JsonArrayLiteral:
|
package/src/TypeSystem.spec.ts
CHANGED
|
@@ -881,5 +881,24 @@ query {
|
|
|
881
881
|
});
|
|
882
882
|
}
|
|
883
883
|
});
|
|
884
|
+
|
|
885
|
+
it('should support explicit push form (assign a = source << value)', async () => {
|
|
886
|
+
const ast = toLiquidHtmlAST(`{% assign arr = [] %}{% assign arr = arr << "item" %}{{ arr }}`);
|
|
887
|
+
const variableOutput = ast.children[2];
|
|
888
|
+
assert(isLiquidVariableOutput(variableOutput));
|
|
889
|
+
const inferredType = await typeSystem.inferType(
|
|
890
|
+
variableOutput.markup,
|
|
891
|
+
ast,
|
|
892
|
+
'file:///file.liquid',
|
|
893
|
+
);
|
|
894
|
+
expect(inferredType).to.have.property('kind', 'shape');
|
|
895
|
+
if (typeof inferredType !== 'string' && inferredType.kind === 'shape') {
|
|
896
|
+
expect(inferredType.shape.kind).to.equal('array');
|
|
897
|
+
expect(inferredType.shape.itemShape).to.deep.equal({
|
|
898
|
+
kind: 'primitive',
|
|
899
|
+
primitiveType: 'string',
|
|
900
|
+
});
|
|
901
|
+
}
|
|
902
|
+
});
|
|
884
903
|
});
|
|
885
904
|
});
|
package/src/TypeSystem.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AssignMarkup,
|
|
3
|
+
AssignPushRhs,
|
|
3
4
|
ComplexLiquidExpression,
|
|
4
5
|
FunctionMarkup,
|
|
5
6
|
LiquidDocParamNode,
|
|
@@ -240,7 +241,7 @@ type FilterEntryName = FilterEntry['name'];
|
|
|
240
241
|
export const Untyped = 'untyped' as const;
|
|
241
242
|
export type Untyped = typeof Untyped;
|
|
242
243
|
|
|
243
|
-
/** Unknown is for variables that don't exist, type would come from context (e.g.
|
|
244
|
+
/** Unknown is for variables that don't exist, type would come from context (e.g. partial var without LiquidDoc) */
|
|
244
245
|
export const Unknown = 'unknown' as const;
|
|
245
246
|
export type Unknown = typeof Untyped;
|
|
246
247
|
|
|
@@ -383,8 +384,15 @@ async function buildSymbolsTable(
|
|
|
383
384
|
// {% assign x = {a: 1, b: "hello"} %}
|
|
384
385
|
// {% assign x["key"] = value %}
|
|
385
386
|
// {% assign arr << item %}
|
|
387
|
+
// {% assign arr = source << item %}
|
|
386
388
|
async AssignMarkup(node) {
|
|
387
|
-
|
|
389
|
+
// For explicit push form (assign a = source << value), treat as array append
|
|
390
|
+
const isPushRhs = node.value.type === NodeTypes.AssignPushRhs;
|
|
391
|
+
const effectiveValue = isPushRhs
|
|
392
|
+
? (node.value as AssignPushRhs).pushValue
|
|
393
|
+
: (node.value as LiquidVariable);
|
|
394
|
+
const effectiveOperator = isPushRhs ? '<<' : node.operator;
|
|
395
|
+
const expression = effectiveValue.expression;
|
|
388
396
|
let valueShape: PropertyShape | undefined;
|
|
389
397
|
|
|
390
398
|
// Resolver for variable references inside JSON literals
|
|
@@ -451,7 +459,7 @@ async function buildSymbolsTable(
|
|
|
451
459
|
|
|
452
460
|
// Case 2: parse_json / to_hash filter on a string
|
|
453
461
|
if (!valueShape) {
|
|
454
|
-
const hasParseJsonFilter =
|
|
462
|
+
const hasParseJsonFilter = effectiveValue.filters?.some(
|
|
455
463
|
(f: { name: string }) => f.name === 'parse_json' || f.name === 'to_hash',
|
|
456
464
|
);
|
|
457
465
|
if (hasParseJsonFilter) {
|
|
@@ -459,8 +467,8 @@ async function buildSymbolsTable(
|
|
|
459
467
|
if (expression.type === NodeTypes.String) {
|
|
460
468
|
jsonString = expression.value;
|
|
461
469
|
}
|
|
462
|
-
if (!jsonString &&
|
|
463
|
-
const defaultFilter =
|
|
470
|
+
if (!jsonString && effectiveValue.filters) {
|
|
471
|
+
const defaultFilter = effectiveValue.filters.find(
|
|
464
472
|
(f: { name: string }) => f.name === 'default',
|
|
465
473
|
);
|
|
466
474
|
if (
|
|
@@ -479,7 +487,10 @@ async function buildSymbolsTable(
|
|
|
479
487
|
}
|
|
480
488
|
|
|
481
489
|
// Case 3: Infer primitive shape for << and LHS lookup scenarios
|
|
482
|
-
if (
|
|
490
|
+
if (
|
|
491
|
+
!valueShape &&
|
|
492
|
+
((node.lookups && node.lookups.length > 0) || effectiveOperator === '<<')
|
|
493
|
+
) {
|
|
483
494
|
if (expression.type === NodeTypes.String) {
|
|
484
495
|
valueShape = { kind: 'primitive', primitiveType: 'string' };
|
|
485
496
|
} else if (expression.type === NodeTypes.Number) {
|
|
@@ -537,8 +548,8 @@ async function buildSymbolsTable(
|
|
|
537
548
|
}
|
|
538
549
|
}
|
|
539
550
|
|
|
540
|
-
// Handle << operator (array append)
|
|
541
|
-
if (
|
|
551
|
+
// Handle << operator (array append), including explicit form (assign a = source << value)
|
|
552
|
+
if (effectiveOperator === '<<') {
|
|
542
553
|
const itemShape: PropertyShape = valueShape ?? { kind: 'primitive' };
|
|
543
554
|
const existingShapes = variableShapes.get(node.name) || [];
|
|
544
555
|
const existingShapeEntry = findLastApplicableShape(existingShapes, node.position.start);
|
|
@@ -578,7 +589,7 @@ async function buildSymbolsTable(
|
|
|
578
589
|
// Default: lazy variable type
|
|
579
590
|
return {
|
|
580
591
|
identifier: node.name,
|
|
581
|
-
type: lazyVariable(
|
|
592
|
+
type: lazyVariable(effectiveValue, node.position.start),
|
|
582
593
|
range: [node.position.end],
|
|
583
594
|
};
|
|
584
595
|
},
|
|
@@ -986,7 +997,9 @@ function inferType(
|
|
|
986
997
|
// The type of the assign markup is the type of the right hand side.
|
|
987
998
|
// {% assign x = y.property | filter1 | filter2 %}
|
|
988
999
|
case NodeTypes.AssignMarkup: {
|
|
989
|
-
|
|
1000
|
+
const assignValue =
|
|
1001
|
+
thing.value.type === NodeTypes.AssignPushRhs ? thing.value.pushValue : thing.value;
|
|
1002
|
+
return inferType(assignValue, symbolsTable, objectMap, filtersMap);
|
|
990
1003
|
}
|
|
991
1004
|
|
|
992
1005
|
// A variable lookup is expression[.lookup]*
|
|
@@ -75,7 +75,7 @@ describe('Unit: FixProvider', () => {
|
|
|
75
75
|
isPreferred: true,
|
|
76
76
|
command: {
|
|
77
77
|
title: 'applyFixes',
|
|
78
|
-
command: '
|
|
78
|
+
command: 'platformosCheck/applyFixes',
|
|
79
79
|
arguments: [uri, 1, [1]],
|
|
80
80
|
},
|
|
81
81
|
});
|
|
@@ -87,7 +87,7 @@ describe('Unit: FixProvider', () => {
|
|
|
87
87
|
isPreferred: false,
|
|
88
88
|
command: {
|
|
89
89
|
title: 'applyFixes',
|
|
90
|
-
command: '
|
|
90
|
+
command: 'platformosCheck/applyFixes',
|
|
91
91
|
arguments: [uri, 1, [1, 2]],
|
|
92
92
|
},
|
|
93
93
|
});
|
|
@@ -99,7 +99,7 @@ describe('Unit: FixProvider', () => {
|
|
|
99
99
|
isPreferred: false,
|
|
100
100
|
command: {
|
|
101
101
|
title: 'applyFixes',
|
|
102
|
-
command: '
|
|
102
|
+
command: 'platformosCheck/applyFixes',
|
|
103
103
|
arguments: [uri, 1, [0, 1, 2]],
|
|
104
104
|
},
|
|
105
105
|
});
|
|
@@ -135,7 +135,7 @@ describe('Unit: FixProvider', () => {
|
|
|
135
135
|
isPreferred: true,
|
|
136
136
|
command: {
|
|
137
137
|
title: 'applyFixes',
|
|
138
|
-
command: '
|
|
138
|
+
command: 'platformosCheck/applyFixes',
|
|
139
139
|
arguments: [uri, 1, [1]],
|
|
140
140
|
},
|
|
141
141
|
});
|
|
@@ -147,7 +147,7 @@ describe('Unit: FixProvider', () => {
|
|
|
147
147
|
isPreferred: false,
|
|
148
148
|
command: {
|
|
149
149
|
title: 'applyFixes',
|
|
150
|
-
command: '
|
|
150
|
+
command: 'platformosCheck/applyFixes',
|
|
151
151
|
arguments: [uri, 1, [0, 1]],
|
|
152
152
|
},
|
|
153
153
|
});
|
|
@@ -183,7 +183,7 @@ describe('Unit: FixProvider', () => {
|
|
|
183
183
|
isPreferred: true,
|
|
184
184
|
command: {
|
|
185
185
|
title: 'applyFixes',
|
|
186
|
-
command: '
|
|
186
|
+
command: 'platformosCheck/applyFixes',
|
|
187
187
|
arguments: [uri, 1, [0]],
|
|
188
188
|
},
|
|
189
189
|
});
|
|
@@ -195,7 +195,7 @@ describe('Unit: FixProvider', () => {
|
|
|
195
195
|
isPreferred: false,
|
|
196
196
|
command: {
|
|
197
197
|
title: 'applyFixes',
|
|
198
|
-
command: '
|
|
198
|
+
command: 'platformosCheck/applyFixes',
|
|
199
199
|
arguments: [uri, 1, [0, 1]],
|
|
200
200
|
},
|
|
201
201
|
});
|
|
@@ -230,7 +230,7 @@ describe('Unit: FixProvider', () => {
|
|
|
230
230
|
isPreferred: true,
|
|
231
231
|
command: {
|
|
232
232
|
title: 'applyFixes',
|
|
233
|
-
command: '
|
|
233
|
+
command: 'platformosCheck/applyFixes',
|
|
234
234
|
arguments: [uri, 1, [0]],
|
|
235
235
|
},
|
|
236
236
|
});
|
|
@@ -264,7 +264,7 @@ describe('Unit: FixProvider', () => {
|
|
|
264
264
|
isPreferred: true,
|
|
265
265
|
command: {
|
|
266
266
|
title: 'applyFixes',
|
|
267
|
-
command: '
|
|
267
|
+
command: 'platformosCheck/applyFixes',
|
|
268
268
|
arguments: [uri, 1, [1]],
|
|
269
269
|
},
|
|
270
270
|
});
|
|
@@ -276,7 +276,7 @@ describe('Unit: FixProvider', () => {
|
|
|
276
276
|
isPreferred: false,
|
|
277
277
|
command: {
|
|
278
278
|
title: 'applyFixes',
|
|
279
|
-
command: '
|
|
279
|
+
command: 'platformosCheck/applyFixes',
|
|
280
280
|
arguments: [uri, 1, [1, 2]],
|
|
281
281
|
},
|
|
282
282
|
});
|
|
@@ -288,7 +288,7 @@ describe('Unit: FixProvider', () => {
|
|
|
288
288
|
isPreferred: false,
|
|
289
289
|
command: {
|
|
290
290
|
title: 'applyFixes',
|
|
291
|
-
command: '
|
|
291
|
+
command: 'platformosCheck/applyFixes',
|
|
292
292
|
arguments: [uri, 1, [0, 1, 2]],
|
|
293
293
|
},
|
|
294
294
|
});
|
|
@@ -88,7 +88,7 @@ describe('Unit: SuggestionProvider', () => {
|
|
|
88
88
|
isPreferred: false,
|
|
89
89
|
command: {
|
|
90
90
|
title: 'applySuggestion',
|
|
91
|
-
command: '
|
|
91
|
+
command: 'platformosCheck/applySuggestion',
|
|
92
92
|
arguments: [uri, version, anomalyId, 0],
|
|
93
93
|
},
|
|
94
94
|
});
|
|
@@ -100,7 +100,7 @@ describe('Unit: SuggestionProvider', () => {
|
|
|
100
100
|
isPreferred: false,
|
|
101
101
|
command: {
|
|
102
102
|
title: 'applySuggestion',
|
|
103
|
-
command: '
|
|
103
|
+
command: 'platformosCheck/applySuggestion',
|
|
104
104
|
arguments: [uri, version, anomalyId, 1],
|
|
105
105
|
},
|
|
106
106
|
});
|
|
@@ -14,7 +14,7 @@ import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
|
14
14
|
import { BaseExecuteCommandProvider } from '../BaseExecuteCommandProvider';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
* The ApplyFixesProvider is responsible for handling the `
|
|
17
|
+
* The ApplyFixesProvider is responsible for handling the `platformosCheck/applyFixes` command.
|
|
18
18
|
*
|
|
19
19
|
* To create a command, use the `applyFixCommand` function.
|
|
20
20
|
* The provider will execute the command with the given arguments.
|
|
@@ -23,7 +23,7 @@ import { BaseExecuteCommandProvider } from '../BaseExecuteCommandProvider';
|
|
|
23
23
|
* applies them, and forwards the result to the client using the 'workspace/applyEdit' request.
|
|
24
24
|
*/
|
|
25
25
|
export class ApplyFixesProvider extends BaseExecuteCommandProvider {
|
|
26
|
-
static command = '
|
|
26
|
+
static command = 'platformosCheck/applyFixes' as const;
|
|
27
27
|
|
|
28
28
|
async execute(uri: string, version: number | undefined, ids: number[]) {
|
|
29
29
|
if (!this.clientCapabilities.hasApplyEditSupport) return;
|
|
@@ -14,7 +14,7 @@ import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
|
14
14
|
import { BaseExecuteCommandProvider } from '../BaseExecuteCommandProvider';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
* The ApplySuggestionProvider is responsible for handling the `
|
|
17
|
+
* The ApplySuggestionProvider is responsible for handling the `platformosCheck/applySuggestion` command.
|
|
18
18
|
*
|
|
19
19
|
* To create a command, use the `applySuggestionCommand` function.
|
|
20
20
|
* The provider will execute the command with the given arguments.
|
|
@@ -23,7 +23,7 @@ import { BaseExecuteCommandProvider } from '../BaseExecuteCommandProvider';
|
|
|
23
23
|
* applies them, and forwards the result to the client using the 'workspace/applyEdit' request.
|
|
24
24
|
*/
|
|
25
25
|
export class ApplySuggestionProvider extends BaseExecuteCommandProvider {
|
|
26
|
-
static command = '
|
|
26
|
+
static command = 'platformosCheck/applySuggestion' as const;
|
|
27
27
|
|
|
28
28
|
async execute(
|
|
29
29
|
uri: string,
|
|
@@ -6,7 +6,7 @@ import { DebouncedFunction } from '../../utils';
|
|
|
6
6
|
import { BaseExecuteCommandProvider } from '../BaseExecuteCommandProvider';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* The RunChecksProvider runs
|
|
9
|
+
* The RunChecksProvider runs platformos-check on all open files.
|
|
10
10
|
*
|
|
11
11
|
* It is triggered by the cmd+p command in the VS Code extension and is
|
|
12
12
|
* otherwise not used internally, which is why there is no
|
|
@@ -16,7 +16,7 @@ import { BaseExecuteCommandProvider } from '../BaseExecuteCommandProvider';
|
|
|
16
16
|
* `checkOnOpen` are all false.
|
|
17
17
|
*/
|
|
18
18
|
export class RunChecksProvider extends BaseExecuteCommandProvider {
|
|
19
|
-
static command = '
|
|
19
|
+
static command = 'platformosCheck/runChecks' as const;
|
|
20
20
|
|
|
21
21
|
constructor(
|
|
22
22
|
protected documentManager: DocumentManager,
|
|
@@ -38,7 +38,7 @@ export interface CompletionProviderDependencies {
|
|
|
38
38
|
fs?: AbstractFileSystem;
|
|
39
39
|
/** Locator for finding documents by type */
|
|
40
40
|
documentsLocator?: DocumentsLocator;
|
|
41
|
-
/** Function to find the
|
|
41
|
+
/** Function to find the app root URI for a given file */
|
|
42
42
|
findAppRootURI?: FindAppRootURI;
|
|
43
43
|
log?: (message: string) => void;
|
|
44
44
|
/** Callback to notify when unable to infer properties for a variable */
|
|
@@ -373,8 +373,8 @@ function findCurrentNode(
|
|
|
373
373
|
finder.current = last(current.args);
|
|
374
374
|
} else if (current.variable && isCovered(cursor, current.variable.position)) {
|
|
375
375
|
finder.current = current.variable;
|
|
376
|
-
} else if (current.
|
|
377
|
-
finder.current = current.
|
|
376
|
+
} else if (current.partial && isCovered(cursor, current.partial.position)) {
|
|
377
|
+
finder.current = current.partial;
|
|
378
378
|
}
|
|
379
379
|
|
|
380
380
|
break;
|
|
@@ -442,7 +442,8 @@ function findCurrentNode(
|
|
|
442
442
|
case NodeTypes.ExportMarkup:
|
|
443
443
|
case NodeTypes.RedirectToMarkup:
|
|
444
444
|
case NodeTypes.IncludeFormMarkup:
|
|
445
|
-
case NodeTypes.SpamProtectionMarkup:
|
|
445
|
+
case NodeTypes.SpamProtectionMarkup:
|
|
446
|
+
case NodeTypes.AssignPushRhs: {
|
|
446
447
|
break;
|
|
447
448
|
}
|
|
448
449
|
|
|
@@ -38,8 +38,8 @@ endcase`;
|
|
|
38
38
|
export const tags: TagEntry[] = [
|
|
39
39
|
{
|
|
40
40
|
name: 'render',
|
|
41
|
-
syntax: "{% render '
|
|
42
|
-
syntax_keywords: [{ keyword: '
|
|
41
|
+
syntax: "{% render 'partial' %}",
|
|
42
|
+
syntax_keywords: [{ keyword: 'partial', description: '...' }],
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
name: 'for',
|
|
@@ -2,7 +2,7 @@ import { describe, beforeEach, it, expect } from 'vitest';
|
|
|
2
2
|
import { DocumentManager } from '../../documents';
|
|
3
3
|
import { CompletionsProvider } from '../CompletionsProvider';
|
|
4
4
|
|
|
5
|
-
describe('Module:
|
|
5
|
+
describe('Module: RenderPartialCompletionProvider', async () => {
|
|
6
6
|
let provider: CompletionsProvider;
|
|
7
7
|
|
|
8
8
|
beforeEach(async () => {
|
|
@@ -20,7 +20,7 @@ describe('Module: RenderSnippetCompletionProvider', async () => {
|
|
|
20
20
|
});
|
|
21
21
|
});
|
|
22
22
|
|
|
23
|
-
it('should complete
|
|
23
|
+
it('should complete partials correctly', async () => {
|
|
24
24
|
await expect(provider).to.complete('{% render "', ['product-card', 'image']);
|
|
25
25
|
});
|
|
26
26
|
});
|
|
@@ -3,12 +3,12 @@ import { CompletionsProvider } from '../CompletionsProvider';
|
|
|
3
3
|
import { DocumentManager } from '../../documents';
|
|
4
4
|
import { DocDefinition } from '@platformos/platformos-check-common';
|
|
5
5
|
|
|
6
|
-
const uri = 'file:///
|
|
6
|
+
const uri = 'file:///app/views/partials/product-card.liquid';
|
|
7
7
|
|
|
8
|
-
describe('Module:
|
|
8
|
+
describe('Module: RenderPartialParameterCompletionProvider', async () => {
|
|
9
9
|
let provider: CompletionsProvider;
|
|
10
|
-
const
|
|
11
|
-
const
|
|
10
|
+
const mockPartialName = 'product-card';
|
|
11
|
+
const mockPartialDefinition: DocDefinition = {
|
|
12
12
|
uri,
|
|
13
13
|
liquidDoc: {
|
|
14
14
|
parameters: [
|
|
@@ -61,16 +61,16 @@ describe('Module: RenderSnippetParameterCompletionProvider', async () => {
|
|
|
61
61
|
liquidDrops: async () => [],
|
|
62
62
|
tags: async () => [],
|
|
63
63
|
},
|
|
64
|
-
getDocDefinitionForURI: async (_uri,
|
|
65
|
-
if (
|
|
66
|
-
return
|
|
64
|
+
getDocDefinitionForURI: async (_uri, partialName) => {
|
|
65
|
+
if (mockPartialName === partialName) {
|
|
66
|
+
return mockPartialDefinition;
|
|
67
67
|
}
|
|
68
68
|
},
|
|
69
69
|
});
|
|
70
70
|
});
|
|
71
71
|
|
|
72
72
|
it("provide completion options that doesn't already exist in render tag", async () => {
|
|
73
|
-
await expect(provider).to.complete(`{% render '${
|
|
73
|
+
await expect(provider).to.complete(`{% render '${mockPartialName}', █ %}`, [
|
|
74
74
|
'title',
|
|
75
75
|
'border-radius',
|
|
76
76
|
'no-type',
|
|
@@ -78,12 +78,12 @@ describe('Module: RenderSnippetParameterCompletionProvider', async () => {
|
|
|
78
78
|
'no-type-or-description',
|
|
79
79
|
]);
|
|
80
80
|
await expect(provider).to.complete(
|
|
81
|
-
`{% render '${
|
|
81
|
+
`{% render '${mockPartialName}', title: 'foo', border-radius: 5, █ %}`,
|
|
82
82
|
['no-type', 'no-description', 'no-type-or-description'],
|
|
83
83
|
);
|
|
84
84
|
});
|
|
85
85
|
|
|
86
|
-
it('does not provide completion options if the
|
|
87
|
-
await expect(provider).to.complete(`{% render 'fake-
|
|
86
|
+
it('does not provide completion options if the partial does not exist', async () => {
|
|
87
|
+
await expect(provider).to.complete(`{% render 'fake-partial', █ %}`, []);
|
|
88
88
|
});
|
|
89
89
|
});
|
|
@@ -28,7 +28,7 @@ export class RenderPartialParameterCompletionProvider implements Provider {
|
|
|
28
28
|
!parentNode ||
|
|
29
29
|
node.type !== NodeTypes.VariableLookup ||
|
|
30
30
|
parentNode.type !== NodeTypes.RenderMarkup ||
|
|
31
|
-
parentNode.
|
|
31
|
+
parentNode.partial.type !== 'String'
|
|
32
32
|
) {
|
|
33
33
|
return [];
|
|
34
34
|
}
|
|
@@ -37,7 +37,7 @@ export class RenderPartialParameterCompletionProvider implements Provider {
|
|
|
37
37
|
|
|
38
38
|
const partialDefinition = await this.getDocDefinitionForURI(
|
|
39
39
|
params.textDocument.uri,
|
|
40
|
-
parentNode.
|
|
40
|
+
parentNode.partial.value,
|
|
41
41
|
);
|
|
42
42
|
|
|
43
43
|
const liquidDocParams = partialDefinition?.liquidDoc?.parameters;
|
|
@@ -41,10 +41,10 @@ export class TranslationCompletionProvider implements Provider {
|
|
|
41
41
|
const translations = await this.getTranslationsForURI(params.textDocument.uri);
|
|
42
42
|
const partial = node.value;
|
|
43
43
|
|
|
44
|
-
// We only want to show
|
|
45
|
-
//
|
|
44
|
+
// We only want to show platformos system translations if the user is already
|
|
45
|
+
// typing that namespace prefix. Otherwise it's too noisy.
|
|
46
46
|
const options = translationOptions(translations).filter(
|
|
47
|
-
(option) => !option.path[0]?.startsWith('
|
|
47
|
+
(option) => !option.path[0]?.startsWith('platformos') || partial.startsWith('platformos'),
|
|
48
48
|
);
|
|
49
49
|
|
|
50
50
|
const [_currentNode, realAncestors] =
|
|
@@ -46,7 +46,7 @@ describe('Module: runChecks', () => {
|
|
|
46
46
|
let runChecks: ReturnType<typeof makeRunChecks>;
|
|
47
47
|
let fs: MockFileSystem;
|
|
48
48
|
const rootUri = path.normalize('browser:///app');
|
|
49
|
-
const fileUri = path.join(rootUri, 'app', 'input.liquid');
|
|
49
|
+
const fileUri = path.join(rootUri, 'app', 'views', 'pages', 'input.liquid');
|
|
50
50
|
|
|
51
51
|
beforeEach(() => {
|
|
52
52
|
connection = {
|
|
@@ -58,7 +58,7 @@ describe('Module: runChecks', () => {
|
|
|
58
58
|
fs = new MockFileSystem(
|
|
59
59
|
{
|
|
60
60
|
'.pos': '',
|
|
61
|
-
'app/input.liquid': `{{ 'any' | filter }}`,
|
|
61
|
+
'app/views/pages/input.liquid': `{{ 'any' | filter }}`,
|
|
62
62
|
'.git/test': 'test',
|
|
63
63
|
'modules/test': 'test',
|
|
64
64
|
},
|
|
@@ -140,7 +140,7 @@ describe('Module: runChecks', () => {
|
|
|
140
140
|
it('should send diagnostics per URI when there are errors', async () => {
|
|
141
141
|
const files = [
|
|
142
142
|
{
|
|
143
|
-
fileURI: path.join(rootUri, 'app', 'input1.liquid'),
|
|
143
|
+
fileURI: path.join(rootUri, 'app', 'views', 'pages', 'input1.liquid'),
|
|
144
144
|
fileContents: `{{ 'any' | filter }}`,
|
|
145
145
|
fileVersion: 0,
|
|
146
146
|
diagnostics: [
|
|
@@ -163,7 +163,7 @@ describe('Module: runChecks', () => {
|
|
|
163
163
|
],
|
|
164
164
|
},
|
|
165
165
|
{
|
|
166
|
-
fileURI: path.join(rootUri, 'app', 'input2.liquid'),
|
|
166
|
+
fileURI: path.join(rootUri, 'app', 'views', 'pages', 'input2.liquid'),
|
|
167
167
|
// same but on a new line
|
|
168
168
|
fileContents: `\n{{ 'any' | filter }}`,
|
|
169
169
|
fileVersion: 0,
|
|
@@ -192,7 +192,7 @@ describe('Module: runChecks', () => {
|
|
|
192
192
|
documentManager.open(fileURI, fileContents, fileVersion);
|
|
193
193
|
});
|
|
194
194
|
|
|
195
|
-
await runChecks([path.join(rootUri, 'app', 'input1.liquid')]);
|
|
195
|
+
await runChecks([path.join(rootUri, 'app', 'views', 'pages', 'input1.liquid')]);
|
|
196
196
|
|
|
197
197
|
files.forEach(({ fileURI, fileVersion, diagnostics }) => {
|
|
198
198
|
expect(connection.sendDiagnostics).toBeCalledWith({
|
|
@@ -250,7 +250,7 @@ describe('Module: runChecks', () => {
|
|
|
250
250
|
source: 'platformos-check',
|
|
251
251
|
code: 'MatchingTranslations',
|
|
252
252
|
codeDescription: { href: expect.any(String) },
|
|
253
|
-
message: `A
|
|
253
|
+
message: `A translation for 'hi' does not exist in the en locale`,
|
|
254
254
|
severity: 1,
|
|
255
255
|
range: {
|
|
256
256
|
// 'fr:\n hello: bonjour\n hi: salut'
|
|
@@ -53,12 +53,12 @@ function documentLinksVisitor(
|
|
|
53
53
|
if (
|
|
54
54
|
(node.name === 'render' || node.name === 'include') &&
|
|
55
55
|
typeof node.markup !== 'string' &&
|
|
56
|
-
isLiquidString(node.markup.
|
|
56
|
+
isLiquidString(node.markup.partial)
|
|
57
57
|
) {
|
|
58
|
-
const
|
|
58
|
+
const partial = node.markup.partial;
|
|
59
59
|
return DocumentLink.create(
|
|
60
|
-
range(textDocument,
|
|
61
|
-
await documentsLocator.locate(root, node.name,
|
|
60
|
+
range(textDocument, partial),
|
|
61
|
+
await documentsLocator.locate(root, node.name, partial.value),
|
|
62
62
|
);
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -67,10 +67,10 @@ function documentLinksVisitor(
|
|
|
67
67
|
typeof node.markup !== 'string' &&
|
|
68
68
|
isLiquidString(node.markup.partial)
|
|
69
69
|
) {
|
|
70
|
-
const
|
|
70
|
+
const partial = node.markup.partial;
|
|
71
71
|
return DocumentLink.create(
|
|
72
|
-
range(textDocument,
|
|
73
|
-
await documentsLocator.locate(root, node.name,
|
|
72
|
+
range(textDocument, partial),
|
|
73
|
+
await documentsLocator.locate(root, node.name, partial.value),
|
|
74
74
|
);
|
|
75
75
|
}
|
|
76
76
|
|