@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
|
@@ -20,7 +20,7 @@ describe('Module: DocumentManager', () => {
|
|
|
20
20
|
it('should return an app for a root', () => {
|
|
21
21
|
// these will be different in windows vs unix
|
|
22
22
|
const rootUri = URI.file(__dirname);
|
|
23
|
-
const fileUri = Utils.joinPath(rootUri, 'test.liquid');
|
|
23
|
+
const fileUri = Utils.joinPath(rootUri, 'app', 'views', 'partials', 'test.liquid');
|
|
24
24
|
|
|
25
25
|
// We expect forward slash paths (windows path get normalized)
|
|
26
26
|
expect(fileUri.path).not.to.include('\\');
|
|
@@ -37,8 +37,8 @@ describe('Module: DocumentManager', () => {
|
|
|
37
37
|
beforeEach(async () => {
|
|
38
38
|
fs = new MockFileSystem(
|
|
39
39
|
{
|
|
40
|
-
'
|
|
41
|
-
'
|
|
40
|
+
'app/views/partials/foo.liquid': `hello {% render 'bar' %}`,
|
|
41
|
+
'app/views/partials/bar.liquid': `world`,
|
|
42
42
|
},
|
|
43
43
|
'mock-fs:',
|
|
44
44
|
);
|
|
@@ -52,14 +52,18 @@ describe('Module: DocumentManager', () => {
|
|
|
52
52
|
});
|
|
53
53
|
|
|
54
54
|
it('preloads source codes with a version of undefined', async () => {
|
|
55
|
-
const sc = documentManager.get('mock-fs:/
|
|
55
|
+
const sc = documentManager.get('mock-fs:/app/views/partials/foo.liquid');
|
|
56
56
|
assert(sc);
|
|
57
57
|
expect(sc.version).to.equal(undefined);
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
it('returns defined versions of opened files', () => {
|
|
61
|
-
documentManager.open(
|
|
62
|
-
|
|
61
|
+
documentManager.open(
|
|
62
|
+
'mock-fs:/app/views/partials/foo.liquid',
|
|
63
|
+
'hello {% render "bar" %}',
|
|
64
|
+
0,
|
|
65
|
+
);
|
|
66
|
+
const sc = documentManager.get('mock-fs:/app/views/partials/foo.liquid');
|
|
63
67
|
assert(sc);
|
|
64
68
|
expect(sc.version).to.equal(0);
|
|
65
69
|
});
|
|
@@ -78,9 +82,13 @@ describe('Module: DocumentManager', () => {
|
|
|
78
82
|
|
|
79
83
|
describe('Unit: close(uri)', () => {
|
|
80
84
|
it('sets the source version to undefined (value is on disk)', () => {
|
|
81
|
-
documentManager.open(
|
|
82
|
-
|
|
83
|
-
|
|
85
|
+
documentManager.open(
|
|
86
|
+
'mock-fs:/app/views/partials/foo.liquid',
|
|
87
|
+
'hello {% render "bar" %}',
|
|
88
|
+
10,
|
|
89
|
+
);
|
|
90
|
+
documentManager.close('mock-fs:/app/views/partials/foo.liquid');
|
|
91
|
+
const sc = documentManager.get('mock-fs:/app/views/partials/foo.liquid');
|
|
84
92
|
assert(sc);
|
|
85
93
|
expect(sc.source).to.equal('hello {% render "bar" %}');
|
|
86
94
|
expect(sc.version).to.equal(undefined);
|
|
@@ -90,9 +98,13 @@ describe('Module: DocumentManager', () => {
|
|
|
90
98
|
describe('Unit: delete(uri)', () => {
|
|
91
99
|
it('deletes the source code from the document manager', () => {
|
|
92
100
|
// as though the file no longer exists
|
|
93
|
-
documentManager.open(
|
|
94
|
-
|
|
95
|
-
|
|
101
|
+
documentManager.open(
|
|
102
|
+
'mock-fs:/app/views/partials/foo.liquid',
|
|
103
|
+
'hello {% render "bar" %}',
|
|
104
|
+
10,
|
|
105
|
+
);
|
|
106
|
+
documentManager.delete('mock-fs:/app/views/partials/foo.liquid');
|
|
107
|
+
const sc = documentManager.get('mock-fs:/app/views/partials/foo.liquid');
|
|
96
108
|
assert(!sc);
|
|
97
109
|
});
|
|
98
110
|
});
|
|
@@ -131,16 +143,16 @@ describe('Module: DocumentManager', () => {
|
|
|
131
143
|
|
|
132
144
|
fs = new MockFileSystem(
|
|
133
145
|
{
|
|
134
|
-
'
|
|
135
|
-
'
|
|
136
|
-
'
|
|
137
|
-
'
|
|
138
|
-
'
|
|
139
|
-
'
|
|
140
|
-
'
|
|
141
|
-
'
|
|
142
|
-
'
|
|
143
|
-
'
|
|
146
|
+
'app/views/partials/1.liquid': `hello {% render 'bar' %}`,
|
|
147
|
+
'app/views/partials/2.liquid': `hello {% render 'bar' %}`,
|
|
148
|
+
'app/views/partials/3.liquid': `hello {% render 'bar' %}`,
|
|
149
|
+
'app/views/partials/4.liquid': `hello {% render 'bar' %}`,
|
|
150
|
+
'app/views/partials/5.liquid': `hello {% render 'bar' %}`,
|
|
151
|
+
'app/views/partials/6.liquid': `hello {% render 'bar' %}`,
|
|
152
|
+
'app/views/partials/7.liquid': `hello {% render 'bar' %}`,
|
|
153
|
+
'app/views/partials/8.liquid': `hello {% render 'bar' %}`,
|
|
154
|
+
'app/views/partials/9.liquid': `hello {% render 'bar' %}`,
|
|
155
|
+
'app/views/partials/10.liquid': `hello {% render 'bar' %}`,
|
|
144
156
|
},
|
|
145
157
|
mockRoot,
|
|
146
158
|
);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
assertNever,
|
|
3
|
+
isKnownLiquidFile,
|
|
3
4
|
memoize,
|
|
4
5
|
path,
|
|
5
6
|
recursiveReadDirectory,
|
|
@@ -78,8 +79,12 @@ export class DocumentManager {
|
|
|
78
79
|
public app(root: UriString, includeFilesFromDisk = false): AugmentedSourceCode[] {
|
|
79
80
|
return [...this.sourceCodes.values()]
|
|
80
81
|
.filter((sourceCode) => sourceCode.uri.startsWith(root))
|
|
82
|
+
.filter((sourceCode) => includeFilesFromDisk || sourceCode.version !== undefined)
|
|
81
83
|
.filter(
|
|
82
|
-
|
|
84
|
+
// Exclude .liquid files that aren't in a recognized platformOS directory
|
|
85
|
+
// (e.g. generator templates). Non-liquid files are always included.
|
|
86
|
+
(sourceCode) =>
|
|
87
|
+
sourceCode.type !== SourceCodeType.LiquidHtml || isKnownLiquidFile(sourceCode.uri),
|
|
83
88
|
) satisfies App;
|
|
84
89
|
}
|
|
85
90
|
|
|
@@ -6,7 +6,7 @@ import { formatLiquidDocTagHandle, SUPPORTED_LIQUID_DOC_TAG_HANDLES } from '../.
|
|
|
6
6
|
import { TranslationProvider } from '@platformos/platformos-common';
|
|
7
7
|
import { MockFileSystem } from '@platformos/platformos-check-common/src/test';
|
|
8
8
|
|
|
9
|
-
describe('Module:
|
|
9
|
+
describe('Module: RenderPartialParameterHoverProvider', async () => {
|
|
10
10
|
let provider: HoverProvider;
|
|
11
11
|
|
|
12
12
|
beforeEach(() => {
|
|
@@ -6,11 +6,11 @@ import { GetDocDefinitionForURI, DocDefinition } from '@platformos/platformos-ch
|
|
|
6
6
|
import { TranslationProvider } from '@platformos/platformos-common';
|
|
7
7
|
import { MockFileSystem } from '@platformos/platformos-check-common/src/test';
|
|
8
8
|
|
|
9
|
-
const uri = 'file:///
|
|
9
|
+
const uri = 'file:///app/views/partials/product-card.liquid';
|
|
10
10
|
|
|
11
|
-
describe('Module:
|
|
11
|
+
describe('Module: RenderPartialHoverProvider', async () => {
|
|
12
12
|
let provider: HoverProvider;
|
|
13
|
-
const
|
|
13
|
+
const mockPartialDefinition: DocDefinition = {
|
|
14
14
|
uri,
|
|
15
15
|
liquidDoc: {
|
|
16
16
|
parameters: [
|
|
@@ -36,10 +36,10 @@ describe('Module: RenderSnippetHoverProvider', async () => {
|
|
|
36
36
|
};
|
|
37
37
|
|
|
38
38
|
describe('hover', () => {
|
|
39
|
-
it('should return
|
|
40
|
-
provider = createProvider(async () =>
|
|
39
|
+
it('should return partial definition with all parameters', async () => {
|
|
40
|
+
provider = createProvider(async () => mockPartialDefinition);
|
|
41
41
|
// prettier-ignore
|
|
42
|
-
const expectedHoverContent =
|
|
42
|
+
const expectedHoverContent =
|
|
43
43
|
`### product-card
|
|
44
44
|
|
|
45
45
|
**Description:**
|
|
@@ -59,13 +59,13 @@ This is a description
|
|
|
59
59
|
});
|
|
60
60
|
|
|
61
61
|
it('should return nothing if not in render tag', async () => {
|
|
62
|
-
await expect(provider).to.hover(`{% assign asdf = '
|
|
63
|
-
await expect(provider).to.hover(`{{ '
|
|
62
|
+
await expect(provider).to.hover(`{% assign asdf = 'any-str█ing' %}`, null);
|
|
63
|
+
await expect(provider).to.hover(`{{ 'any-str█ing' }}`, null);
|
|
64
64
|
});
|
|
65
65
|
});
|
|
66
66
|
});
|
|
67
67
|
|
|
68
|
-
const createProvider = (
|
|
68
|
+
const createProvider = (getPartialDefinition: GetDocDefinitionForURI) => {
|
|
69
69
|
return new HoverProvider(
|
|
70
70
|
new DocumentManager(),
|
|
71
71
|
{
|
|
@@ -77,6 +77,6 @@ const createProvider = (getSnippetDefinition: GetDocDefinitionForURI) => {
|
|
|
77
77
|
},
|
|
78
78
|
new TranslationProvider(new MockFileSystem({})),
|
|
79
79
|
async () => ({}),
|
|
80
|
-
|
|
80
|
+
getPartialDefinition,
|
|
81
81
|
);
|
|
82
82
|
};
|
|
@@ -6,12 +6,12 @@ import { GetDocDefinitionForURI, DocDefinition } from '@platformos/platformos-ch
|
|
|
6
6
|
import { TranslationProvider } from '@platformos/platformos-common';
|
|
7
7
|
import { MockFileSystem } from '@platformos/platformos-check-common/src/test';
|
|
8
8
|
|
|
9
|
-
const uri = 'file:///
|
|
9
|
+
const uri = 'file:///app/views/partials/product-card.liquid';
|
|
10
10
|
|
|
11
|
-
describe('Module:
|
|
11
|
+
describe('Module: RenderPartialParameterHoverProvider', async () => {
|
|
12
12
|
let provider: HoverProvider;
|
|
13
|
-
let
|
|
14
|
-
const
|
|
13
|
+
let getPartialDefinition: GetDocDefinitionForURI;
|
|
14
|
+
const mockPartialDefinition: DocDefinition = {
|
|
15
15
|
uri,
|
|
16
16
|
liquidDoc: {
|
|
17
17
|
parameters: [
|
|
@@ -28,12 +28,12 @@ describe('Module: RenderSnippetParameterHoverProvider', async () => {
|
|
|
28
28
|
|
|
29
29
|
describe('hover', () => {
|
|
30
30
|
beforeEach(() => {
|
|
31
|
-
provider = createProvider(async () =>
|
|
31
|
+
provider = createProvider(async () => mockPartialDefinition);
|
|
32
32
|
});
|
|
33
33
|
|
|
34
34
|
it('should return null if doc definition not found', async () => {
|
|
35
|
-
|
|
36
|
-
provider = createProvider(
|
|
35
|
+
getPartialDefinition = async () => undefined;
|
|
36
|
+
provider = createProvider(getPartialDefinition);
|
|
37
37
|
await expect(provider).to.hover(`{% render 'product-card' tit█le: 'value' %}`, null);
|
|
38
38
|
});
|
|
39
39
|
|
|
@@ -50,7 +50,7 @@ describe('Module: RenderSnippetParameterHoverProvider', async () => {
|
|
|
50
50
|
});
|
|
51
51
|
});
|
|
52
52
|
|
|
53
|
-
const createProvider = (
|
|
53
|
+
const createProvider = (getPartialDefinition: GetDocDefinitionForURI) => {
|
|
54
54
|
return new HoverProvider(
|
|
55
55
|
new DocumentManager(),
|
|
56
56
|
{
|
|
@@ -62,6 +62,6 @@ const createProvider = (getSnippetDefinition: GetDocDefinitionForURI) => {
|
|
|
62
62
|
},
|
|
63
63
|
new TranslationProvider(new MockFileSystem({})),
|
|
64
64
|
async () => ({}),
|
|
65
|
-
|
|
65
|
+
getPartialDefinition,
|
|
66
66
|
);
|
|
67
67
|
};
|
|
@@ -17,14 +17,14 @@ export class RenderPartialParameterHoverProvider implements BaseHoverProvider {
|
|
|
17
17
|
currentNode.type !== NodeTypes.NamedArgument ||
|
|
18
18
|
!parentNode ||
|
|
19
19
|
parentNode.type !== NodeTypes.RenderMarkup ||
|
|
20
|
-
parentNode.
|
|
20
|
+
parentNode.partial.type !== NodeTypes.String
|
|
21
21
|
) {
|
|
22
22
|
return null;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
const docDefinition = await this.getDocDefinitionForURI(
|
|
26
26
|
params.textDocument.uri,
|
|
27
|
-
parentNode.
|
|
27
|
+
parentNode.partial.value,
|
|
28
28
|
);
|
|
29
29
|
|
|
30
30
|
const paramName = currentNode.name;
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
Config as
|
|
2
|
+
Config as PlatformOSCheckConfig,
|
|
3
3
|
allChecks,
|
|
4
4
|
recommended as recommendedChecks,
|
|
5
5
|
SourceCodeType,
|
|
@@ -20,7 +20,7 @@ export {
|
|
|
20
20
|
export { debounce, memo, parseJSON, ArgumentTypes } from './utils';
|
|
21
21
|
export { startServer } from './server';
|
|
22
22
|
export {
|
|
23
|
-
|
|
23
|
+
PlatformOSCheckConfig,
|
|
24
24
|
recommendedChecks,
|
|
25
25
|
allChecks,
|
|
26
26
|
AbstractFileSystem,
|
|
@@ -17,7 +17,7 @@ import { ClientCapabilities } from '../ClientCapabilities';
|
|
|
17
17
|
import { FindAppRootURI } from '../internal-types';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* RenameProvider is responsible for providing rename support for the
|
|
20
|
+
* RenameProvider is responsible for providing rename support for the platformOS language server.
|
|
21
21
|
*
|
|
22
22
|
* Rename is a pretty abstract concept, it can be renaming a tag name, a variable, a class name, etc.
|
|
23
23
|
*/
|
|
@@ -104,8 +104,8 @@ export class LiquidVariableRenameProvider implements BaseRenameProvider {
|
|
|
104
104
|
});
|
|
105
105
|
|
|
106
106
|
if (this.clientCapabilities.hasApplyEditSupport && liquidDocParamUpdated) {
|
|
107
|
-
const
|
|
108
|
-
const liquidSourceCodes =
|
|
107
|
+
const appFiles = this.documentManager.app(rootUri, true);
|
|
108
|
+
const liquidSourceCodes = appFiles.filter(isLiquidSourceCode);
|
|
109
109
|
const name = partialName(params.textDocument.uri);
|
|
110
110
|
|
|
111
111
|
await updateRenderTags(this.connection, liquidSourceCodes, name, oldName, params.newName);
|
|
@@ -242,7 +242,7 @@ async function updateRenderTags(
|
|
|
242
242
|
const textDocument = sourceCode.textDocument;
|
|
243
243
|
const edits: TextEdit[] = await visit<SourceCodeType.LiquidHtml, TextEdit>(sourceCode.ast, {
|
|
244
244
|
async RenderMarkup(node: RenderMarkup) {
|
|
245
|
-
if (node.
|
|
245
|
+
if (node.partial.type !== NodeTypes.String || node.partial.value !== partialName) {
|
|
246
246
|
return;
|
|
247
247
|
}
|
|
248
248
|
|
|
@@ -22,9 +22,9 @@ describe('Module: AssetRenameHandler', () => {
|
|
|
22
22
|
capabilities = new ClientCapabilities();
|
|
23
23
|
fs = new MockFileSystem(
|
|
24
24
|
{
|
|
25
|
-
'assets/oldName.js': 'console.log("Hello, world!")',
|
|
26
|
-
'
|
|
27
|
-
'
|
|
25
|
+
'app/assets/oldName.js': 'console.log("Hello, world!")',
|
|
26
|
+
'app/views/partials/section.liquid': `<script src="{{ 'oldName.js' | asset_url }}" defer></script>`,
|
|
27
|
+
'app/views/partials/block.liquid': `{{ 'oldName.js' | asset_url | script_tag }} oldName.js`,
|
|
28
28
|
},
|
|
29
29
|
mockRoot,
|
|
30
30
|
);
|
|
@@ -45,8 +45,8 @@ describe('Module: AssetRenameHandler', () => {
|
|
|
45
45
|
await handler.onDidRenameFiles({
|
|
46
46
|
files: [
|
|
47
47
|
{
|
|
48
|
-
oldUri: 'mock-fs:/assets/oldName.js',
|
|
49
|
-
newUri: 'mock-fs:/assets/newName.js',
|
|
48
|
+
oldUri: 'mock-fs:/app/assets/oldName.js',
|
|
49
|
+
newUri: 'mock-fs:/app/assets/newName.js',
|
|
50
50
|
},
|
|
51
51
|
],
|
|
52
52
|
});
|
|
@@ -67,8 +67,8 @@ describe('Module: AssetRenameHandler', () => {
|
|
|
67
67
|
await handler.onDidRenameFiles({
|
|
68
68
|
files: [
|
|
69
69
|
{
|
|
70
|
-
oldUri: 'mock-fs:/assets/oldName.js',
|
|
71
|
-
newUri: 'mock-fs:/assets/newName.js',
|
|
70
|
+
oldUri: 'mock-fs:/app/assets/oldName.js',
|
|
71
|
+
newUri: 'mock-fs:/app/assets/newName.js',
|
|
72
72
|
},
|
|
73
73
|
],
|
|
74
74
|
});
|
|
@@ -90,7 +90,7 @@ describe('Module: AssetRenameHandler', () => {
|
|
|
90
90
|
documentChanges: [
|
|
91
91
|
{
|
|
92
92
|
textDocument: {
|
|
93
|
-
uri: 'mock-fs:/
|
|
93
|
+
uri: 'mock-fs:/app/views/partials/section.liquid',
|
|
94
94
|
version: null,
|
|
95
95
|
},
|
|
96
96
|
edits: [expectedTextEdit],
|
|
@@ -98,7 +98,7 @@ describe('Module: AssetRenameHandler', () => {
|
|
|
98
98
|
},
|
|
99
99
|
{
|
|
100
100
|
textDocument: {
|
|
101
|
-
uri: 'mock-fs:/
|
|
101
|
+
uri: 'mock-fs:/app/views/partials/block.liquid',
|
|
102
102
|
version: null,
|
|
103
103
|
},
|
|
104
104
|
edits: [expectedTextEdit],
|
|
@@ -113,8 +113,8 @@ describe('Module: AssetRenameHandler', () => {
|
|
|
113
113
|
await handler.onDidRenameFiles({
|
|
114
114
|
files: [
|
|
115
115
|
{
|
|
116
|
-
oldUri: 'mock-fs:/assets/oldName.js',
|
|
117
|
-
newUri: 'mock-fs:/assets/newName.js',
|
|
116
|
+
oldUri: 'mock-fs:/app/assets/oldName.js',
|
|
117
|
+
newUri: 'mock-fs:/app/assets/newName.js',
|
|
118
118
|
},
|
|
119
119
|
],
|
|
120
120
|
});
|
|
@@ -122,9 +122,9 @@ describe('Module: AssetRenameHandler', () => {
|
|
|
122
122
|
const params: ApplyWorkspaceEditParams = connection.spies.sendRequest.mock.calls[0][1];
|
|
123
123
|
const expectedFs = new MockFileSystem(
|
|
124
124
|
{
|
|
125
|
-
'assets/oldName.js': 'console.log("Hello, world!")',
|
|
126
|
-
'
|
|
127
|
-
'
|
|
125
|
+
'app/assets/oldName.js': 'console.log("Hello, world!")',
|
|
126
|
+
'app/views/partials/section.liquid': `<script src="{{ 'newName.js' | asset_url }}" defer></script>`,
|
|
127
|
+
'app/views/partials/block.liquid': `{{ 'newName.js' | asset_url | script_tag }} oldName.js`,
|
|
128
128
|
},
|
|
129
129
|
'mock-fs:',
|
|
130
130
|
);
|
|
@@ -145,8 +145,8 @@ describe('Module: AssetRenameHandler', () => {
|
|
|
145
145
|
await handler.onDidRenameFiles({
|
|
146
146
|
files: [
|
|
147
147
|
{
|
|
148
|
-
oldUri: 'mock-fs:/assets/oldName.js',
|
|
149
|
-
newUri: `mock-fs:/assets/newName.js.liquid`,
|
|
148
|
+
oldUri: 'mock-fs:/app/assets/oldName.js',
|
|
149
|
+
newUri: `mock-fs:/app/assets/newName.js.liquid`,
|
|
150
150
|
},
|
|
151
151
|
],
|
|
152
152
|
});
|
|
@@ -154,9 +154,9 @@ describe('Module: AssetRenameHandler', () => {
|
|
|
154
154
|
const params: ApplyWorkspaceEditParams = connection.spies.sendRequest.mock.calls[0][1];
|
|
155
155
|
const expectedFs = new MockFileSystem(
|
|
156
156
|
{
|
|
157
|
-
'assets/oldName.js': 'console.log("Hello, world!")',
|
|
158
|
-
'
|
|
159
|
-
'
|
|
157
|
+
'app/assets/oldName.js': 'console.log("Hello, world!")',
|
|
158
|
+
'app/views/partials/section.liquid': `<script src="{{ 'newName.js' | asset_url }}" defer></script>`,
|
|
159
|
+
'app/views/partials/block.liquid': `{{ 'newName.js' | asset_url | script_tag }} oldName.js`,
|
|
160
160
|
},
|
|
161
161
|
'mock-fs:',
|
|
162
162
|
);
|
|
@@ -176,8 +176,8 @@ describe('Module: AssetRenameHandler', () => {
|
|
|
176
176
|
it('handles .css.liquid files', async () => {
|
|
177
177
|
fs = new MockFileSystem(
|
|
178
178
|
{
|
|
179
|
-
'assets/oldName.css.liquid': 'body { color: red; }',
|
|
180
|
-
'
|
|
179
|
+
'app/assets/oldName.css.liquid': 'body { color: red; }',
|
|
180
|
+
'app/views/partials/section.liquid': `{% echo 'oldName.css' | asset_url | stylesheet_tag %}`,
|
|
181
181
|
},
|
|
182
182
|
'mock-fs:',
|
|
183
183
|
);
|
|
@@ -187,8 +187,8 @@ describe('Module: AssetRenameHandler', () => {
|
|
|
187
187
|
await handler.onDidRenameFiles({
|
|
188
188
|
files: [
|
|
189
189
|
{
|
|
190
|
-
oldUri: 'mock-fs:/assets/oldName.css.liquid',
|
|
191
|
-
newUri: `mock-fs:/assets/newName.css.liquid`,
|
|
190
|
+
oldUri: 'mock-fs:/app/assets/oldName.css.liquid',
|
|
191
|
+
newUri: `mock-fs:/app/assets/newName.css.liquid`,
|
|
192
192
|
},
|
|
193
193
|
],
|
|
194
194
|
});
|
|
@@ -196,8 +196,8 @@ describe('Module: AssetRenameHandler', () => {
|
|
|
196
196
|
const params: ApplyWorkspaceEditParams = connection.spies.sendRequest.mock.calls[0][1];
|
|
197
197
|
const expectedFs = new MockFileSystem(
|
|
198
198
|
{
|
|
199
|
-
'assets/newName.css.liquid': 'body { color: red; }',
|
|
200
|
-
'
|
|
199
|
+
'app/assets/newName.css.liquid': 'body { color: red; }',
|
|
200
|
+
'app/views/partials/section.liquid': `{% echo 'newName.css' | asset_url | stylesheet_tag %}`,
|
|
201
201
|
},
|
|
202
202
|
'mock-fs:',
|
|
203
203
|
);
|
|
@@ -22,7 +22,7 @@ import { FindAppRootURI } from '../../internal-types';
|
|
|
22
22
|
*
|
|
23
23
|
* We'll do that for `.(css|js).liquid` files as well
|
|
24
24
|
*
|
|
25
|
-
* We'll do this by visiting all the liquid files in the
|
|
25
|
+
* We'll do this by visiting all the liquid files in the app and looking for
|
|
26
26
|
* string | asset_url Variable nodes that reference the old asset. We'll then create a
|
|
27
27
|
* WorkspaceEdit that changes the references to the new asset.
|
|
28
28
|
*/
|
|
@@ -21,8 +21,8 @@ describe('Module: PartialRenameHandler', () => {
|
|
|
21
21
|
capabilities = new ClientCapabilities();
|
|
22
22
|
fs = new MockFileSystem(
|
|
23
23
|
{
|
|
24
|
-
'
|
|
25
|
-
'
|
|
24
|
+
'app/views/partials/page.liquid': `<div>{% render 'oldName', foo: 'bar' %}oldName</div>`,
|
|
25
|
+
'app/lib/component.liquid': `<div>{% render 'oldName', foo: 'baz' %}</div>`,
|
|
26
26
|
'app/views/partials/oldName.liquid': `<div>oldName{%</div>`,
|
|
27
27
|
'app/views/partials/other.liquid': `<div>{% render 'oldName' %}{% render 'other' %}</div>`,
|
|
28
28
|
},
|
|
@@ -90,7 +90,7 @@ describe('Module: PartialRenameHandler', () => {
|
|
|
90
90
|
documentChanges: [
|
|
91
91
|
{
|
|
92
92
|
textDocument: {
|
|
93
|
-
uri: 'mock-fs:/
|
|
93
|
+
uri: 'mock-fs:/app/views/partials/page.liquid',
|
|
94
94
|
version: null,
|
|
95
95
|
},
|
|
96
96
|
edits: [expectedTextEdit],
|
|
@@ -98,7 +98,7 @@ describe('Module: PartialRenameHandler', () => {
|
|
|
98
98
|
},
|
|
99
99
|
{
|
|
100
100
|
textDocument: {
|
|
101
|
-
uri: 'mock-fs:/
|
|
101
|
+
uri: 'mock-fs:/app/views/partials/other.liquid',
|
|
102
102
|
version: null,
|
|
103
103
|
},
|
|
104
104
|
edits: [expectedTextEdit],
|
|
@@ -106,7 +106,7 @@ describe('Module: PartialRenameHandler', () => {
|
|
|
106
106
|
},
|
|
107
107
|
{
|
|
108
108
|
textDocument: {
|
|
109
|
-
uri: 'mock-fs:/app/
|
|
109
|
+
uri: 'mock-fs:/app/lib/component.liquid',
|
|
110
110
|
version: null,
|
|
111
111
|
},
|
|
112
112
|
edits: [expectedTextEdit],
|
|
@@ -130,8 +130,8 @@ describe('Module: PartialRenameHandler', () => {
|
|
|
130
130
|
const params: ApplyWorkspaceEditParams = connection.spies.sendRequest.mock.calls[0][1];
|
|
131
131
|
const expectedFs = new MockFileSystem(
|
|
132
132
|
{
|
|
133
|
-
'
|
|
134
|
-
'
|
|
133
|
+
'app/views/partials/page.liquid': `<div>{% render 'newName', foo: 'bar' %}oldName</div>`,
|
|
134
|
+
'app/lib/component.liquid': `<div>{% render 'newName', foo: 'baz' %}</div>`,
|
|
135
135
|
'app/views/partials/newName.liquid': `<div>oldName{%</div>`,
|
|
136
136
|
'app/views/partials/other.liquid': `<div>{% render 'newName' %}{% render 'other' %}</div>`,
|
|
137
137
|
},
|
|
@@ -22,7 +22,7 @@ import { FindAppRootURI } from '../../internal-types';
|
|
|
22
22
|
*
|
|
23
23
|
* {% render 'oldName' %} -> {% render 'newName' %}
|
|
24
24
|
*
|
|
25
|
-
* We'll do this by visiting all the liquid files in the
|
|
25
|
+
* We'll do this by visiting all the liquid files in the app and looking for
|
|
26
26
|
* render and include tags that reference the old partial. We'll then create a
|
|
27
27
|
* WorkspaceEdit that changes the references to the new partial.
|
|
28
28
|
*/
|
|
@@ -73,13 +73,13 @@ export class PartialRenameHandler implements BaseRenameHandler {
|
|
|
73
73
|
if (typeof node.markup === 'string') {
|
|
74
74
|
return;
|
|
75
75
|
}
|
|
76
|
-
const
|
|
77
|
-
if (
|
|
76
|
+
const partial = node.markup.partial;
|
|
77
|
+
if (partial.type === NodeTypes.String && partial.value === oldPartialName) {
|
|
78
78
|
return {
|
|
79
79
|
newText: `${newPartialName}`,
|
|
80
80
|
range: Range.create(
|
|
81
|
-
textDocument.positionAt(
|
|
82
|
-
textDocument.positionAt(
|
|
81
|
+
textDocument.positionAt(partial.position.start + 1), // +1 to skip the opening quote
|
|
82
|
+
textDocument.positionAt(partial.position.end - 1), // -1 to skip the closing quote
|
|
83
83
|
),
|
|
84
84
|
};
|
|
85
85
|
}
|
package/src/server/safe.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* @param defaultReturnValue
|
|
15
15
|
*
|
|
16
16
|
* @example
|
|
17
|
-
* const
|
|
17
|
+
* const getPartialNames = safe(async function () { ... }, []);
|
|
18
18
|
*/
|
|
19
19
|
export const safe = <T extends (...args: any[]) => Promise<any>>(
|
|
20
20
|
fn: T,
|
|
@@ -16,8 +16,8 @@ import { startServer } from './startServer';
|
|
|
16
16
|
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
17
17
|
|
|
18
18
|
describe('Module: server', () => {
|
|
19
|
-
const mockRoot = path.normalize('browser:/
|
|
20
|
-
const filePath = 'app/code.liquid';
|
|
19
|
+
const mockRoot = path.normalize('browser:/app');
|
|
20
|
+
const filePath = 'app/views/partials/code.liquid';
|
|
21
21
|
const fileURI = path.join(mockRoot, filePath);
|
|
22
22
|
const fileContents = `{% render 'foo' %}`;
|
|
23
23
|
let checkOnChange: boolean | null = null;
|
|
@@ -60,7 +60,7 @@ describe('Module: server', () => {
|
|
|
60
60
|
|
|
61
61
|
fileTree = {
|
|
62
62
|
'.pos': '',
|
|
63
|
-
'app/code.liquid': fileContents,
|
|
63
|
+
'app/views/partials/code.liquid': fileContents,
|
|
64
64
|
'.git/test': 'test',
|
|
65
65
|
'modules/test': 'test',
|
|
66
66
|
};
|
|
@@ -362,18 +362,17 @@ export function startServer(
|
|
|
362
362
|
runChecks([uri]);
|
|
363
363
|
}
|
|
364
364
|
|
|
365
|
-
// The objective at the time of writing this is to make {Asset,
|
|
365
|
+
// The objective at the time of writing this is to make {Asset,Partial}Rename
|
|
366
366
|
// fast when you eventually need it.
|
|
367
367
|
//
|
|
368
368
|
// I'm choosing the textDocument/didOpen notification as a hook because
|
|
369
369
|
// I'm not sure we have a better solution than this. Yes we have the
|
|
370
370
|
// initialize request with the workspace folders, but you might have opened
|
|
371
|
-
// an app folder.
|
|
372
|
-
//
|
|
373
|
-
// figure out from the initialize request params.
|
|
371
|
+
// an app folder. It'd be hard to figure out the root from the
|
|
372
|
+
// initialize request params alone.
|
|
374
373
|
//
|
|
375
374
|
// If we open a file that we know is liquid, then we can kind of guarantee
|
|
376
|
-
// we'll find
|
|
375
|
+
// we'll find an app root and we'll preload that.
|
|
377
376
|
if (await configuration.shouldPreloadOnBoot()) {
|
|
378
377
|
const rootUri = await findAppRootURI(uri);
|
|
379
378
|
if (rootUri) {
|
package/src/utils/debounce.ts
CHANGED
|
@@ -27,7 +27,7 @@ export interface DebouncedFunction<F extends Function> {
|
|
|
27
27
|
* This is useful in cases where you have an "expensive" function that you only want
|
|
28
28
|
* to execute after the user is idle for a little bit.
|
|
29
29
|
*
|
|
30
|
-
* e.g. Run
|
|
30
|
+
* e.g. Run platformos-check after the user has stopped typing for at least 100ms.
|
|
31
31
|
*
|
|
32
32
|
* The debounced function has the same type signature as its argument.
|
|
33
33
|
*
|
package/src/utils/liquidDoc.ts
CHANGED
|
@@ -29,7 +29,7 @@ export function formatLiquidDocTagHandle(label: string, description: string, exa
|
|
|
29
29
|
export const SUPPORTED_LIQUID_DOC_TAG_HANDLES = {
|
|
30
30
|
[SupportedDocTagTypes.Param]: {
|
|
31
31
|
description:
|
|
32
|
-
'Provides information about a parameter for the
|
|
32
|
+
'Provides information about a parameter for the partial.\n' +
|
|
33
33
|
`- The type of parameter is optional and can be ${Object.values(BasicParamTypes)
|
|
34
34
|
.map((type) => `\`${type}\``)
|
|
35
35
|
.join(', ')}\n` +
|
|
@@ -45,15 +45,15 @@ export const SUPPORTED_LIQUID_DOC_TAG_HANDLES = {
|
|
|
45
45
|
template: `param {$2} $1$0`,
|
|
46
46
|
},
|
|
47
47
|
[SupportedDocTagTypes.Example]: {
|
|
48
|
-
description: 'Provides an example on how to use the
|
|
48
|
+
description: 'Provides an example on how to use the partial.',
|
|
49
49
|
example:
|
|
50
|
-
'{% doc %}\n' + ' @example {% render "
|
|
50
|
+
'{% doc %}\n' + ' @example {% render "partial-name", arg1: "value" %}\n' + '{% enddoc %}\n',
|
|
51
51
|
template: `example $0`,
|
|
52
52
|
},
|
|
53
53
|
[SupportedDocTagTypes.Description]: {
|
|
54
|
-
description: 'Provides information on what the
|
|
54
|
+
description: 'Provides information on what the partial does.',
|
|
55
55
|
example:
|
|
56
|
-
'{% doc %}\n' + ' @description This
|
|
56
|
+
'{% doc %}\n' + ' @description This partial renders a product image.\n' + '{% enddoc %}\n',
|
|
57
57
|
template: `description $0`,
|
|
58
58
|
},
|
|
59
59
|
};
|
package/src/utils/uri.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { path } from '@platformos/platformos-check-common';
|
|
2
|
+
import { isPartial, PlatformOSFileType, getFileType } from '@platformos/platformos-common';
|
|
3
|
+
|
|
4
|
+
export { isPartial };
|
|
2
5
|
|
|
3
6
|
export const partialName = (uri: string) => path.basename(uri, '.liquid');
|
|
4
|
-
export const isPartial = (uri: string) => /\b(partials|lib)(\\|\/)[^\\\/]*\.liquid/.test(uri);
|
|
5
7
|
|
|
6
|
-
// asset urls have their `.liquid
|
|
8
|
+
// asset urls have their `.liquid` removed (if present) and require the other extension
|
|
7
9
|
export const assetName = (uri: string) => path.basename(uri, '.liquid');
|
|
8
|
-
export const isAsset = (uri: string) =>
|
|
10
|
+
export const isAsset = (uri: string) => getFileType(uri) === PlatformOSFileType.Asset;
|