@astrojs/language-server 0.13.3 → 0.15.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 (39) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/core/documents/utils.d.ts +6 -0
  3. package/dist/core/documents/utils.js +17 -1
  4. package/dist/plugins/PluginHost.d.ts +1 -1
  5. package/dist/plugins/PluginHost.js +29 -4
  6. package/dist/plugins/astro/AstroPlugin.d.ts +1 -1
  7. package/dist/plugins/astro/AstroPlugin.js +1 -1
  8. package/dist/plugins/astro/features/CompletionsProvider.d.ts +2 -2
  9. package/dist/plugins/astro/features/CompletionsProvider.js +24 -9
  10. package/dist/plugins/css/CSSPlugin.js +9 -1
  11. package/dist/plugins/css/features/astro-selectors.js +1 -2
  12. package/dist/plugins/html/features/astro-attributes.js +56 -1
  13. package/dist/plugins/html/utils.d.ts +1 -1
  14. package/dist/plugins/html/utils.js +1 -1
  15. package/dist/plugins/interfaces.d.ts +2 -2
  16. package/dist/plugins/typescript/TypeScriptPlugin.d.ts +6 -4
  17. package/dist/plugins/typescript/TypeScriptPlugin.js +12 -4
  18. package/dist/plugins/typescript/astro2tsx.d.ts +1 -1
  19. package/dist/plugins/typescript/astro2tsx.js +11 -6
  20. package/dist/plugins/typescript/features/CompletionsProvider.d.ts +23 -6
  21. package/dist/plugins/typescript/features/CompletionsProvider.js +256 -51
  22. package/dist/plugins/typescript/features/DiagnosticsProvider.js +44 -58
  23. package/dist/plugins/typescript/features/DocumentSymbolsProvider.js +8 -5
  24. package/dist/plugins/typescript/features/FoldingRangesProvider.d.ts +9 -0
  25. package/dist/plugins/typescript/features/FoldingRangesProvider.js +64 -0
  26. package/dist/plugins/typescript/features/SemanticTokenProvider.js +4 -1
  27. package/dist/plugins/typescript/features/utils.d.ts +2 -0
  28. package/dist/plugins/typescript/features/utils.js +7 -1
  29. package/dist/plugins/typescript/language-service.d.ts +1 -1
  30. package/dist/plugins/typescript/language-service.js +44 -23
  31. package/dist/plugins/typescript/snapshots/SnapshotManager.js +2 -1
  32. package/dist/plugins/typescript/snapshots/utils.js +24 -3
  33. package/dist/plugins/typescript/utils.d.ts +3 -0
  34. package/dist/plugins/typescript/utils.js +17 -1
  35. package/dist/server.js +16 -0
  36. package/dist/utils.d.ts +16 -0
  37. package/dist/utils.js +57 -1
  38. package/package.json +4 -4
  39. package/types/astro-jsx.d.ts +112 -113
package/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # @astrojs/language-server
2
2
 
3
+ ## 0.15.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 6bb45cb: Overhaul TypeScript completions
8
+
9
+ - Add support for completions inside expressions
10
+ - Add support for auto imports on completion
11
+ - Fix misc issues in completions (missing description, deprecated stuff not showing as deprecated)
12
+
13
+ ### Patch Changes
14
+
15
+ - 7978de1: Add support for folding JavaScript
16
+ - 3ac74bc: Improve props completions on components
17
+ - Updated dependencies [6bb45cb]
18
+ - @astrojs/svelte-language-integration@0.1.3
19
+
20
+ ## 0.14.0
21
+
22
+ ### Minor Changes
23
+
24
+ - 9118c46: Add support for loading type definitions from Astro itself
25
+
26
+ ### Patch Changes
27
+
28
+ - 9ea5b97: Make TypeScript ignore content of Markdown tags
29
+ - dbf624a: Fix error when returning a response from the frontmatter
30
+
31
+ ## 0.13.4
32
+
33
+ ### Patch Changes
34
+
35
+ - 5874655: Add support for Astro 0.26.0 attributes
36
+
3
37
  ## 0.13.3
4
38
 
5
39
  ### Patch Changes
@@ -11,9 +11,15 @@ export interface TagInformation {
11
11
  start: number;
12
12
  end: number;
13
13
  };
14
+ closed: boolean;
14
15
  }
15
16
  export declare function walk(node: Node): Generator<Node, void, unknown>;
16
17
  export declare function extractStyleTags(source: string, html?: HTMLDocument): TagInformation[];
