@platformos/platformos-language-server-common 0.0.7 → 0.0.8

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.
Files changed (239) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/PropertyShapeInference.d.ts +18 -0
  3. package/dist/PropertyShapeInference.js +58 -0
  4. package/dist/PropertyShapeInference.js.map +1 -1
  5. package/dist/TypeSystem.d.ts +4 -9
  6. package/dist/TypeSystem.js +234 -388
  7. package/dist/TypeSystem.js.map +1 -1
  8. package/dist/codeActions/providers/GenerateDocBlockProvider.d.ts +10 -0
  9. package/dist/codeActions/providers/GenerateDocBlockProvider.js +39 -0
  10. package/dist/codeActions/providers/GenerateDocBlockProvider.js.map +1 -0
  11. package/dist/commands/providers/GenerateDocBlockCommandProvider.d.ts +19 -0
  12. package/dist/commands/providers/GenerateDocBlockCommandProvider.js +64 -0
  13. package/dist/commands/providers/GenerateDocBlockCommandProvider.js.map +1 -0
  14. package/dist/completions/CompletionsProvider.d.ts +6 -10
  15. package/dist/completions/CompletionsProvider.js +6 -9
  16. package/dist/completions/CompletionsProvider.js.map +1 -1
  17. package/dist/completions/params/LiquidCompletionParams.js +4 -16
  18. package/dist/completions/params/LiquidCompletionParams.js.map +1 -1
  19. package/dist/completions/providers/ContentForCompletionProvider.js +2 -4
  20. package/dist/completions/providers/ContentForCompletionProvider.js.map +1 -1
  21. package/dist/completions/providers/FilterNamedParameterCompletionProvider.d.ts +3 -3
  22. package/dist/completions/providers/FilterNamedParameterCompletionProvider.js +6 -6
  23. package/dist/completions/providers/FilterNamedParameterCompletionProvider.js.map +1 -1
  24. package/dist/completions/providers/LiquidDocParamTypeCompletionProvider.d.ts +3 -3
  25. package/dist/completions/providers/LiquidDocParamTypeCompletionProvider.js +3 -3
  26. package/dist/completions/providers/LiquidDocParamTypeCompletionProvider.js.map +1 -1
  27. package/dist/completions/providers/LiquidTagsCompletionProvider.d.ts +3 -3
  28. package/dist/completions/providers/LiquidTagsCompletionProvider.js +3 -3
  29. package/dist/completions/providers/LiquidTagsCompletionProvider.js.map +1 -1
  30. package/dist/completions/providers/RenderPartialParameterCompletionProvider.js +1 -1
  31. package/dist/completions/providers/RenderPartialParameterCompletionProvider.js.map +1 -1
  32. package/dist/completions/providers/index.d.ts +0 -3
  33. package/dist/completions/providers/index.js +1 -7
  34. package/dist/completions/providers/index.js.map +1 -1
  35. package/dist/css/CSSLanguageService.d.ts +19 -5
  36. package/dist/css/CSSLanguageService.js +77 -63
  37. package/dist/css/CSSLanguageService.js.map +1 -1
  38. package/dist/definitions/DefinitionProvider.d.ts +1 -1
  39. package/dist/definitions/DefinitionProvider.js +1 -3
  40. package/dist/definitions/DefinitionProvider.js.map +1 -1
  41. package/dist/diagnostics/offenseToDiagnostic.js +1 -1
  42. package/dist/diagnostics/offenseToDiagnostic.js.map +1 -1
  43. package/dist/diagnostics/runChecks.d.ts +3 -5
  44. package/dist/diagnostics/runChecks.js +12 -64
  45. package/dist/diagnostics/runChecks.js.map +1 -1
  46. package/dist/docset/MarkdownRenderer.js +1 -1
  47. package/dist/docset/MarkdownRenderer.js.map +1 -1
  48. package/dist/documentLinks/DocumentLinksProvider.d.ts +3 -3
  49. package/dist/documentLinks/DocumentLinksProvider.js +3 -3
  50. package/dist/documentLinks/DocumentLinksProvider.js.map +1 -1
  51. package/dist/documents/DocumentManager.d.ts +4 -5
  52. package/dist/documents/DocumentManager.js +12 -11
  53. package/dist/documents/DocumentManager.js.map +1 -1
  54. package/dist/documents/types.d.ts +16 -3
  55. package/dist/documents/types.js +3 -3
  56. package/dist/documents/types.js.map +1 -1
  57. package/dist/hover/HoverProvider.d.ts +5 -8
  58. package/dist/hover/HoverProvider.js +8 -14
  59. package/dist/hover/HoverProvider.js.map +1 -1
  60. package/dist/hover/providers/LiquidFilterArgumentHoverProvider.d.ts +3 -3
  61. package/dist/hover/providers/LiquidFilterArgumentHoverProvider.js +3 -3
  62. package/dist/hover/providers/LiquidFilterArgumentHoverProvider.js.map +1 -1
  63. package/dist/hover/providers/LiquidFilterHoverProvider.d.ts +3 -3
  64. package/dist/hover/providers/LiquidFilterHoverProvider.js +3 -3
  65. package/dist/hover/providers/LiquidFilterHoverProvider.js.map +1 -1
  66. package/dist/hover/providers/LiquidTagHoverProvider.d.ts +3 -3
  67. package/dist/hover/providers/LiquidTagHoverProvider.js +3 -3
  68. package/dist/hover/providers/LiquidTagHoverProvider.js.map +1 -1
  69. package/dist/hover/providers/RenderPartialHoverProvider.js +1 -1
  70. package/dist/hover/providers/RenderPartialHoverProvider.js.map +1 -1
  71. package/dist/hover/providers/RenderPartialParameterHoverProvider.js +1 -1
  72. package/dist/hover/providers/RenderPartialParameterHoverProvider.js.map +1 -1
  73. package/dist/hover/providers/TranslationHoverProvider.d.ts +3 -3
  74. package/dist/hover/providers/TranslationHoverProvider.js +3 -3
  75. package/dist/hover/providers/TranslationHoverProvider.js.map +1 -1
  76. package/dist/index.d.ts +1 -1
  77. package/dist/index.js.map +1 -1
  78. package/dist/internal-types.d.ts +1 -1
  79. package/dist/json/JSONContributions.d.ts +1 -5
  80. package/dist/json/JSONContributions.js +4 -36
  81. package/dist/json/JSONContributions.js.map +1 -1
  82. package/dist/json/JSONLanguageService.d.ts +4 -12
  83. package/dist/json/JSONLanguageService.js +17 -80
  84. package/dist/json/JSONLanguageService.js.map +1 -1
  85. package/dist/json/test/test-helpers.d.ts +1 -3
  86. package/dist/json/test/test-helpers.js +3 -19
  87. package/dist/json/test/test-helpers.js.map +1 -1
  88. package/dist/json/utils.d.ts +0 -5
  89. package/dist/json/utils.js +0 -24
  90. package/dist/json/utils.js.map +1 -1
  91. package/dist/rename/RenameProvider.d.ts +2 -2
  92. package/dist/rename/RenameProvider.js +2 -2
  93. package/dist/rename/RenameProvider.js.map +1 -1
  94. package/dist/rename/providers/LiquidVariableRenameProvider.d.ts +3 -3
  95. package/dist/rename/providers/LiquidVariableRenameProvider.js +4 -4
  96. package/dist/rename/providers/LiquidVariableRenameProvider.js.map +1 -1
  97. package/dist/renamed/RenameHandler.d.ts +2 -3
  98. package/dist/renamed/RenameHandler.js +3 -8
  99. package/dist/renamed/RenameHandler.js.map +1 -1
  100. package/dist/renamed/handlers/AssetRenameHandler.d.ts +3 -3
  101. package/dist/renamed/handlers/AssetRenameHandler.js +5 -5
  102. package/dist/renamed/handlers/AssetRenameHandler.js.map +1 -1
  103. package/dist/renamed/handlers/PartialRenameHandler.d.ts +3 -3
  104. package/dist/renamed/handlers/PartialRenameHandler.js +5 -5
  105. package/dist/renamed/handlers/PartialRenameHandler.js.map +1 -1
  106. package/dist/renamed/handlers/utils.d.ts +1 -1
  107. package/dist/server/AppGraphManager.d.ts +32 -0
  108. package/dist/server/AppGraphManager.js +155 -0
  109. package/dist/server/AppGraphManager.js.map +1 -0
  110. package/dist/server/startServer.d.ts +2 -2
  111. package/dist/server/startServer.js +62 -164
  112. package/dist/server/startServer.js.map +1 -1
  113. package/dist/tsconfig.tsbuildinfo +1 -1
  114. package/dist/types.d.ts +33 -54
  115. package/dist/types.js +21 -26
  116. package/dist/types.js.map +1 -1
  117. package/dist/utils/liquidDoc.js +1 -1
  118. package/dist/utils/liquidDoc.js.map +1 -1
  119. package/dist/utils/uri.d.ts +0 -8
  120. package/dist/utils/uri.js +1 -17
  121. package/dist/utils/uri.js.map +1 -1
  122. package/package.json +4 -4
  123. package/src/PropertyShapeInference.ts +76 -1
  124. package/src/TypeSystem.spec.ts +188 -450
  125. package/src/TypeSystem.ts +251 -457
  126. package/src/completions/CompletionsProvider.ts +13 -34
  127. package/src/completions/params/LiquidCompletionParams.spec.ts +0 -9
  128. package/src/completions/params/LiquidCompletionParams.ts +4 -14
  129. package/src/completions/params/fix.spec.ts +0 -3
  130. package/src/completions/providers/FilterCompletionProvider.spec.ts +2 -8
  131. package/src/completions/providers/FilterNamedParameterCompletionProvider.spec.ts +1 -5
  132. package/src/completions/providers/FilterNamedParameterCompletionProvider.ts +6 -6
  133. package/src/completions/providers/HtmlAttributeCompletionProvider.spec.ts +1 -4
  134. package/src/completions/providers/HtmlAttributeValueCompletionProvider.spec.ts +1 -4
  135. package/src/completions/providers/HtmlTagCompletionProvider.spec.ts +1 -4
  136. package/src/completions/providers/LiquidDocParamTypeCompletionProvider.spec.ts +1 -28
  137. package/src/completions/providers/LiquidDocParamTypeCompletionProvider.ts +3 -3
  138. package/src/completions/providers/LiquidDocTagCompletionProvider.spec.ts +1 -26
  139. package/src/completions/providers/LiquidTagsCompletionProvider.spec.ts +2 -16
  140. package/src/completions/providers/LiquidTagsCompletionProvider.ts +3 -3
  141. package/src/completions/providers/ObjectAttributeCompletionProvider.spec.ts +2 -31
  142. package/src/completions/providers/ObjectCompletionProvider.spec.ts +34 -123
  143. package/src/completions/providers/PartialCompletionProvider.spec.ts +4 -13
  144. package/src/completions/providers/RenderPartialParameterCompletionProvider.spec.ts +3 -5
  145. package/src/completions/providers/RenderPartialParameterCompletionProvider.ts +0 -1
  146. package/src/completions/providers/TranslationCompletionProvider.spec.ts +1 -4
  147. package/src/completions/providers/index.ts +0 -3
  148. package/src/css/CSSLanguageService.ts +97 -81
  149. package/src/definitions/DefinitionProvider.ts +0 -6
  150. package/src/definitions/providers/TranslationStringDefinitionProvider.spec.ts +1 -5
  151. package/src/diagnostics/offenseToDiagnostic.ts +1 -1
  152. package/src/diagnostics/runChecks.spec.ts +16 -24
  153. package/src/diagnostics/runChecks.ts +17 -91
  154. package/src/docset/MarkdownRenderer.ts +1 -1
  155. package/src/documentLinks/DocumentLinksProvider.ts +3 -3
  156. package/src/documents/DocumentManager.spec.ts +12 -97
  157. package/src/documents/DocumentManager.ts +13 -14
  158. package/src/documents/types.ts +18 -9
  159. package/src/hover/HoverProvider.ts +9 -21
  160. package/src/hover/providers/HtmlAttributeHoverProvider.spec.ts +1 -3
  161. package/src/hover/providers/HtmlAttributeValueHoverProvider.spec.ts +1 -3
  162. package/src/hover/providers/HtmlTagHoverProvider.spec.ts +1 -3
  163. package/src/hover/providers/LiquidDocTagHoverProvider.spec.ts +0 -3
  164. package/src/hover/providers/LiquidFilterArgumentHoverProvider.spec.ts +0 -3
  165. package/src/hover/providers/LiquidFilterArgumentHoverProvider.ts +3 -3
  166. package/src/hover/providers/LiquidFilterHoverProvider.spec.ts +0 -3
  167. package/src/hover/providers/LiquidFilterHoverProvider.ts +3 -3
  168. package/src/hover/providers/LiquidObjectAttributeHoverProvider.spec.ts +1 -3
  169. package/src/hover/providers/LiquidObjectHoverProvider.spec.ts +46 -129
  170. package/src/hover/providers/LiquidTagHoverProvider.spec.ts +0 -3
  171. package/src/hover/providers/LiquidTagHoverProvider.ts +3 -3
  172. package/src/hover/providers/RenderPartialHoverProvider.spec.ts +1 -4
  173. package/src/hover/providers/RenderPartialHoverProvider.ts +1 -5
  174. package/src/hover/providers/RenderPartialParameterHoverProvider.spec.ts +1 -4
  175. package/src/hover/providers/RenderPartialParameterHoverProvider.ts +0 -1
  176. package/src/hover/providers/TranslationHoverProvider.spec.ts +1 -4
  177. package/src/hover/providers/TranslationHoverProvider.ts +3 -3
  178. package/src/index.ts +2 -5
  179. package/src/internal-types.ts +1 -1
  180. package/src/json/JSONContributions.ts +4 -61
  181. package/src/json/JSONLanguageService.ts +19 -117
  182. package/src/json/test/test-helpers.ts +4 -35
  183. package/src/json/utils.ts +0 -27
  184. package/src/rename/RenameProvider.ts +3 -3
  185. package/src/rename/providers/LiquidVariableRenameProvider.spec.ts +4 -4
  186. package/src/rename/providers/LiquidVariableRenameProvider.ts +4 -4
  187. package/src/renamed/RenameHandler.ts +4 -9
  188. package/src/renamed/handlers/AssetRenameHandler.spec.ts +3 -3
  189. package/src/renamed/handlers/AssetRenameHandler.ts +5 -5
  190. package/src/renamed/handlers/PartialRenameHandler.spec.ts +2 -2
  191. package/src/renamed/handlers/PartialRenameHandler.ts +5 -5
  192. package/src/renamed/handlers/utils.ts +1 -1
  193. package/src/server/{ThemeGraphManager.ts → AppGraphManager.ts} +21 -90
  194. package/src/server/startServer.spec.ts +7 -9
  195. package/src/server/startServer.ts +65 -217
  196. package/src/test/CompletionItemsAssertion.spec.ts +1 -4
  197. package/src/types.ts +33 -63
  198. package/src/utils/liquidDoc.ts +1 -1
  199. package/src/utils/uri.ts +0 -14
  200. package/src/completions/providers/ContentForBlockTypeCompletionProvider.spec.ts +0 -41
  201. package/src/completions/providers/ContentForBlockTypeCompletionProvider.ts +0 -42
  202. package/src/completions/providers/ContentForCompletionProvider.spec.ts +0 -96
  203. package/src/completions/providers/ContentForCompletionProvider.ts +0 -113
  204. package/src/completions/providers/ContentForParameterCompletionProvider.spec.ts +0 -362
  205. package/src/completions/providers/ContentForParameterCompletionProvider.ts +0 -187
  206. package/src/completions/providers/data/contentForParameterCompletionOptions.ts +0 -9
  207. package/src/css/CSSLanguageService.spec.ts +0 -159
  208. package/src/css/test/test-helpers.ts +0 -30
  209. package/src/definitions/providers/SchemaTranslationStringDefinitionProvider.spec.ts +0 -96
  210. package/src/definitions/providers/SchemaTranslationStringDefinitionProvider.ts +0 -82
  211. package/src/hover/providers/ContentForArgumentHoverProvider.spec.ts +0 -76
  212. package/src/hover/providers/ContentForArgumentHoverProvider.ts +0 -56
  213. package/src/hover/providers/ContentForTypeHoverProvider.spec.ts +0 -91
  214. package/src/hover/providers/ContentForTypeHoverProvider.ts +0 -42
  215. package/src/json/JSONLanguageService.spec.ts +0 -424
  216. package/src/json/completions/providers/BlockSettingsPropertyCompletionProvider.spec.ts +0 -163
  217. package/src/json/completions/providers/BlockSettingsPropertyCompletionProvider.ts +0 -121
  218. package/src/json/completions/providers/BlockTypeCompletionProvider.spec.ts +0 -137
  219. package/src/json/completions/providers/BlockTypeCompletionProvider.ts +0 -108
  220. package/src/json/completions/providers/ReferencedBlockTypeCompletionProvider.spec.ts +0 -132
  221. package/src/json/completions/providers/ReferencedBlockTypeCompletionProvider.ts +0 -120
  222. package/src/json/completions/providers/SchemaTranslationCompletionProvider.ts +0 -51
  223. package/src/json/completions/providers/SettingsPropertyCompletionProvider.spec.ts +0 -211
  224. package/src/json/completions/providers/SettingsPropertyCompletionProvider.ts +0 -75
  225. package/src/json/documentLinks/DocumentLinksProvider.spec.ts +0 -223
  226. package/src/json/documentLinks/DocumentLinksProvider.ts +0 -61
  227. package/src/json/hover/providers/BlockSettingsHoverProvider.spec.ts +0 -292
  228. package/src/json/hover/providers/BlockSettingsHoverProvider.ts +0 -99
  229. package/src/json/hover/providers/SchemaTranslationHoverProvider.ts +0 -35
  230. package/src/json/hover/providers/SettingsHoverProvider.spec.ts +0 -139
  231. package/src/json/hover/providers/SettingsHoverProvider.ts +0 -79
  232. package/src/json/schemaSettings.spec.ts +0 -103
  233. package/src/json/schemaSettings.ts +0 -53
  234. package/src/plugins/css.ts +0 -12
  235. package/src/renamed/handlers/BlockRenameHandler.spec.ts +0 -399
  236. package/src/renamed/handlers/BlockRenameHandler.ts +0 -402
  237. package/src/renamed/handlers/SectionRenameHandler.spec.ts +0 -321
  238. package/src/renamed/handlers/SectionRenameHandler.ts +0 -224
  239. package/src/settings/index.ts +0 -50
