@astrojs/language-server 0.15.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/check.js +1 -2
  3. package/dist/core/config/ConfigManager.d.ts +20 -16
  4. package/dist/core/config/ConfigManager.js +112 -46
  5. package/dist/core/config/interfaces.d.ts +0 -52
  6. package/dist/core/documents/AstroDocument.d.ts +1 -0
  7. package/dist/core/documents/AstroDocument.js +1 -0
  8. package/dist/core/documents/DocumentMapper.d.ts +2 -0
  9. package/dist/core/documents/DocumentMapper.js +9 -9
  10. package/dist/core/documents/parseAstro.js +1 -1
  11. package/dist/core/documents/utils.d.ts +1 -0
  12. package/dist/core/documents/utils.js +19 -5
  13. package/dist/plugins/PluginHost.d.ts +2 -1
  14. package/dist/plugins/PluginHost.js +8 -6
  15. package/dist/plugins/astro/AstroPlugin.d.ts +1 -6
  16. package/dist/plugins/astro/AstroPlugin.js +1 -83
  17. package/dist/plugins/astro/features/CompletionsProvider.d.ts +4 -5
  18. package/dist/plugins/astro/features/CompletionsProvider.js +49 -59
  19. package/dist/plugins/css/CSSPlugin.d.ts +5 -5
  20. package/dist/plugins/css/CSSPlugin.js +41 -20
  21. package/dist/plugins/html/HTMLPlugin.d.ts +4 -4
  22. package/dist/plugins/html/HTMLPlugin.js +20 -16
  23. package/dist/plugins/html/features/astro-attributes.js +44 -27
  24. package/dist/plugins/typescript/LanguageServiceManager.js +1 -1
  25. package/dist/plugins/typescript/TypeScriptPlugin.d.ts +5 -4
  26. package/dist/plugins/typescript/TypeScriptPlugin.js +30 -108
  27. package/dist/plugins/typescript/astro-sys.js +3 -5
  28. package/dist/plugins/typescript/astro2tsx.js +1 -2
  29. package/dist/plugins/typescript/features/CodeActionsProvider.d.ts +16 -0
  30. package/dist/plugins/typescript/features/CodeActionsProvider.js +206 -0
  31. package/dist/plugins/typescript/features/CompletionsProvider.d.ts +5 -2
  32. package/dist/plugins/typescript/features/CompletionsProvider.js +116 -68
  33. package/dist/plugins/typescript/features/DefinitionsProvider.d.ts +9 -0
  34. package/dist/plugins/typescript/features/DefinitionsProvider.js +57 -0
  35. package/dist/plugins/typescript/features/DiagnosticsProvider.js +60 -18
  36. package/dist/plugins/typescript/features/DocumentSymbolsProvider.js +3 -4
  37. package/dist/plugins/typescript/features/FoldingRangesProvider.js +13 -6
  38. package/dist/plugins/typescript/features/HoverProvider.js +14 -1
  39. package/dist/plugins/typescript/features/SemanticTokenProvider.js +1 -1
  40. package/dist/plugins/typescript/features/SignatureHelpProvider.js +11 -3
  41. package/dist/plugins/typescript/features/utils.d.ts +2 -0
  42. package/dist/plugins/typescript/features/utils.js +19 -3
  43. package/dist/plugins/typescript/language-service.js +23 -6
  44. package/dist/plugins/typescript/module-loader.js +1 -1
  45. package/dist/plugins/typescript/previewer.js +1 -1
  46. package/dist/plugins/typescript/snapshots/DocumentSnapshot.d.ts +22 -2
  47. package/dist/plugins/typescript/snapshots/DocumentSnapshot.js +48 -1
  48. package/dist/plugins/typescript/snapshots/SnapshotManager.js +2 -1
  49. package/dist/plugins/typescript/snapshots/utils.js +3 -6
  50. package/dist/plugins/typescript/utils.d.ts +12 -1
  51. package/dist/plugins/typescript/utils.js +29 -1
  52. package/dist/server.js +43 -14
  53. package/dist/utils.d.ts +4 -0
  54. package/dist/utils.js +16 -3
  55. package/package.json +2 -2
@@ -1,22 +1,15 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.AstroPlugin = void 0;
7
- const typescript_1 = __importDefault(require("typescript"));
8
4
  const vscode_languageserver_1 = require("vscode-languageserver");