18
+ export declare function getLineAtPosition(position: Position, text: string): string;
19
+ /**
20
+ * Returns the node if offset is inside a HTML start tag
21
+ */
22
+ export declare function getNodeIfIsInHTMLStartTag(html: HTMLDocument, offset: number): Node | undefined;
17
23
  /**
18
24
  * Return if a Node is a Component
19
25
  */
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getFirstNonWhitespaceIndex = exports.getLineOffsets = exports.offsetAt = exports.positionAt = exports.isInsideFrontmatter = exports.isInsideExpression = exports.isInTag = exports.isInComponentStartTag = exports.isComponentTag = exports.extractStyleTags = exports.walk = void 0;
3
+ exports.getFirstNonWhitespaceIndex = exports.getLineOffsets = exports.offsetAt = exports.positionAt = exports.isInsideFrontmatter = exports.isInsideExpression = exports.isInTag = exports.isInComponentStartTag = exports.isComponentTag = exports.getNodeIfIsInHTMLStartTag = exports.getLineAtPosition = exports.extractStyleTags = exports.walk = void 0;
4
4
  const vscode_languageserver_1 = require("vscode-languageserver");
5
5
  const utils_1 = require("../../utils");
6
6
  const parseHtml_1 = require("./parseHtml");
@@ -48,6 +48,8 @@ function extractTags(text, tag, html) {
48
48
  startPos,
49
49
  endPos,
50
50
  container,
51
+ // vscode-html-languageservice types does not contain this, despite it existing. Annoying
52
+ closed: matchedNode.closed,
51
53
  };
52
54
  }
53
55
  }
@@ -77,6 +79,20 @@ function parseAttributes(rawAttrs) {
77
79
  return attrValue;
78
80
  }
79
81
  }
82
+ function getLineAtPosition(position, text) {
83
+ return text.substring(offsetAt({ line: position.line, character: 0 }, text), offsetAt({ line: position.line, character: Number.MAX_VALUE }, text));
84
+ }
85
+ exports.getLineAtPosition = getLineAtPosition;
86
+ /**
87
+ * Returns the node if offset is inside a HTML start tag
88
+ */
89
+ function getNodeIfIsInHTMLStartTag(html, offset) {
90
+ const node = html.findNodeAt(offset);
91
+ if (!!node.tag && node.tag[0] === node.tag[0].toLowerCase() && (!node.startTagEnd || offset < node.startTagEnd)) {
92
+ return node;
93
+ }
94
+ }
95
+ exports.getNodeIfIsInHTMLStartTag = getNodeIfIsInHTMLStartTag;
80
96
  /**
81
97
  * Return if a Node is a Component
82
98
  */