@@ -1,362 +0,0 @@
1
- import { describe, afterEach, beforeEach, it, expect, vi } from 'vitest';
2
- import { CompletionsProvider } from '../CompletionsProvider';
3
- import { DocumentManager } from '../../documents';
4
- import { MetafieldDefinitionMap } from '@platformos/platformos-check-common';
5
- import { TextEdit, InsertTextFormat } from 'vscode-languageserver-protocol';
6
- import { TextDocument } from 'vscode-languageserver-textdocument';
7
- import { CURSOR } from '../params';
8
-
9
- vi.mock('./data/contentForParameterCompletionOptions', async () => {
10
- const actual = (await vi.importActual(
11
- './data/contentForParameterCompletionOptions',
12
- )) as typeof import('./data/contentForParameterCompletionOptions');
13
- return {
14
- DEFAULT_COMPLETION_OPTIONS: {
15
- ...actual.DEFAULT_COMPLETION_OPTIONS,
16
- // Add another option here so we can properly test some scenarios that
17
- // we wouldn't be able to otherwise.
18
- testOption: '',
19
- },
20
- };
21
- });
22
-
23
- describe('Module: ContentForBlockParameterCompletionProvider', async () => {
24
- let provider: CompletionsProvider;
25
-
26
- beforeEach(async () => {
27
- provider = new CompletionsProvider({
28
- documentManager: new DocumentManager(),
29
- themeDocset: {
30
- graphQL: async () => null,
31
- filters: async () => [],
32
- objects: async () => [],
33
- liquidDrops: async () => [],
34
- tags: async () => [],
35
- systemTranslations: async () => ({}),
36
- },
37
- getMetafieldDefinitions: async (_rootUri: string) => ({}) as MetafieldDefinitionMap,
38
- });
39
- });
40
-
41
- afterEach(() => {
42
- vi.restoreAllMocks();
43
- });
44
-
45
- it('offers a full list of completion items', async () => {
46
- await expect(provider).to.complete('{% content_for "block", █ %}', [
47
- 'type',
48
- 'id',
49
- 'closest',
50
- 'testOption',
51
- ]);
52
- });
53
-
54
- it('does not offer completion items if they are already present', async () => {
55
- const context = `{% content_for "block", type: "fake-block", id: "fake-id", █ %}`;
56
-
57
- await expect(provider).to.complete(context, ['closest', 'testOption']);
58
- });
59
-
60
- it('uses text edits to insert the completion item', async () => {
61
- // char 24 ⌄
62
- const context = `{% content_for "block", █ %}`;
63
-
64
- const textEdit: TextEdit = {
65
- newText: "type: '$1'",
66
- range: {
67
- end: { line: 0, character: 24 },
68
- start: { line: 0, character: 24 },
69
- },
70
- };
71
-
72
- await expect(provider).to.complete(
73
- context,
74
- expect.arrayContaining([
75
- expect.objectContaining({
76
- label: 'type',
77
- insertTextFormat: InsertTextFormat.Snippet,
78
- textEdit,
79
- }),
80
- ]),
81
- );
82
-
83
- const textDocument = TextDocument.create('', 'liquid', 0, context.replace(CURSOR, ''));
84
-
85
- expect(TextDocument.applyEdits(textDocument, [textEdit])).toBe(
86
- `{% content_for "block", type: '$1' %}`,
87
- );
88
- });
89
-
90
- it('provides a different style of completion for "closest"', async () => {
91
- // char 24 ⌄
92
- const context = `{% content_for "block", █ %}`;
93
-
94
- const textEdit: TextEdit = {
95
- newText: 'closest.',
96
- range: {
97
- end: { line: 0, character: 24 },
98
- start: { line: 0, character: 24 },
99
- },
100
- };
101
-
102
- await expect(provider).to.complete(
103
- context,
104
- expect.arrayContaining([
105
- expect.objectContaining({
106
- label: 'closest',
107
- insertTextFormat: InsertTextFormat.PlainText,
108
- textEdit,
109
- }),
110
- ]),
111
- );
112
-
113
- const textDocument = TextDocument.create('', 'liquid', 0, context.replace(CURSOR, ''));
114
-
115
- expect(TextDocument.applyEdits(textDocument, [textEdit])).toBe(
116
- `{% content_for "block", closest. %}`,
117
- );
118
- });
119
-
120
- describe("when we're completing for blocks we allow `closest`", () => {
121
- it('does something', async () => {
122
- await expect(provider).to.complete('{% content_for "blocks", █ %}', ['closest']);
123
- });
124
- });
125
-
126
- describe('when the user has already started typing the name of the parameter', () => {
127
- it('filters the completion options to only include ones that match', async () => {
128
- await expect(provider).to.complete('{% content_for "block", t█ %}', ['type', 'testOption']);
129
- });
130
- });
131
-
132
- describe('when the user has already typed out a parameter name', () => {
133
- describe('and the cursor is in the middle of the parameter', () => {
134
- it('changes the range depending on the completion item', async () => {
135
- // char 24 ⌄ ⌄ char 38
136
- const context = `{% content_for "block", t█ype: "button" %}`;
137
- // ⌃ char 28
138
-
139
- const typeTextEdit: TextEdit = {
140
- newText: 'type',
141
- range: {
142
- end: { line: 0, character: 28 },
143
- start: { line: 0, character: 24 },
144
- },
145
- };
146
-
147
- const testTextEdit: TextEdit = {
148
- newText: "testOption: '$1'",
149
- range: {
150
- end: { line: 0, character: 38 },
151
- start: { line: 0, character: 24 },
152
- },
153
- };
154
-
155
- await expect(provider).to.complete(context, [
156
- expect.objectContaining({
157
- label: 'type',
158
- insertTextFormat: InsertTextFormat.PlainText,
159
- textEdit: expect.objectContaining(typeTextEdit),
160
- }),
161
- expect.objectContaining({
162
- label: 'testOption',
163
- insertTextFormat: InsertTextFormat.Snippet,
164
- textEdit: expect.objectContaining(testTextEdit),
165
- }),
166
- ]);
167
-
168
- const textDocument = TextDocument.create('', 'liquid', 0, context.replace(CURSOR, ''));
169
-
170
- expect(TextDocument.applyEdits(textDocument, [testTextEdit])).toBe(
171
- `{% content_for "block", testOption: '$1' %}`,
172
- );
173
-
174
- expect(TextDocument.applyEdits(textDocument, [typeTextEdit])).toBe(
175
- `{% content_for "block", type: "button" %}`,
176
- );
177
- });
178
- });
179
-
180
- describe('and the cursor is at the beginning of the parameter', () => {
181
- it('offers a full list of completion items', async () => {
182
- const context = `{% content_for "block", █type: "button" %}`;
183
-
184
- await expect(provider).to.complete(context, ['type', 'id', 'closest', 'testOption']);
185
- });
186
-
187
- it('does not replace the existing text', async () => {
188
- // char 24 ⌄
189
- const context = `{% content_for "block", █type: "button" %}`;
190
-
191
- const textEdit: TextEdit = {
192
- newText: "testOption: '$1', ",
193
- range: {
194
- end: { line: 0, character: 24 },
195
- start: { line: 0, character: 24 },
196
- },
197
- };
198
-
199
- await expect(provider).to.complete(
200
- context,
201
- expect.arrayContaining([
202
- expect.objectContaining({
203
- label: 'testOption',
204
- insertTextFormat: InsertTextFormat.Snippet,
205
- textEdit,
206
- }),
207
- ]),
208
- );
209
-
210
- const textDocument = TextDocument.create('', 'liquid', 0, context.replace(CURSOR, ''));
211
-
212
- expect(TextDocument.applyEdits(textDocument, [textEdit])).toBe(
213
- `{% content_for "block", testOption: '$1', type: "button" %}`,
214
- );
215
- });
216
- });
217
-
218
- describe('and the cursor is at the end of the parameter', () => {
219
- it('offers only the same completion item', async () => {
220
- const context = `{% content_for "block", type█: "button" %}`;
221
-
222
- await expect(provider).to.complete(context, ['type']);
223
- });
224
-
225
- it('only replaces the parameter name', async () => {
226
- // char 24 ⌄ ⌄ char 28
227
- const context = `{% content_for "block", type█: "button" %}`;
228
-
229
- const textEdit: TextEdit = {
230
- newText: 'type',
231
- range: {
232
- end: { line: 0, character: 28 },
233
- start: { line: 0, character: 24 },
234
- },
235
- };
236
-
237
- await expect(provider).to.complete(
238
- context,
239
- expect.arrayContaining([
240
- expect.objectContaining({
241
- label: 'type',
242
- insertTextFormat: InsertTextFormat.PlainText,
243
- textEdit,
244
- }),
245
- ]),
246
- );
247
-
248
- const textDocument = TextDocument.create('', 'liquid', 0, context.replace(CURSOR, ''));
249
-
250
- expect(TextDocument.applyEdits(textDocument, [textEdit])).toBe(
251
- `{% content_for "block", type: "button" %}`,
252
- );
253
- });
254
- });
255
- });
256
-
257
- describe('when the referred block has LiquidDoc parameters', () => {
258
- beforeEach(async () => {
259
- provider = new CompletionsProvider({
260
- documentManager: new DocumentManager(),
261
- themeDocset: {
262
- graphQL: async () => null,
263
- filters: async () => [],
264
- objects: async () => [],
265
- liquidDrops: async () => [],
266
- tags: async () => [],
267
- systemTranslations: async () => ({}),
268
- },
269
- getMetafieldDefinitions: async (_rootUri: string) => ({}) as MetafieldDefinitionMap,
270
- getDocDefinitionForURI: async (_uri, _category, _name) => {
271
- return {
272
- uri: 'file:///blocks/product-card.liquid',
273
- liquidDoc: {
274
- parameters: [
275
- {
276
- nodeType: 'param',
277
- name: 'example-string-param',
278
- type: 'string',
279
- description: 'An example string parameter',
280
- required: true,
281
- },
282
- {
283
- nodeType: 'param',
284
- name: 'example-number-param',
285
- type: 'number',
286
- description: 'An example number parameter',
287
- required: true,
288
- },
289
- {
290
- nodeType: 'param',
291
- name: 'example-boolean-param',
292
- type: 'boolean',
293
- description: 'An example boolean parameter',
294
- required: true,
295
- },
296
- {
297
- nodeType: 'param',
298
- name: 'example-object-param',
299
- type: 'object',
300
- description: 'An example object parameter',
301
- required: true,
302
- },
303
- {
304
- nodeType: 'param',
305
- name: 'example-unknown-param',
306
- type: 'unknown',
307
- description: 'An example unknown parameter',
308
- required: true,
309
- },
310
- ],
311
- },
312
- };
313
- },
314
- });
315
- });
316
-
317
- it('offers the LiquidDoc parameters as completions', async () => {
318
- const context = `{% content_for "block", type: 'fake-block', █ %}`;
319
-
320
- await expect(provider).to.complete(
321
- context,
322
- expect.arrayContaining([
323
- expect.objectContaining({
324
- label: 'example-string-param',
325
- insertTextFormat: InsertTextFormat.Snippet,
326
- textEdit: expect.objectContaining({
327
- newText: "example-string-param: '$1'$0",
328
- }),
329
- }),
330
- expect.objectContaining({
331
- label: 'example-number-param',
332
- insertTextFormat: InsertTextFormat.Snippet,
333
- textEdit: expect.objectContaining({
334
- newText: 'example-number-param: ${1:0}$0',
335
- }),
336
- }),
337
- expect.objectContaining({
338
- label: 'example-boolean-param',
339
- insertTextFormat: InsertTextFormat.Snippet,
340
- textEdit: expect.objectContaining({
341
- newText: 'example-boolean-param: ${1:false}$0',
342
- }),
343
- }),
344
- expect.objectContaining({
345
- label: 'example-object-param',
346
- insertTextFormat: InsertTextFormat.Snippet,
347
- textEdit: expect.objectContaining({
348
- newText: 'example-object-param: ${1:}$0',
349
- }),
350
- }),
351
- expect.objectContaining({
352
- label: 'example-unknown-param',
353
- insertTextFormat: InsertTextFormat.Snippet,
354
- textEdit: expect.objectContaining({
355
- newText: 'example-unknown-param: ${1:}$0',
356
- }),
357
- }),
358
- ]),
359
- );
360
- });
361
- });
362
- });
@@ -1,187 +0,0 @@
1
- import { LiquidVariableLookup, NodeTypes } from '@platformos/liquid-html-parser';
2
- import {
3
- CompletionItem,
4
- CompletionItemKind,
5
- InsertTextFormat,
6
- TextEdit,
7
- } from 'vscode-languageserver';
8
- import { CURSOR, LiquidCompletionParams } from '../params';
9
- import { Provider } from './common';
10
- import { AugmentedLiquidSourceCode } from '../../documents';
11
- import { DEFAULT_COMPLETION_OPTIONS } from './data/contentForParameterCompletionOptions';
12
- import { DocDefinition, GetDocDefinitionForURI } from '@platformos/platformos-check-common';
13
- import { getParameterCompletionTemplate } from '../../utils/liquidDoc';
14
-
15
- /**
16
- * Offers completions for parameters for the `content_for` tag after a user has
17
- * specificied the type.
18
- *
19
- * @example {% content_for "block", █ %}
20
- */
21
- export class ContentForParameterCompletionProvider implements Provider {
22
- constructor(private readonly getDocDefinitionForURI: GetDocDefinitionForURI) {}
23
-
24
- async completions(params: LiquidCompletionParams): Promise<CompletionItem[]> {
25
- if (!params.completionContext) return [];
26
-
27
- const { node, ancestors } = params.completionContext;
28
-
29
- const parentNode = ancestors.at(-1);
30
-
31
- const parentIsContentFor = parentNode?.type == NodeTypes.ContentForMarkup;
32
- const nodeIsVariableLookup = node?.type == NodeTypes.VariableLookup;
33
-
34
- if (!parentIsContentFor || !nodeIsVariableLookup) {
35
- return [];
36
- }
37
-
38
- if (!node.name || node.lookups.length > 0) {
39
- return [];
40
- }
41
-
42
- const completionItems = this.staticCompletions(
43
- node,
44
- parentNode.contentForType.value == 'blocks',
45
- params.document,
46
- );
47
-
48
- if (parentNode.contentForType.value === 'block') {
49
- const typeArg = parentNode.args.find((arg) => arg.name === 'type')?.value;
50
-
51
- if (typeArg?.type === NodeTypes.String) {
52
- const snippetDefinition = await this.getDocDefinitionForURI(
53
- params.textDocument.uri,
54
- 'blocks',
55
- typeArg.value,
56
- );
57
-
58
- completionItems.push(
59
- ...this.liquidDocParameterCompletions(node, params.document, snippetDefinition),
60
- );
61
- }
62
- }
63
-
64
- // We need to find out existing params in the content_for tag so we don't offer it again for completion
65
- const existingParams = parentNode.args
66
- .filter((arg) => arg.type === NodeTypes.NamedArgument)
67
- .map((arg) => arg.name);
68
-
69
- return completionItems.filter((item) => !existingParams.includes(item.label));
70
- }
71
-
72
- textEdit(
73
- node: LiquidVariableLookup,
74
- document: AugmentedLiquidSourceCode,
75
- name: string,
76
- textTemplate: string = `${name}: '$1'`,
77
- ): {
78
- textEdit: TextEdit;
79
- format: InsertTextFormat;
80
- } {
81
- const remainingText = document.source.slice(node.position.end);
82
-
83
- // Match all the way up to the termination of the parameter which could be
84
- // another parameter (`,`), filter (`|`), or the end of a liquid statement.
85
- const match = remainingText.match(/^(.*?)\s*(?=,|\||-?\}\}|-?\%\})|^(.*)$/);
86
- const offset = match ? match[0].trimEnd().length : remainingText.length;
87
- const existingParameterOffset = remainingText.match(/[^a-zA-Z]/)?.index ?? remainingText.length;
88
-
89
- let start = document.textDocument.positionAt(node.position.start);
90
- let end = document.textDocument.positionAt(node.position.end + offset);
91
- let newText = name === 'closest' ? `${name}.` : textTemplate;
92
- let format = name === 'closest' ? InsertTextFormat.PlainText : InsertTextFormat.Snippet;
93
-
94
- // If the cursor is inside the parameter or at the end and it's the same
95
- // value as the one we're offering a completion for then we want to restrict
96
- // the insert to just the name of the parameter.
97
- // e.g. `{% content_for "block", t█ype: "button" %}` and we're offering `type`
98
- if (node.name + remainingText.slice(0, existingParameterOffset) == name) {
99
- newText = name;
100
- format = InsertTextFormat.PlainText;
101
- end = document.textDocument.positionAt(node.position.end + existingParameterOffset);
102
- }
103
-
104
- // If the cursor is at the beginning of the string we can consider all
105
- // options and should not replace any text.
106
- // e.g. `{% content_for "block", █type: "button" %}`
107
- // e.g. `{% content_for "block", █ %}`
108
- if (node.name === CURSOR) {
109
- end = start;
110
-
111
- // If we're inserting text in front of an existing parameter then we need
112
- // to add a comma to separate them.
113
- if (existingParameterOffset > 0) {
114
- newText += ', ';
115
- }
116
- }
117
-
118
- return {
119
- textEdit: TextEdit.replace(
120
- {
121
- start,
122
- end,
123
- },
124
- newText,
125
- ),
126
- format,
127
- };
128
- }
129
-
130
- private staticCompletions(
131
- node: LiquidVariableLookup,
132
- isTypeBlocks: boolean,
133
- document: AugmentedLiquidSourceCode,
134
- ) {
135
- let options = DEFAULT_COMPLETION_OPTIONS;
136
-
137
- const partial = node.name!.replace(CURSOR, '');
138
-
139
- if (isTypeBlocks) {
140
- options = {
141
- closest: DEFAULT_COMPLETION_OPTIONS.closest,
142
- };
143
- }
144
-
145
- return Object.entries(options)
146
- .filter(([keyword, _description]) => keyword.startsWith(partial))
147
- .map(([keyword, description]): CompletionItem => {
148
- const { textEdit, format } = this.textEdit(node, document, keyword);
149
- return {
150
- label: keyword,
151
- kind: CompletionItemKind.Keyword,
152
- documentation: {
153
- kind: 'markdown',
154
- value: description,
155
- },
156
- insertTextFormat: format,
157
- textEdit,
158
- };
159
- });
160
- }
161
-
162
- private liquidDocParameterCompletions(
163
- node: LiquidVariableLookup,
164
- document: AugmentedLiquidSourceCode,
165
- docDefinition?: DocDefinition,
166
- ) {
167
- return (docDefinition?.liquidDoc?.parameters || []).map((liquidDocParam): CompletionItem => {
168
- const { textEdit, format } = this.textEdit(
169
- node,
170
- document,
171
- liquidDocParam.name,
172
- getParameterCompletionTemplate(liquidDocParam.name, liquidDocParam.type),
173
- );
174
-
175
- return {
176
- label: liquidDocParam.name,
177
- kind: CompletionItemKind.Keyword,
178
- documentation: {
179
- kind: 'markdown',
180
- value: liquidDocParam.description || '',
181
- },
182
- insertTextFormat: format,
183
- textEdit,
184
- };
185
- });
186
- }
187
- }
@@ -1,9 +0,0 @@
1
- /**
2
- * These definitions are not currently available in the generated Liquid Docs
3
- * so we're hardcoding them here in the interim.
4
- */
5
- export const DEFAULT_COMPLETION_OPTIONS: { [key: string]: string } = {
6
- type: "The type (name) of an existing theme block in your theme’s /blocks folder. Only applicable when `content_type` is 'block'.",
7
- id: "A unique identifier and literal string within the section or block that contains the static blocks. Only applicable when `content_type` is 'block'.",
8
- closest: 'A path that provides a way to access the closest resource of a given type.',
9
- };