9
- const documents_1 = require("../../core/documents");
10
- const utils_1 = require("../../utils");
11
5
  const LanguageServiceManager_1 = require("../typescript/LanguageServiceManager");
12
- const utils_2 = require("../typescript/utils");
13
6
  const CompletionsProvider_1 = require("./features/CompletionsProvider");
14
7
  class AstroPlugin {
15
8
  constructor(docManager, configManager, workspaceUris) {
16
9
  this.__name = 'astro';
17
10
  this.configManager = configManager;
18
11
  this.languageServiceManager = new LanguageServiceManager_1.LanguageServiceManager(docManager, workspaceUris, configManager);
19
- this.completionProvider = new CompletionsProvider_1.CompletionsProviderImpl(docManager, this.languageServiceManager);
12
+ this.completionProvider = new CompletionsProvider_1.CompletionsProviderImpl(this.languageServiceManager);
20
13
  }
21
14
  async getCompletions(document, position, completionContext) {
22
15
  const completions = this.completionProvider.getCompletions(document, position, completionContext);
@@ -40,80 +33,5 @@ class AstroPlugin {
40
33
  },
41
34
  ];
42
35
  }
43
- async getDefinitions(document, position) {
44
- if (this.isInsideFrontmatter(document, position)) {
45
- return [];
46
- }
47
- const offset = document.offsetAt(position);
48
- const html = document.html;
49
- const node = html.findNodeAt(offset);
50
- if (!this.isComponentTag(node)) {
51
- return [];
52
- }
53
- const [componentName] = node.tag.split(':');
54
- const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
55
- const defs = this.getDefinitionsForComponentName(document, lang, componentName);
56
- if (!defs || !defs.length) {
57
- return [];
58
- }
59
- const startRange = vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(0, 0), vscode_languageserver_1.Position.create(0, 0));
60
- const links = defs.map((def) => {
61
- const defFilePath = (0, utils_2.ensureRealFilePath)(def.fileName);
62
- return vscode_languageserver_1.LocationLink.create((0, utils_1.pathToUrl)(defFilePath), startRange, startRange);
63
- });
64
- return links;
65
- }
66
- isInsideFrontmatter(document, position) {
67
- return (0, documents_1.isInsideFrontmatter)(document.getText(), document.offsetAt(position));
68
- }
69
- isComponentTag(node) {
70
- if (!node.tag) {
71
- return false;
72
- }
73
- const firstChar = node.tag[0];
74
- return /[A-Z]/.test(firstChar);
75
- }
76
- getDefinitionsForComponentName(document, lang, componentName) {
77
- const filePath = (0, utils_1.urlToPath)(document.uri);
78
- const tsFilePath = (0, utils_2.toVirtualAstroFilePath)(filePath);
79
- const program = lang.getProgram();
80
- const sourceFile = program === null || program === void 0 ? void 0 : program.getSourceFile(tsFilePath);
81
- if (!sourceFile) {
82
- return undefined;
83
- }
84
- const specifier = this.getImportSpecifierForIdentifier(sourceFile, componentName);
85
- if (!specifier) {
86
- return [];
87
- }
88
- const defs = lang.getDefinitionAtPosition(tsFilePath, specifier.getStart());
89
- if (!defs) {
90
- return undefined;
91
- }
92
- return defs;
93
- }
94
- getImportSpecifierForIdentifier(sourceFile, identifier) {
95
- let importSpecifier = undefined;
96
- typescript_1.default.forEachChild(sourceFile, (tsNode) => {
97
- if (typescript_1.default.isImportDeclaration(tsNode)) {
98
- if (tsNode.importClause) {
99
- const { name, namedBindings } = tsNode.importClause;
100
- if (name && name.getText() === identifier) {
101
- importSpecifier = tsNode.moduleSpecifier;
102
- return true;
103
- }
104
- else if (namedBindings && namedBindings.kind === typescript_1.default.SyntaxKind.NamedImports) {
105
- const elements = namedBindings.elements;
106
- for (let elem of elements) {
107
- if (elem.name.getText() === identifier) {
108
- importSpecifier = tsNode.moduleSpecifier;
109
- return true;
110
- }
111
- }
112
- }
113
- }
114
- }
115
- });
116
- return importSpecifier;
117
- }
118
36
  }