@@ -12,7 +12,7 @@ export declare class PluginHost {
12
12
  constructor(docManager: DocumentManager);
13
13
  initialize(pluginHostConfig: PluginHostConfig): void;
14
14
  registerPlugin(plugin: Plugin): void;
15
- getCompletions(textDocument: TextDocumentIdentifier, position: Position, completionContext?: CompletionContext): Promise<CompletionList>;
15
+ getCompletions(textDocument: TextDocumentIdentifier, position: Position, completionContext?: CompletionContext, cancellationToken?: CancellationToken): Promise<CompletionList>;
16
16
  resolveCompletion(textDocument: TextDocumentIdentifier, completionItem: AppCompletionItem): Promise<CompletionItem>;
17
17
  getDiagnostics(textDocument: TextDocumentIdentifier): Promise<Diagnostic[]>;
18
18
  doHover(textDocument: TextDocumentIdentifier, position: Position): Promise<Hover | null>;
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PluginHost = void 0;
4
4
  const vscode_languageserver_1 = require("vscode-languageserver");
5
5
  const lodash_1 = require("lodash");
6
+ const utils_1 = require("../utils");
7
+ const documents_1 = require("../core/documents");
6
8
  var ExecuteMode;
7
9
  (function (ExecuteMode) {
8
10
  ExecuteMode[ExecuteMode["None"] = 0] = "None";
@@ -24,11 +26,34 @@ class PluginHost {
24
26
  registerPlugin(plugin) {
25
27
  this.plugins.push(plugin);
26
28
  }
27
- async getCompletions(textDocument, position, completionContext) {
29
+ async getCompletions(textDocument, position, completionContext, cancellationToken) {
28
30
  const document = this.getDocument(textDocument.uri);
29
- const completions = (await this.execute('getCompletions', [document, position, completionContext], ExecuteMode.Collect)).filter((completion) => completion != null);
30
- let flattenedCompletions = (0, lodash_1.flatten)(completions.map((completion) => completion.items));
31
- const isIncomplete = completions.reduce((incomplete, completion) => incomplete || completion.isIncomplete, false);
31
+ const completions = await Promise.all(this.plugins.map(async (plugin) => {
32
+ const result = await this.tryExecutePlugin(plugin, 'getCompletions', [document, position, completionContext, cancellationToken], null);
33
+ if (result) {
34
+ return { result: result, plugin: plugin.__name };
35
+ }
36
+ })).then((fullCompletions) => fullCompletions.filter(utils_1.isNotNullOrUndefined));
37
+ const html = completions.find((completion) => completion.plugin === 'html');
38
+ const ts = completions.find((completion) => completion.plugin === 'typescript');
39
+ const astro = completions.find((completion) => completion.plugin === 'astro');
40
+ if (html && ts) {
41
+ if ((0, documents_1.getNodeIfIsInHTMLStartTag)(document.html, document.offsetAt(position))) {
42
+ ts.result.items = [];
43
+ }
44
+ // If the Astro plugin has completions for us, don't show TypeScript's as they're most likely duplicates
45
+ if (astro && astro.result.items.length > 0 && (0, documents_1.isInComponentStartTag)(document.html, document.offsetAt(position))) {
46
+ ts.result.items = [];
47
+ }
48
+ ts.result.items = ts.result.items.map((item) => {
49
+ if (item.sortText != '-1') {
50
+ item.sortText = 'Z' + (item.sortText || '');
51
+ }
52
+ return item;
53
+ });
54
+ }
55
+ let flattenedCompletions = (0, lodash_1.flatten)(completions.map((completion) => completion.result.items));
56
+ const isIncomplete = completions.reduce((incomplete, completion) => incomplete || completion.result.isIncomplete, false);
32
57
  return vscode_languageserver_1.CompletionList.create(flattenedCompletions, isIncomplete);
33
58
  }
34
59
  async resolveCompletion(textDocument, completionItem) {
@@ -9,7 +9,7 @@ export declare class AstroPlugin implements Plugin {
9
9
  private readonly completionProvider;
10
10
  constructor(docManager: DocumentManager, configManager: ConfigManager, workspaceUris: string[]);
11
11
  getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext): Promise<AppCompletionList | null>;
12
- getFoldingRanges(document: AstroDocument): Promise<FoldingRange[]>;
12
+ getFoldingRanges(document: AstroDocument): FoldingRange[];
13
13
  getDefinitions(document: AstroDocument, position: Position): Promise<DefinitionLink[]>;
14
14
  private isInsideFrontmatter;
15
15
  private isComponentTag;
@@ -22,7 +22,7 @@ class AstroPlugin {
22
22
  const completions = this.completionProvider.getCompletions(document, position, completionContext);
23
23
  return completions;
24
24
  }
25
- async getFoldingRanges(document) {
25
+ getFoldingRanges(document) {
26
26
  const foldingRanges = [];
27
27
  const { frontmatter } = document.astroMeta;
28
28
  // Currently editing frontmatter, don't fold
@@ -1,8 +1,8 @@
1
- import type { AppCompletionList } from '../../interfaces';
1
+ import type { AppCompletionList, CompletionsProvider } from '../../interfaces';
2
2
  import type { AstroDocument, DocumentManager } from '../../../core/documents';
3
3
  import { CompletionContext, Position } from 'vscode-languageserver';
4
4
  import { LanguageServiceManager as TypeScriptLanguageServiceManager } from '../../typescript/LanguageServiceManager';
5
- export declare class CompletionsProviderImpl {
5
+ export declare class CompletionsProviderImpl implements CompletionsProvider {
6
6
  private readonly docManager;
7
7
  private readonly languageServiceManager;
8
8
  directivesHTMLLang: import("vscode-html-languageservice").LanguageService;
@@ -31,19 +31,18 @@ class CompletionsProviderImpl {
31
31
  if (frontmatter)
32
32
  items.push(frontmatter);
33
33
  }
34
+ const html = document.html;
34
35
  const offset = document.offsetAt(position);
35
- if (!(0, utils_1.isInsideFrontmatter)(document.getText(), offset)) {
36
+ const node = html.findNodeAt(offset);
37
+ if ((0, utils_1.isInComponentStartTag)(html, offset) && !(0, utils_1.isInsideExpression)(document.getText(), node.start, offset)) {
36
38
  const props = await this.getPropCompletions(document, position, completionContext);
37
39
  if (props.length) {
38
40
  items.push(...props);
39
41
  }
40
- }
41
- const html = document.html;
42
- if ((0, utils_1.isInComponentStartTag)(html, offset)) {
43
- const node = html.findNodeAt(offset);
44
42
  const isAstro = await this.isAstroComponent(document, node);
45
43
  if (!isAstro) {
46
- items.push(...(0, utils_4.removeDataAttrCompletion)(this.directivesHTMLLang.doComplete(document, position, html).items));
44
+ const directives = (0, utils_4.removeDataAttrCompletion)(this.directivesHTMLLang.doComplete(document, position, html).items);
45
+ items.push(...directives);
47
46
  }
48
47
  }
49
48
  return vscode_languageserver_1.CompletionList.create(items, true);
@@ -124,7 +123,8 @@ class CompletionsProviderImpl {
124
123
  // Add completions for this component's props type properties
125
124
  const properties = componentType.getProperties().filter((property) => property.name !== 'children') || [];
126
125
  properties.forEach((property) => {
127
- let completionItem = this.getCompletionItemForProperty(property, typeChecker);
126
+ const type = typeChecker.getTypeOfSymbolAtLocation(property, imp);
127
+ let completionItem = this.getCompletionItemForProperty(property, typeChecker, type);
128
128
  completionItems.push(completionItem);
129
129
  });
130
130
  // Ensure that props shows up first as a completion, despite this plugin being ran after the HTML one
@@ -181,10 +181,25 @@ class CompletionsProviderImpl {
181
181
  }
182
182
  return null;
183
183
  }
184
- getCompletionItemForProperty(mem, typeChecker) {
184
+ getCompletionItemForProperty(mem, typeChecker, type) {
185
+ const typeString = typeChecker.typeToString(type);
186
+ let insertText = mem.name;
187
+ switch (typeString) {
188
+ case 'string':
189
+ insertText = `${mem.name}="$1"`;
190
+ break;
191
+ case 'boolean':
192
+ insertText = mem.name;
193
+ break;
194
+ default:
195
+ insertText = `${mem.name}={$1}`;
196
+ break;
197
+ }
185
198
  let item = {
186
199
  label: mem.name,
187
- insertText: mem.name,
200
+ detail: typeString,
201
+ insertText: insertText,
202
+ insertTextFormat: vscode_languageserver_1.InsertTextFormat.Snippet,
188
203
  commitCharacters: [],
189
204
  };
190
205
  mem.getDocumentationComment(typeChecker);
@@ -25,6 +25,12 @@ class CSSPlugin {
25
25
  return null;
26
26
  }
27
27
  const styleTag = this.getStyleTagForPosition(document, position);
28
+ // We technically can return results even for open tags, however, a lot of the info returned is not valid
29
+ // Since most editors will automatically close the tag before the user start working in them, this shouldn't be a problem
30
+ if (styleTag && !styleTag.closed) {
31
+ return null;
32
+ }
33
+ // If we don't have a style tag at this position, we might be in a style property instead, let's check
28
34
  if (!styleTag) {
29
35
  const attributeContext = (0, parseHtml_1.getAttributeContextAtPosition)(document, position);
30
36
  if (!attributeContext) {
@@ -61,7 +67,9 @@ class CSSPlugin {
61
67
  return null;
62
68
  }
63
69
  const styleTag = this.getStyleTagForPosition(document, position);
64
- // If we don't have a style tag at this position, we might be in a style property instead, let's check
70
+ if (styleTag && !styleTag.closed) {
71
+ return null;
72
+ }
65
73
  if (!styleTag) {
66
74
  const attributeContext = (0, parseHtml_1.getAttributeContextAtPosition)(document, position);
67
75
  if (!attributeContext) {
@@ -4,8 +4,7 @@ exports.pseudoClass = void 0;
4
4
  exports.pseudoClass = [
5
5
  {
6
6
  name: ':global()',
7
- description: `[astro] :global modifier
8
- Apply styles to a selector globally`,
7
+ description: 'Apply styles to a selector globally',
9
8
  references: [
10
9
  {
11
10
  name: 'Astro documentation',
@@ -43,7 +43,7 @@ exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)
43
43
  // The VS Code tag definitions does not provide a description for the deprecated `charset` attribute on script tags
44
44
  // Which mean that since we get no hover info for this, we instead get JSX hover info. So we'll just specify a description ourselves for this specific case
45
45
  name: 'charset',
46
- description: "(Deprecated) It's unnecessary to specify the charset attribute, because documents must use UTF-8, and the script element inherits its character encoding from the document.",
46
+ description: "**Deprecated**\n\nIt's unnecessary to specify the charset attribute, because documents must use UTF-8, and the script element inherits its character encoding from the document.",
47
47
  },
48
48
  {
49
49
  name: 'define:vars',
@@ -55,6 +55,28 @@ exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)
55
55
  },
56
56
  ],
57
57
  },
58
+ {
59
+ name: 'hoist',
60
+ description: '**Deprecated in Astro >= 0.26.0**\n\nBuilds, optimizes, and bundles your script with the other JavaScript on the page',
61
+ valueSet: 'v',
62
+ references: [
63
+ {
64
+ name: 'Astro documentation',
65
+ url: 'https://docs.astro.build/en/core-concepts/astro-components/#using-hoisted-scripts',
66
+ },
67
+ ],
68
+ },
69
+ {
70
+ name: 'is:inline',
71
+ description: 'Leave a script tag inline in the page template. No processing will be done on its content',
72
+ valueSet: 'v',
73
+ references: [
74
+ {
75
+ name: 'Astro documentation',
76
+ url: 'https://docs.astro.build/en/migrate/#new-default-script-behavior',
77
+ },
78
+ ],
79
+ },
58
80
  ],
59
81
  },
60
82
  {
@@ -70,6 +92,39 @@ exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)
70
92
  },
71
93
  ],
72
94
  },
95
+ {
96
+ name: 'global',
97
+ description: '**Deprecated in favor of `is:global` in >= Astro 0.26.0**\n\nOpts-out of automatic CSS scoping, all contents will be available globally',
98
+ valueSet: 'v',
99
+ references: [
100
+ {
101
+ name: 'Astro documentation',
102
+ url: 'https://docs.astro.build/en/guides/styling/#global-styles',
103
+ },
104
+ ],
105
+ },
106
+ {
107
+ name: 'is:global',
108
+ description: 'Opts-out of automatic CSS scoping, all contents will be available globally',
109
+ valueSet: 'v',
110
+ references: [
111
+ {
112
+ name: 'Astro documentation',
113
+ url: 'https://docs.astro.build/en/guides/styling/#global-styles',
114
+ },
115
+ ],
116
+ },
117
+ {
118
+ name: 'is:inline',
119
+ description: 'Leave a style tag inline in the page template. No processing will be done on its content',
120
+ valueSet: 'v',
121
+ references: [
122
+ {
123
+ name: 'Astro documentation',
124
+ url: 'https://docs.astro.build/en/migrate/#new-default-script-behavior',
125
+ },
126
+ ],
127
+ },
73
128
  ],
74
129
  },
75
130
  ],
@@ -1,6 +1,6 @@
1
1
  import { CompletionItem } from 'vscode-languageserver-types';
2
2
  /**
3
3
  * The VS Code HTML language service provides a completion for data attributes that is independent from
4
- * data providers, which mean that you can't disable it, so this function removes them from a completionList
4
+ * data providers, which mean that you can't disable it, so this function removes them from completions
5
5
  */
6
6
  export declare function removeDataAttrCompletion(items: CompletionItem[]): CompletionItem[];
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.removeDataAttrCompletion = void 0;
4
4
  /**
5
5
  * The VS Code HTML language service provides a completion for data attributes that is independent from
6
- * data providers, which mean that you can't disable it, so this function removes them from a completionList
6
+ * data providers, which mean that you can't disable it, so this function removes them from completions
7
7
  */
8
8
  function removeDataAttrCompletion(items) {
9
9
  return items.filter((item) => !item.label.startsWith('data-'));
@@ -13,7 +13,7 @@ export interface DiagnosticsProvider {
13
13
  export interface HoverProvider {
14
14
  doHover(document: TextDocument, position: Position): Resolvable<Hover | null>;
15
15
  }
16
- export interface FoldingRangeProvider {
16
+ export interface FoldingRangesProvider {
17
17
  getFoldingRanges(document: TextDocument): Resolvable<FoldingRange[] | null>;
18
18
  }
19
19
  export interface CompletionsProvider<T extends TextDocumentIdentifier = any> {
@@ -81,7 +81,7 @@ export interface OnWatchFileChangesProvider {
81
81
  export interface UpdateNonAstroFile {
82
82
  updateNonAstroFile(fileName: string, changes: TextDocumentContentChangeEvent[]): void;
83
83
  }
84
- declare type ProviderBase = DiagnosticsProvider & HoverProvider & CompletionsProvider & DefinitionsProvider & FormattingProvider & FoldingRangeProvider & TagCompleteProvider & DocumentColorsProvider & ColorPresentationsProvider & DocumentSymbolsProvider & UpdateImportsProvider & CodeActionsProvider & FindReferencesProvider & RenameProvider & SignatureHelpProvider & SemanticTokensProvider & SelectionRangeProvider & OnWatchFileChangesProvider & LinkedEditingRangesProvider & UpdateNonAstroFile;
84
+ declare type ProviderBase = DiagnosticsProvider & HoverProvider & CompletionsProvider & DefinitionsProvider & FormattingProvider & FoldingRangesProvider & TagCompleteProvider & DocumentColorsProvider & ColorPresentationsProvider & DocumentSymbolsProvider & UpdateImportsProvider & CodeActionsProvider & FindReferencesProvider & RenameProvider & SignatureHelpProvider & SemanticTokensProvider & SelectionRangeProvider & OnWatchFileChangesProvider & LinkedEditingRangesProvider & UpdateNonAstroFile;
85
85
  export declare type LSProvider = ProviderBase;
86
86
  export declare type Plugin = Partial<ProviderBase> & {
87
87
  __name: string;
@@ -1,8 +1,8 @@
1
- import { CancellationToken, CompletionContext, DefinitionLink, Diagnostic, Hover, Position, Range, SemanticTokens, SignatureHelp, SignatureHelpContext, SymbolInformation, TextDocumentContentChangeEvent, WorkspaceEdit } from 'vscode-languageserver';
1
+ import { CancellationToken, CompletionContext, DefinitionLink, Diagnostic, FoldingRange, Hover, Position, Range, SemanticTokens, SignatureHelp, SignatureHelpContext, SymbolInformation, TextDocumentContentChangeEvent, WorkspaceEdit } from 'vscode-languageserver';
2
2
  import { ConfigManager } from '../../core/config';
3
3
  import { AstroDocument, DocumentManager } from '../../core/documents';
4
4
  import { AppCompletionItem, AppCompletionList, OnWatchFileChangesParam, Plugin } from '../interfaces';
5
- import { CompletionEntryWithIdentifer } from './features/CompletionsProvider';
5
+ import { CompletionItemData } from './features/CompletionsProvider';
6
6
  export declare class TypeScriptPlugin implements Plugin {
7
7
  __name: string;
8
8
  private configManager;
@@ -13,13 +13,15 @@ export declare class TypeScriptPlugin implements Plugin {
13
13
  private readonly diagnosticsProvider;
14
14
  private readonly documentSymbolsProvider;
15
15
  private readonly semanticTokensProvider;
16
+ private readonly foldingRangesProvider;
16
17
  constructor(docManager: DocumentManager, configManager: ConfigManager, workspaceUris: string[]);
17
18
  doHover(document: AstroDocument, position: Position): Promise<Hover | null>;
18
19
  rename(document: AstroDocument, position: Position, newName: string): Promise<WorkspaceEdit | null>;
20
+ getFoldingRanges(document: AstroDocument): Promise<FoldingRange[] | null>;
19
21
  getSemanticTokens(textDocument: AstroDocument, range?: Range, cancellationToken?: CancellationToken): Promise<SemanticTokens | null>;
20
22
  getDocumentSymbols(document: AstroDocument): Promise<SymbolInformation[]>;
21
- getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext): Promise<AppCompletionList<CompletionEntryWithIdentifer> | null>;
22
- resolveCompletion(document: AstroDocument, completionItem: AppCompletionItem<CompletionEntryWithIdentifer>): Promise<AppCompletionItem<CompletionEntryWithIdentifer>>;
23
+ getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext, cancellationToken?: CancellationToken): Promise<AppCompletionList<CompletionItemData> | null>;
24
+ resolveCompletion(document: AstroDocument, completionItem: AppCompletionItem<CompletionItemData>, cancellationToken?: CancellationToken): Promise<AppCompletionItem<CompletionItemData>>;
23
25
  getDefinitions(document: AstroDocument, position: Position): Promise<DefinitionLink[]>;
24
26
  getDiagnostics(document: AstroDocument, cancellationToken?: CancellationToken): Promise<Diagnostic[]>;
25
27
  onWatchFileChanges(onWatchFileChangesParas: OnWatchFileChangesParam[]): Promise<void>;
@@ -37,6 +37,7 @@ const LanguageServiceManager_1 = require("./LanguageServiceManager");
37
37
  const utils_3 = require("./utils");
38
38
  const DocumentSymbolsProvider_1 = require("./features/DocumentSymbolsProvider");
39
39
  const SemanticTokenProvider_1 = require("./features/SemanticTokenProvider");
40
+ const FoldingRangesProvider_1 = require("./features/FoldingRangesProvider");
40
41
  class TypeScriptPlugin {
41
42
  constructor(docManager, configManager, workspaceUris) {
42
43
  this.__name = 'typescript';
@@ -48,6 +49,7 @@ class TypeScriptPlugin {
48
49
  this.diagnosticsProvider = new DiagnosticsProvider_1.DiagnosticsProviderImpl(this.languageServiceManager);
49
50
  this.documentSymbolsProvider = new DocumentSymbolsProvider_1.DocumentSymbolsProviderImpl(this.languageServiceManager);
50
51
  this.semanticTokensProvider = new SemanticTokenProvider_1.SemanticTokensProviderImpl(this.languageServiceManager);
52
+ this.foldingRangesProvider = new FoldingRangesProvider_1.FoldingRangesProviderImpl(this.languageServiceManager);
51
53
  }
52
54
  async doHover(document, position) {
53
55
  if (!this.featureEnabled('hover')) {
@@ -78,7 +80,13 @@ class TypeScriptPlugin {
78
80
  });
79
81
  return edit;
80
82
  }
83
+ async getFoldingRanges(document) {
84
+ return this.foldingRangesProvider.getFoldingRanges(document);
85
+ }
81
86
  async getSemanticTokens(textDocument, range, cancellationToken) {
87
+ if (!this.featureEnabled('semanticTokens')) {
88
+ return null;
89
+ }
82
90
  return this.semanticTokensProvider.getSemanticTokens(textDocument, range, cancellationToken);
83
91
  }
84
92
  async getDocumentSymbols(document) {
@@ -88,15 +96,15 @@ class TypeScriptPlugin {
88
96
  const symbols = await this.documentSymbolsProvider.getDocumentSymbols(document);
89
97
  return symbols;
90
98
  }
91
- async getCompletions(document, position, completionContext) {
99
+ async getCompletions(document, position, completionContext, cancellationToken) {
92
100
  if (!this.featureEnabled('completions')) {
93
101
  return null;
94
102
  }
95
- const completions = await this.completionProvider.getCompletions(document, position, completionContext);
103
+ const completions = await this.completionProvider.getCompletions(document, position, completionContext, cancellationToken);
96
104
  return completions;
97
105
  }
98
- async resolveCompletion(document, completionItem) {
99
- return this.completionProvider.resolveCompletion(document, completionItem);
106
+ async resolveCompletion(document, completionItem, cancellationToken) {
107
+ return this.completionProvider.resolveCompletion(document, completionItem, cancellationToken);
100
108
  }
101
109
  async getDefinitions(document, position) {
102
110
  const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
@@ -1,5 +1,5 @@
1
1
  interface Astro2TSXResult {
2
2
  code: string;
3
3
  }
4
- export default function (content: string): Astro2TSXResult;
4
+ export default function (content: string, className: string): Astro2TSXResult;
5
5
  export {};
@@ -2,17 +2,17 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const os_1 = require("os");
4
4
  const parseAstro_1 = require("../../core/documents/parseAstro");
5
- function addProps(content) {
5
+ function addProps(content, className) {
6
6
  let defaultExportType = 'Record<string, any>';
7
7
  if (/(interface|type) Props/.test(content)) {
8
8
  defaultExportType = 'Props';
9
9
  }
10
- return os_1.EOL + `export default function (_props: ${defaultExportType}) { return <div></div>; }`;
10
+ return os_1.EOL + `export default function ${className}__AstroComponent_(_props: ${defaultExportType}): any {}`;
11
11
  }
12
12
  function escapeTemplateLiteralContent(content) {
13
13
  return content.replace(/`/g, '\\`');
14
14
  }
15
- function default_1(content) {
15
+ function default_1(content, className) {
16
16
  var _a, _b;
17
17
  let result = {
18
18
  code: '',
@@ -24,8 +24,9 @@ function default_1(content) {
24
24
  frontMatterRaw = content
25
25
  .substring((_a = astroDocument.frontmatter.startOffset) !== null && _a !== void 0 ? _a : 0, ((_b = astroDocument.frontmatter.endOffset) !== null && _b !== void 0 ? _b : 0) + 3)
26
26
  // Handle case where semicolons is not used in the frontmatter section
27
+ // We need to add something before the semi-colon or TypeScript won't be able to do completions
27
28
  .replace(/((?!^)(?<!;)\n)(---)/g, (_whole, start, _dashes) => {
28
- return start + ';' + '//';
29
+ return start + '"";';
29
30
  })
30
31
  // Replace frontmatter marks with comments
31
32
  .replace(/---/g, '///');
@@ -38,9 +39,13 @@ function default_1(content) {
38
39
  .replace(/<\s*!--([^-->]*)(.*?)-->/gs, (whole) => {
39
40
  return `{/*${whole}*/}`;
40
41
  })
41
- // Turn styles into internal strings
42
+ // Turn styles tags into internal strings
42
43
  .replace(/<\s*style([^>]*)>(.*?)<\s*\/\s*style>/gs, (_whole, attrs, children) => {
43
44
  return `<style${attrs}>{\`${escapeTemplateLiteralContent(children)}\`}</style>`;
45
+ })
46
+ // Turn Markdown tags into internal strings
47
+ .replace(/<\s*Markdown([^>]*)>(.*?)<\s*\/\s*Markdown>/gs, (_whole, attrs, children) => {
48
+ return `<Markdown${attrs}>{\`${escapeTemplateLiteralContent(children)}\`}</Markdown>`;
44
49
  })
45
50
  // Turn scripts into function calls
46
51
  .replace(/<\s*script([^\/>]*)>(.*?)<\s*\/\s*script>/gs, (_whole, attrs, children, offset) => {
@@ -76,7 +81,7 @@ function default_1(content) {
76
81
  htmlRaw +
77
82
  os_1.EOL +
78
83
  // Add TypeScript definitions
79
- addProps(frontMatterRaw);
84
+ addProps(frontMatterRaw, className);
80
85
  return result;
81
86
  }
82
87
  exports.default = default_1;
@@ -1,16 +1,33 @@
1
- import type { CompletionContext, Position, TextDocumentIdentifier } from 'vscode-languageserver';
1
+ import { CompletionContext, Position, TextDocumentIdentifier, TextEdit, CancellationToken } from 'vscode-languageserver';
2
2
  import type { LanguageServiceManager } from '../LanguageServiceManager';
3
3
  import { AstroDocument } from '../../../core/documents';
4
4
  import ts from 'typescript';
5
5
  import { AppCompletionItem, AppCompletionList, CompletionsProvider } from '../../interfaces';
6
- export interface CompletionEntryWithIdentifer extends ts.CompletionEntry, TextDocumentIdentifier {
7
- position: Position;
6
+ import { AstroSnapshotFragment } from '../snapshots/DocumentSnapshot';
7
+ export interface CompletionItemData extends TextDocumentIdentifier {
8
+ filePath: string;
9
+ offset: number;
10
+ originalItem: ts.CompletionEntry;
8
11
  }
9
- export declare class CompletionsProviderImpl implements CompletionsProvider<CompletionEntryWithIdentifer> {
12
+ export declare class CompletionsProviderImpl implements CompletionsProvider<CompletionItemData> {
10
13
  private languageServiceManager;
11
14
  constructor(languageServiceManager: LanguageServiceManager);
12
- getCompletions(document: AstroDocument, position: Position, _completionContext?: CompletionContext): Promise<AppCompletionList<CompletionEntryWithIdentifer> | null>;
13
- resolveCompletion(document: AstroDocument, completionItem: AppCompletionItem<CompletionEntryWithIdentifer>): Promise<AppCompletionItem<CompletionEntryWithIdentifer>>;
15
+ private readonly validTriggerCharacters;
16
+ private isValidTriggerCharacter;
17
+ private lastCompletion?;
18
+ getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext, cancellationToken?: CancellationToken): Promise<AppCompletionList<CompletionItemData> | null>;
19
+ resolveCompletion(document: AstroDocument, item: AppCompletionItem<CompletionItemData>, cancellationToken?: CancellationToken): Promise<AppCompletionItem<CompletionItemData>>;
14
20
  private toCompletionItem;
21
+ private isValidCompletion;
22
+ codeActionChangeToTextEdit(document: AstroDocument, fragment: AstroSnapshotFragment, change: ts.TextChange): TextEdit;
15
23
  private getCompletionDocument;
24
+ /**
25
+ * If the textEdit is out of the word range of the triggered position
26
+ * vscode would refuse to show the completions
27
+ * split those edits into additionalTextEdit to fix it
28
+ */
29
+ private fixTextEditRange;
30
+ private canReuseLastCompletion;
31
+ private getExistingImports;
32
+ private isAstroComponentImport;
16
33
  }