119
37
  exports.AstroPlugin = AstroPlugin;
@@ -1,17 +1,16 @@
1
1
  import type { AppCompletionList, CompletionsProvider } from '../../interfaces';
2
- import type { AstroDocument, DocumentManager } from '../../../core/documents';
2
+ import type { AstroDocument } from '../../../core/documents';
3
3
  import { CompletionContext, Position } from 'vscode-languageserver';
4
4
  import { LanguageServiceManager as TypeScriptLanguageServiceManager } from '../../typescript/LanguageServiceManager';
5
5
  export declare class CompletionsProviderImpl implements CompletionsProvider {
6
- private readonly docManager;
7
6
  private readonly languageServiceManager;
7
+ private lastCompletion;
8
8
  directivesHTMLLang: import("vscode-html-languageservice").LanguageService;
9
- constructor(docManager: DocumentManager, languageServiceManager: TypeScriptLanguageServiceManager);
9
+ constructor(languageServiceManager: TypeScriptLanguageServiceManager);
10
10
  getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext): Promise<AppCompletionList | null>;
11
11
  private getComponentScriptCompletion;
12
- private getPropCompletions;
12
+ private getPropCompletionsAndFilePath;
13
13
  private getImportedSymbol;
14
14
  private getPropType;
15
15
  private getCompletionItemForProperty;
16
- private isAstroComponent;
17
16
  }
@@ -13,21 +13,18 @@ const vscode_html_languageservice_1 = require("vscode-html-languageservice");
13
13
  const astro_attributes_1 = require("../../html/features/astro-attributes");
14
14
  const utils_4 = require("../../html/utils");
15
15
  class CompletionsProviderImpl {
16
- constructor(docManager, languageServiceManager) {
16
+ constructor(languageServiceManager) {
17
+ this.lastCompletion = null;
17
18
  this.directivesHTMLLang = (0, vscode_html_languageservice_1.getLanguageService)({
18
19
  customDataProviders: [astro_attributes_1.astroDirectives],
19
20
  useDefaultDataProvider: false,
20
21
  });
21
- this.docManager = docManager;
22
22
  this.languageServiceManager = languageServiceManager;
23
23
  }
24
24
  async getCompletions(document, position, completionContext) {
25
- const doc = this.docManager.get(document.uri);
26
- if (!doc)
27
- return null;
28
25
  let items = [];
29
- if ((completionContext === null || completionContext === void 0 ? void 0 : completionContext.triggerCharacter) === '-') {
30
- const frontmatter = this.getComponentScriptCompletion(doc, position, completionContext);
26
+ if (completionContext?.triggerCharacter === '-') {
27
+ const frontmatter = this.getComponentScriptCompletion(document, position);
31
28
  if (frontmatter)
32
29
  items.push(frontmatter);
33
30
  }
@@ -35,11 +32,11 @@ class CompletionsProviderImpl {
35
32
  const offset = document.offsetAt(position);
36
33
  const node = html.findNodeAt(offset);
37
34
  if ((0, utils_1.isInComponentStartTag)(html, offset) && !(0, utils_1.isInsideExpression)(document.getText(), node.start, offset)) {
38
- const props = await this.getPropCompletions(document, position, completionContext);
35
+ const { completions: props, componentFilePath } = await this.getPropCompletionsAndFilePath(document, position, completionContext);
39
36
  if (props.length) {
40
37
  items.push(...props);
41
38
  }
42
- const isAstro = await this.isAstroComponent(document, node);
39
+ const isAstro = componentFilePath?.endsWith('.astro');
43
40
  if (!isAstro) {
44
41
  const directives = (0, utils_4.removeDataAttrCompletion)(this.directivesHTMLLang.doComplete(document, position, html).items);
45
42
  items.push(...directives);
@@ -47,7 +44,7 @@ class CompletionsProviderImpl {
47
44
  }
48
45
  return vscode_languageserver_1.CompletionList.create(items, true);
49
46
  }
50
- getComponentScriptCompletion(document, position, completionContext) {
47
+ getComponentScriptCompletion(document, position) {
51
48
  const base = {
52
49
  kind: vscode_languageserver_1.CompletionItemKind.Snippet,
53
50
  label: '---',
@@ -55,7 +52,7 @@ class CompletionsProviderImpl {
55
52
  preselect: true,
56
53
  detail: 'Component script',
57
54
  insertTextFormat: vscode_languageserver_1.InsertTextFormat.Snippet,
58
- commitCharacters: ['-'],
55
+ commitCharacters: [],
59
56
  };
60
57
  const prefix = document.getLineUntilOffset(document.offsetAt(position));
61
58
  if (document.astroMeta.frontmatter.state === null) {
@@ -78,46 +75,62 @@ class CompletionsProviderImpl {
78
75
  }
79
76
  return null;
80
77
  }
81
- async getPropCompletions(document, position, completionContext) {
78
+ async getPropCompletionsAndFilePath(document, position, completionContext) {
82
79
  const offset = document.offsetAt(position);
83
80
  const html = document.html;
84
81
  const node = html.findNodeAt(offset);
85
82
  if (!(0, utils_2.isPossibleComponent)(node)) {
86
- return [];
83
+ return { completions: [], componentFilePath: null };
87
84
  }
88
85
  const inAttribute = node.start + node.tag.length < offset;
89
86
  if (!inAttribute) {
90
- return [];
87
+ return { completions: [], componentFilePath: null };
91
88
  }
92
- if ((completionContext === null || completionContext === void 0 ? void 0 : completionContext.triggerCharacter) === '/' || (completionContext === null || completionContext === void 0 ? void 0 : completionContext.triggerCharacter) === '>') {
93
- return [];
89
+ if (completionContext?.triggerCharacter === '/' || completionContext?.triggerCharacter === '>') {
90
+ return { completions: [], componentFilePath: null };
94
91
  }
95
92
  // If inside of attribute value, skip.
96
93
  if (completionContext &&
97
94
  completionContext.triggerKind === vscode_languageserver_1.CompletionTriggerKind.TriggerCharacter &&
98
95
  completionContext.triggerCharacter === '"') {
99
- return [];
96
+ return { completions: [], componentFilePath: null };
100
97
  }
101
98
  const componentName = node.tag;
102
99
  const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
103
100
  // Get the source file
104
101
  const tsFilePath = (0, utils_3.toVirtualAstroFilePath)(tsDoc.filePath);
105
102
  const program = lang.getProgram();
106
- const sourceFile = program === null || program === void 0 ? void 0 : program.getSourceFile(tsFilePath);
107
- const typeChecker = program === null || program === void 0 ? void 0 : program.getTypeChecker();
103
+ const sourceFile = program?.getSourceFile(tsFilePath);
104
+ const typeChecker = program?.getTypeChecker();
108
105
  if (!sourceFile || !typeChecker) {
109
- return [];
106
+ return { completions: [], componentFilePath: null };
110
107
  }
111
108
  // Get the import statement
112
109
  const imp = this.getImportedSymbol(sourceFile, componentName);
113
110
  const importType = imp && typeChecker.getTypeAtLocation(imp);
114
111
  if (!importType) {
115
- return [];
112
+ return { completions: [], componentFilePath: null };
113
+ }
114
+ const symbol = importType.getSymbol();
115
+ if (!symbol) {
116
+ return { completions: [], componentFilePath: null };
117
+ }
118
+ const symbolDeclaration = symbol.declarations;
119
+ if (!symbolDeclaration) {
120
+ return { completions: [], componentFilePath: null };
121
+ }
122
+ const filePath = symbolDeclaration[0].getSourceFile().fileName;
123
+ const componentSnapshot = await this.languageServiceManager.getSnapshot(filePath);
124
+ if (this.lastCompletion) {
125
+ if (this.lastCompletion.tag === componentName &&
126
+ this.lastCompletion.documentVersion == componentSnapshot.version) {
127
+ return { completions: this.lastCompletion.completions, componentFilePath: filePath };
128
+ }
116
129
  }
117
130
  // Get the component's props type
118
- const componentType = this.getPropType(importType, typeChecker);
131
+ const componentType = this.getPropType(symbolDeclaration, typeChecker);
119
132
  if (!componentType) {
120
- return [];
133
+ return { completions: [], componentFilePath: null };
121
134
  }
122
135
  let completionItems = [];
123
136
  // Add completions for this component's props type properties
@@ -131,7 +144,12 @@ class CompletionsProviderImpl {
131
144
  completionItems = completionItems.map((item) => {
132
145
  return { ...item, sortText: '_' };
133
146
  });
134
- return completionItems;
147
+ this.lastCompletion = {
148
+ tag: componentName,
149
+ documentVersion: componentSnapshot.version,
150
+ completions: completionItems,
151
+ };
152
+ return { completions: completionItems, componentFilePath: filePath };
135
153
  }
136
154
  getImportedSymbol(sourceFile, identifier) {
137
155
  for (let list of sourceFile.getChildren()) {
@@ -159,24 +177,20 @@ class CompletionsProviderImpl {
159
177
  }
160
178
  return null;
161
179
  }
162
- getPropType(type, typeChecker) {
163
- const sym = type === null || type === void 0 ? void 0 : type.getSymbol();
164
- if (!sym) {
165
- return null;
166
- }
167
- for (const decl of (sym === null || sym === void 0 ? void 0 : sym.getDeclarations()) || []) {
180
+ getPropType(declarations, typeChecker) {
181
+ for (const decl of declarations) {
168
182
  const fileName = (0, utils_3.toVirtualFilePath)(decl.getSourceFile().fileName);
169
- if (fileName.endsWith('.tsx') || fileName.endsWith('.jsx')) {
170
- if (!typescript_1.default.isFunctionDeclaration(decl)) {
171
- console.error(`We only support function components for tsx/jsx at the moment.`);
183
+ if (fileName.endsWith('.tsx') || fileName.endsWith('.jsx') || fileName.endsWith('.d.ts')) {
184
+ if (!typescript_1.default.isFunctionDeclaration(decl) && !typescript_1.default.isFunctionTypeNode(decl)) {
185
+ console.error(`We only support functions declarations at the moment`);
172
186
  continue;
173
187
  }
174
188
  const fn = decl;
175
189
  if (!fn.parameters.length)
176
190
  continue;
177
191
  const param1 = fn.parameters[0];
178
- const type = typeChecker.getTypeAtLocation(param1);
179
- return type;
192
+ const propType = typeChecker.getTypeAtLocation(param1);
193
+ return propType;
180
194
  }
181
195
  }
182
196
  return null;
@@ -216,29 +230,5 @@ class CompletionsProviderImpl {
216
230
  }
217
231
  return item;
218
232
  }
219
- async isAstroComponent(document, node) {
220
- var _a;
221
- const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
222
- // Get the source file
223
- const tsFilePath = (0, utils_3.toVirtualAstroFilePath)(tsDoc.filePath);
224
- const program = lang.getProgram();
225
- const sourceFile = program === null || program === void 0 ? void 0 : program.getSourceFile(tsFilePath);
226
- const typeChecker = program === null || program === void 0 ? void 0 : program.getTypeChecker();
227
- if (!sourceFile || !typeChecker) {
228
- return false;
229
- }
230
- const componentName = node.tag;
231
- const imp = this.getImportedSymbol(sourceFile, componentName);
232
- const importType = imp && typeChecker.getTypeAtLocation(imp);
233
- if (!importType) {
234
- return false;
235
- }
236
- const symbolDeclaration = (_a = importType.getSymbol()) === null || _a === void 0 ? void 0 : _a.declarations;
237
- if (symbolDeclaration) {
238
- const fileName = symbolDeclaration[0].getSourceFile().fileName;
239
- return fileName.endsWith('.astro');
240
- }
241
- return false;
242
- }
243
233
  }
244
234
  exports.CompletionsProviderImpl = CompletionsProviderImpl;
@@ -8,14 +8,14 @@ export declare class CSSPlugin implements Plugin {
8
8
  private cssDocuments;
9
9
  private triggerCharacters;
10
10
  constructor(configManager: ConfigManager);
11
- doHover(document: AstroDocument, position: Position): Hover | null;
11
+ doHover(document: AstroDocument, position: Position): Promise<Hover | null>;
12
12
  private doHoverInternal;
13
- getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext): CompletionList | null;
13
+ getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext): Promise<CompletionList | null>;
14
14
  private getCompletionsInternal;
15
- getDocumentColors(document: AstroDocument): ColorInformation[];
16
- getColorPresentations(document: AstroDocument, range: Range, color: Color): ColorPresentation[];
15
+ getDocumentColors(document: AstroDocument): Promise<ColorInformation[]>;
16
+ getColorPresentations(document: AstroDocument, range: Range, color: Color): Promise<ColorPresentation[]>;
17
17
  getFoldingRanges(document: AstroDocument): FoldingRange[] | null;
18
- getDocumentSymbols(document: AstroDocument): SymbolInformation[];
18
+ getDocumentSymbols(document: AstroDocument): Promise<SymbolInformation[]>;
19
19
  private inStyleAttributeWithoutInterpolation;
20
20
  /**
21
21
  * Get the associated CSS Document for a style tag
@@ -17,8 +17,8 @@ class CSSPlugin {
17
17
  this.triggerCharacters = new Set(['.', ':', '-', '/']);
18
18
  this.configManager = configManager;
19
19
  }
20
- doHover(document, position) {
21
- if (!this.featureEnabled('hover')) {
20
+ async doHover(document, position) {
21
+ if (!(await this.featureEnabled(document, 'hover'))) {
22
22
  return null;
23
23
  }
24
24
  if ((0, documents_1.isInsideFrontmatter)(document.getText(), document.offsetAt(position))) {
@@ -53,15 +53,15 @@ class CSSPlugin {
53
53
  const hoverInfo = (0, language_service_1.getLanguageService)(extractLanguage(cssDocument)).doHover(cssDocument, cssDocument.getGeneratedPosition(position), cssDocument.stylesheet);
54
54
  return hoverInfo ? (0, documents_1.mapHoverToParent)(cssDocument, hoverInfo) : hoverInfo;
55
55
  }
56
- getCompletions(document, position, completionContext) {
57
- if (!this.featureEnabled('completions')) {
56
+ async getCompletions(document, position, completionContext) {
57
+ if (!(await this.featureEnabled(document, 'completions'))) {
58
58
  return null;
59
59
  }
60
60
  if ((0, documents_1.isInsideFrontmatter)(document.getText(), document.offsetAt(position))) {
61
61
  return null;
62
62
  }
63
- const triggerCharacter = completionContext === null || completionContext === void 0 ? void 0 : completionContext.triggerCharacter;
64
- const triggerKind = completionContext === null || completionContext === void 0 ? void 0 : completionContext.triggerKind;
63
+ const triggerCharacter = completionContext?.triggerCharacter;
64
+ const triggerKind = completionContext?.triggerKind;
65
65
  const isCustomTriggerCharacter = triggerKind === vscode_languageserver_1.CompletionTriggerKind.TriggerCharacter;
66
66
  if (isCustomTriggerCharacter && triggerCharacter && !this.triggerCharacters.has(triggerCharacter)) {
67
67
  return null;
@@ -77,7 +77,7 @@ class CSSPlugin {
77
77
  }
78
78
  if (this.inStyleAttributeWithoutInterpolation(attributeContext, document.getText())) {
79
79
  const [start, end] = attributeContext.valueRange;
80
- return this.getCompletionsInternal(document, position, new StyleAttributeDocument_1.StyleAttributeDocument(document, start, end));
80
+ return await this.getCompletionsInternal(document, position, new StyleAttributeDocument_1.StyleAttributeDocument(document, start, end));
81
81
  }
82
82
  // If we're not in a style attribute, instead give completions for ids and classes used in the current document
83
83
  else if ((attributeContext.name == 'id' || attributeContext.name == 'class') && attributeContext.inValue) {
@@ -87,27 +87,47 @@ class CSSPlugin {
87
87
  return null;
88
88
  }
89
89
  const cssDocument = this.getCSSDocumentForStyleTag(styleTag, document);
90
- return this.getCompletionsInternal(document, position, cssDocument);
90
+ return await this.getCompletionsInternal(document, position, cssDocument);
91
91
  }
92
- getCompletionsInternal(document, position, cssDocument) {
92
+ async getCompletionsInternal(document, position, cssDocument) {
93
+ const emmetConfig = await this.configManager.getEmmetConfig(document);
93
94
  if (isSASS(cssDocument)) {
94
95
  // The CSS language service does not support SASS (not to be confused with SCSS)
95
96
  // however we can at least still at least provide Emmet completions in SASS blocks
96
- return (0, emmet_helper_1.doComplete)(document, position, 'sass', this.configManager.getEmmetConfig()) || null;
97
+ return (0, emmet_helper_1.doComplete)(document, position, 'sass', emmetConfig) || null;
97
98
  }
98
99
  const cssLang = extractLanguage(cssDocument);
99
100
  const langService = (0, language_service_1.getLanguageService)(cssLang);
100
- const emmetResults = {
101
- isIncomplete: true,
101
+ let emmetResults = {
102
+ isIncomplete: false,
102
103
  items: [],
103
104
  };
105
+ const extensionConfig = await this.configManager.getConfig('astro', document.uri);
106
+ if (extensionConfig.css.completions.emmet) {
107
+ langService.setCompletionParticipants([
108
+ {
109
+ onCssProperty: (context) => {
110
+ if (context?.propertyName) {
111
+ emmetResults =
112
+ (0, emmet_helper_1.doComplete)(cssDocument, cssDocument.getGeneratedPosition(position), (0, language_service_1.getLanguage)(cssLang), emmetConfig) || emmetResults;
113
+ }
114
+ },
115
+ onCssPropertyValue: (context) => {
116
+ if (context?.propertyValue) {
117
+ emmetResults =
118
+ (0, emmet_helper_1.doComplete)(cssDocument, cssDocument.getGeneratedPosition(position), (0, language_service_1.getLanguage)(cssLang), emmetConfig) || emmetResults;
119
+ }
120
+ },
121
+ },
122
+ ]);
123
+ }
104
124
  const results = langService.doComplete(cssDocument, cssDocument.getGeneratedPosition(position), cssDocument.stylesheet);
105
125
  return vscode_languageserver_1.CompletionList.create([...(results ? results.items : []), ...emmetResults.items].map((completionItem) => (0, documents_1.mapCompletionItemToOriginal)(cssDocument, completionItem)),
106
126
  // Emmet completions change on every keystroke, so they are never complete
107
127
  emmetResults.items.length > 0);
108
128
  }
109
- getDocumentColors(document) {
110
- if (!this.featureEnabled('documentColors')) {
129
+ async getDocumentColors(document) {
130
+ if (!(await this.featureEnabled(document, 'documentColors'))) {
111
131
  return [];
112
132
  }
113
133
  const allColorInfo = this.getCSSDocumentsForDocument(document).map((cssDoc) => {
@@ -122,8 +142,8 @@ class CSSPlugin {
122
142
  });
123
143
  return (0, lodash_1.flatten)(allColorInfo);
124
144
  }
125
- getColorPresentations(document, range, color) {
126
- if (!this.featureEnabled('colorPresentations')) {
145
+ async getColorPresentations(document, range, color) {
146
+ if (!(await this.featureEnabled(document, 'documentColors'))) {
127
147
  return [];
128
148
  }
129
149
  const allColorPres = this.getCSSDocumentsForDocument(document).map((cssDoc) => {
@@ -147,8 +167,8 @@ class CSSPlugin {
147
167
  });
148
168
  return (0, lodash_1.flatten)(allFoldingRanges);
149
169
  }
150
- getDocumentSymbols(document) {
151
- if (!this.featureEnabled('documentSymbols')) {
170
+ async getDocumentSymbols(document) {
171
+ if (!(await this.featureEnabled(document, 'documentSymbols'))) {
152
172
  return [];
153
173
  }
154
174
  const allDocumentSymbols = this.getCSSDocumentsForDocument(document).map((cssDoc) => {
@@ -194,8 +214,9 @@ class CSSPlugin {
194
214
  return (0, documents_1.isInTag)(position, styleTag);
195
215
  });
196
216
  }
197
- featureEnabled(feature) {
198
- return this.configManager.enabled('css.enabled') && this.configManager.enabled(`css.${feature}.enabled`);
217
+ async featureEnabled(document, feature) {
218
+ return ((await this.configManager.isEnabled(document, 'css')) &&
219
+ (await this.configManager.isEnabled(document, 'css', feature)));
199
220
  }
200
221
  }
201
222
  exports.CSSPlugin = CSSPlugin;
@@ -10,14 +10,14 @@ export declare class HTMLPlugin implements Plugin {
10
10
  private styleScriptTemplate;
11
11
  private configManager;
12
12
  constructor(configManager: ConfigManager);
13
- doHover(document: AstroDocument, position: Position): Hover | null;
13
+ doHover(document: AstroDocument, position: Position): Promise<Hover | null>;
14
14
  /**
15
15
  * Get HTML completions
16
16
  */
17
- getCompletions(document: AstroDocument, position: Position): CompletionList | null;
17
+ getCompletions(document: AstroDocument, position: Position): Promise<CompletionList | null>;
18
18
  getFoldingRanges(document: AstroDocument): FoldingRange[] | null;
19
- doTagComplete(document: AstroDocument, position: Position): string | null;
20
- getDocumentSymbols(document: AstroDocument): SymbolInformation[];
19
+ doTagComplete(document: AstroDocument, position: Position): Promise<string | null>;
20
+ getDocumentSymbols(document: AstroDocument): Promise<SymbolInformation[]>;
21
21
  /**
22
22
  * Get lang completions for style tags (ex: `<style lang="scss">`)
23
23
  */
@@ -25,8 +25,8 @@ class HTMLPlugin {
25
25
  this.styleScriptTemplate = new Set(['style']);
26
26
  this.configManager = configManager;
27
27
  }
28
- doHover(document, position) {
29
- if (!this.featureEnabled('hover')) {
28
+ async doHover(document, position) {
29
+ if (!(await this.featureEnabled(document, 'hover'))) {
30
30
  return null;
31
31
  }
32
32
  const html = document.html;
@@ -46,8 +46,8 @@ class HTMLPlugin {
46
46
  /**
47
47
  * Get HTML completions
48
48
  */
49
- getCompletions(document, position) {
50
- if (!this.featureEnabled('completions')) {
49
+ async getCompletions(document, position) {
50
+ if (!(await this.featureEnabled(document, 'completions'))) {
51
51
  return null;
52
52
  }
53
53
  const html = document.html;
@@ -62,12 +62,15 @@ class HTMLPlugin {
62
62
  isIncomplete: true,
63
63
  items: [],
64
64
  };
65
- this.lang.setCompletionParticipants([
66
- {
67
- onHtmlContent: () => (emmetResults =
68
- (0, emmet_helper_1.doComplete)(document, position, 'html', this.configManager.getEmmetConfig()) || emmetResults),
69
- },
70
- ]);
65
+ const emmetConfig = await this.configManager.getEmmetConfig(document);
66
+ const extensionConfig = await this.configManager.getConfig('astro', document.uri);
67
+ if (extensionConfig.html.completions.emmet) {
68
+ this.lang.setCompletionParticipants([
69
+ {
70
+ onHtmlContent: () => (emmetResults = (0, emmet_helper_1.doComplete)(document, position, 'html', emmetConfig) || emmetResults),
71
+ },
72
+ ]);
73
+ }
71
74
  // If we're in a component starting tag, we do not want HTML language completions
72
75
  // as HTML attributes are not valid for components
73
76
  const results = (0, utils_1.isInComponentStartTag)(html, document.offsetAt(position))
@@ -84,8 +87,8 @@ class HTMLPlugin {
84
87
  }
85
88
  return this.lang.getFoldingRanges(document);
86
89
  }
87
- doTagComplete(document, position) {
88
- if (!this.featureEnabled('tagComplete')) {
90
+ async doTagComplete(document, position) {
91
+ if (!(await this.featureEnabled(document, 'tagComplete'))) {
89
92
  return null;
90
93
  }
91
94
  const html = document.html;
@@ -97,8 +100,8 @@ class HTMLPlugin {
97
100
  }
98
101
  return this.lang.doTagComplete(document, position, html);
99
102
  }
100
- getDocumentSymbols(document) {
101
- if (!this.featureEnabled('documentSymbols')) {
103
+ async getDocumentSymbols(document) {
104
+ if (!(await this.featureEnabled(document, 'documentSymbols'))) {
102
105
  return [];
103
106
  }
104
107
  const html = document.html;
@@ -134,8 +137,9 @@ class HTMLPlugin {
134
137
  }));
135
138
  }
136
139
  }
137
- featureEnabled(feature) {
138
- return this.configManager.enabled('html.enabled') && this.configManager.enabled(`html.${feature}.enabled`);
140
+ async featureEnabled(document, feature) {
141
+ return ((await this.configManager.isEnabled(document, 'html')) &&
142
+ (await this.configManager.isEnabled(document, 'html', feature)));
139
143
  }
140
144
  }
141
145
  exports.HTMLPlugin = HTMLPlugin;