@astrojs/language-server 0.26.2 → 0.28.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 (29) hide show
  1. package/dist/plugins/PluginHost.d.ts +7 -4
  2. package/dist/plugins/PluginHost.js +17 -5
  3. package/dist/plugins/astro/features/CompletionsProvider.js +2 -2
  4. package/dist/plugins/html/HTMLPlugin.js +1 -1
  5. package/dist/plugins/html/features/astro-attributes.js +3 -0
  6. package/dist/plugins/interfaces.d.ts +10 -4
  7. package/dist/plugins/typescript/LanguageServiceManager.d.ts +6 -1
  8. package/dist/plugins/typescript/LanguageServiceManager.js +8 -2
  9. package/dist/plugins/typescript/TypeScriptPlugin.d.ts +13 -3
  10. package/dist/plugins/typescript/TypeScriptPlugin.js +27 -5
  11. package/dist/plugins/typescript/astro-sys.js +1 -1
  12. package/dist/plugins/typescript/features/CodeActionsProvider.js +2 -1
  13. package/dist/plugins/typescript/features/FileReferencesProvider.d.ts +9 -0
  14. package/dist/plugins/typescript/features/FileReferencesProvider.js +28 -0
  15. package/dist/plugins/typescript/features/ImplementationsProvider.d.ts +9 -0
  16. package/dist/plugins/typescript/features/ImplementationsProvider.js +51 -0
  17. package/dist/plugins/typescript/features/ReferencesProvider.d.ts +9 -0
  18. package/dist/plugins/typescript/features/ReferencesProvider.js +54 -0
  19. package/dist/plugins/typescript/features/TypeDefinitionsProvider.d.ts +2 -2
  20. package/dist/plugins/typescript/language-service.d.ts +1 -1
  21. package/dist/plugins/typescript/language-service.js +3 -3
  22. package/dist/plugins/typescript/snapshots/DocumentSnapshot.d.ts +2 -3
  23. package/dist/plugins/typescript/snapshots/DocumentSnapshot.js +2 -2
  24. package/dist/plugins/typescript/snapshots/SnapshotManager.d.ts +2 -3
  25. package/dist/plugins/typescript/snapshots/SnapshotManager.js +9 -21
  26. package/dist/plugins/typescript/snapshots/utils.d.ts +3 -3
  27. package/dist/plugins/typescript/snapshots/utils.js +9 -9
  28. package/dist/server.js +13 -6
  29. package/package.json +3 -2
@@ -1,4 +1,4 @@
1
- import { CancellationToken, CodeAction, CodeActionContext, Color, ColorInformation, ColorPresentation, CompletionContext, CompletionItem, CompletionList, DefinitionLink, Diagnostic, FoldingRange, FormattingOptions, Hover, InlayHint, LinkedEditingRanges, Location, Position, Range, SemanticTokens, SignatureHelp, SignatureHelpContext, SymbolInformation, TextDocumentContentChangeEvent, TextDocumentIdentifier, TextEdit, WorkspaceEdit } from 'vscode-languageserver';
1
+ import { CancellationToken, CodeAction, CodeActionContext, Color, ColorInformation, ColorPresentation, CompletionContext, CompletionItem, CompletionList, DefinitionLink, Diagnostic, FoldingRange, FormattingOptions, Hover, InlayHint, LinkedEditingRanges, Location, Position, Range, ReferenceContext, SemanticTokens, SignatureHelp, SignatureHelpContext, SymbolInformation, TextDocumentContentChangeEvent, TextDocumentIdentifier, TextEdit, WorkspaceEdit } from 'vscode-languageserver';
2
2
  import type { DocumentManager } from '../core/documents/DocumentManager';
3
3
  import type { AppCompletionItem, Plugin } from './interfaces';
4
4
  export interface PluginHostConfig {
@@ -23,15 +23,18 @@ export declare class PluginHost {
23
23
  getDocumentSymbols(textDocument: TextDocumentIdentifier, cancellationToken?: CancellationToken): Promise<SymbolInformation[]>;
24
24
  getSemanticTokens(textDocument: TextDocumentIdentifier, range?: Range, cancellationToken?: CancellationToken): Promise<SemanticTokens | null>;
25
25
  getLinkedEditingRanges(textDocument: TextDocumentIdentifier, position: Position): Promise<LinkedEditingRanges | null>;
26
+ fileReferences(textDocument: TextDocumentIdentifier): Promise<Location[] | null>;
26
27
  getDefinitions(textDocument: TextDocumentIdentifier, position: Position): Promise<DefinitionLink[] | Location[]>;
27
- getTypeDefinition(textDocument: TextDocumentIdentifier, position: Position): Promise<Location[] | null>;
28
+ getTypeDefinitions(textDocument: TextDocumentIdentifier, position: Position): Promise<Location[] | null>;
29
+ getImplementations(textDocument: TextDocumentIdentifier, position: Position): Promise<Location[] | null>;
30
+ getReferences(textdocument: TextDocumentIdentifier, position: Position, context: ReferenceContext): Promise<Location[] | null>;
28
31
  rename(textDocument: TextDocumentIdentifier, position: Position, newName: string): Promise<WorkspaceEdit | null>;
29
32
  getDocumentColors(textDocument: TextDocumentIdentifier): Promise<ColorInformation[]>;
30
33
  getColorPresentations(textDocument: TextDocumentIdentifier, range: Range, color: Color): Promise<ColorPresentation[]>;
31
34
  getInlayHints(textDocument: TextDocumentIdentifier, range: Range, cancellationToken?: CancellationToken): Promise<InlayHint[]>;
32
35
  getSignatureHelp(textDocument: TextDocumentIdentifier, position: Position, context: SignatureHelpContext | undefined, cancellationToken?: CancellationToken): Promise<SignatureHelp | null>;
33
- onWatchFileChanges(onWatchFileChangesParams: any[]): void;
34
- updateNonAstroFile(fileName: string, changes: TextDocumentContentChangeEvent[]): void;
36
+ onWatchFileChanges(onWatchFileChangesParams: any[]): Promise<void>;
37
+ updateNonAstroFile(fileName: string, changes: TextDocumentContentChangeEvent[], text?: string): void;
35
38
  private getDocument;
36
39
  private execute;
37
40
  private tryExecutePlugin;
@@ -105,6 +105,10 @@ class PluginHost {
105
105
  const document = this.getDocument(textDocument.uri);
106
106
  return await this.execute('getLinkedEditingRanges', [document, position], ExecuteMode.FirstNonNull);
107
107
  }
108
+ async fileReferences(textDocument) {
109
+ const document = this.getDocument(textDocument.uri);
110
+ return await this.execute('fileReferences', [document], ExecuteMode.FirstNonNull);
111
+ }
108
112
  async getDefinitions(textDocument, position) {
109
113
  const document = this.getDocument(textDocument.uri);
110
114
  const definitions = await this.execute('getDefinitions', [document, position], ExecuteMode.Collect);
@@ -115,10 +119,18 @@ class PluginHost {
115
119
  return definitions.map((def) => ({ range: def.targetSelectionRange, uri: def.targetUri }));
116
120
  }
117
121
  }
118
- getTypeDefinition(textDocument, position) {
122
+ getTypeDefinitions(textDocument, position) {
119
123
  const document = this.getDocument(textDocument.uri);
120
124
  return this.execute('getTypeDefinitions', [document, position], ExecuteMode.FirstNonNull);
121
125
  }
126
+ getImplementations(textDocument, position) {
127
+ const document = this.getDocument(textDocument.uri);
128
+ return this.execute('getImplementation', [document, position], ExecuteMode.FirstNonNull);
129
+ }
130
+ getReferences(textdocument, position, context) {
131
+ const document = this.getDocument(textdocument.uri);
132
+ return this.execute('findReferences', [document, position, context], ExecuteMode.FirstNonNull);
133
+ }
122
134
  async rename(textDocument, position, newName) {
123
135
  const document = this.getDocument(textDocument.uri);
124
136
  return this.execute('rename', [document, position, newName], ExecuteMode.FirstNonNull);
@@ -139,14 +151,14 @@ class PluginHost {
139
151
  const document = this.getDocument(textDocument.uri);
140
152
  return await this.execute('getSignatureHelp', [document, position, context, cancellationToken], ExecuteMode.FirstNonNull);
141
153
  }
142
- onWatchFileChanges(onWatchFileChangesParams) {
154
+ async onWatchFileChanges(onWatchFileChangesParams) {
143
155
  for (const support of this.plugins) {
144
- support.onWatchFileChanges?.(onWatchFileChangesParams);
156
+ await support.onWatchFileChanges?.(onWatchFileChangesParams);
145
157
  }
146
158
  }
147
- updateNonAstroFile(fileName, changes) {
159
+ updateNonAstroFile(fileName, changes, text) {
148
160
  for (const support of this.plugins) {
149
- support.updateNonAstroFile?.(fileName, changes);
161
+ support.updateNonAstroFile?.(fileName, changes, text);
150
162
  }
151
163
  }
152
164
  getDocument(uri) {
@@ -34,7 +34,7 @@ class CompletionsProviderImpl {
34
34
  items.push(...props);
35
35
  }
36
36
  const isAstro = componentFilePath?.endsWith('.astro');
37
- if (!isAstro) {
37
+ if (!isAstro && node.tag !== 'Fragment') {
38
38
  const directives = (0, utils_2.removeDataAttrCompletion)(this.directivesHTMLLang.doComplete(document, position, html).items);
39
39
  items.push(...directives);
40
40
  }
@@ -157,7 +157,7 @@ class CompletionsProviderImpl {
157
157
  if (this.ts.isImportDeclaration(node)) {
158
158
  let clauses = node.importClause;
159
159
  if (!clauses)
160
- return null;
160
+ continue;
161
161
  let namedImport = clauses.getChildAt(0);
162
162
  if (this.ts.isNamedImports(namedImport)) {
163
163
  for (let imp of namedImport.elements) {
@@ -37,7 +37,7 @@ class HTMLPlugin {
37
37
  return null;
38
38
  }
39
39
  // If the node we're hovering on is a component, instead only provide astro-specific hover info
40
- if ((0, utils_1.isPossibleComponent)(node)) {
40
+ if ((0, utils_1.isPossibleComponent)(node) && node.tag !== 'Fragment') {
41
41
  return this.componentLang.doHover(document, position, html);
42
42
  }
43
43
  return this.lang.doHover(document, position, html);
@@ -2,6 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.astroDirectives = exports.astroAttributes = exports.astroElements = exports.classListAttribute = void 0;
4
4
  const vscode_html_languageservice_1 = require("vscode-html-languageservice");
5
+ const defaultProvider = (0, vscode_html_languageservice_1.getDefaultHTMLDataProvider)();
6
+ const slotAttr = defaultProvider.provideAttributes('div').find((attr) => attr.name === 'slot');
5
7
  exports.classListAttribute = (0, vscode_html_languageservice_1.newHTMLDataProvider)('class-list', {
6
8
  version: 1,
7
9
  globalAttributes: [
@@ -169,6 +171,7 @@ exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)
169
171
  },
170
172
  ],
171
173
  },
174
+ slotAttr,
172
175
  ],
173
176
  });
174
177
  exports.astroDirectives = (0, vscode_html_languageservice_1.newHTMLDataProvider)('astro-directives', {
@@ -35,6 +35,9 @@ export interface ColorPresentationsProvider {
35
35
  export interface DocumentSymbolsProvider {
36
36
  getDocumentSymbols(document: TextDocument): Resolvable<SymbolInformation[]>;
37
37
  }
38
+ export interface FileReferencesProvider {
39
+ fileReferences(document: TextDocument): Promise<Location[] | null>;
40
+ }
38
41
  export interface DefinitionsProvider {
39
42
  getDefinitions(document: TextDocument, position: Position): Resolvable<DefinitionLink[]>;
40
43
  }
@@ -74,7 +77,10 @@ export interface SemanticTokensProvider {
74
77
  export interface LinkedEditingRangesProvider {
75
78
  getLinkedEditingRanges(document: TextDocument, position: Position): Resolvable<LinkedEditingRanges | null>;
76
79
  }
77
- export interface TypeDefinitionProvider {
80
+ export interface ImplementationProvider {
81
+ getImplementation(document: TextDocument, position: Position): Resolvable<Location[] | null>;
82
+ }
83
+ export interface TypeDefinitionsProvider {
78
84
  getTypeDefinitions(document: TextDocument, position: Position): Resolvable<Location[] | null>;
79
85
  }
80
86
  export interface OnWatchFileChangesParam {
@@ -82,12 +88,12 @@ export interface OnWatchFileChangesParam {
82
88
  changeType: FileChangeType;
83
89
  }
84
90
  export interface OnWatchFileChangesProvider {
85
- onWatchFileChanges(onWatchFileChangesParams: OnWatchFileChangesParam[]): void;
91
+ onWatchFileChanges(onWatchFileChangesParams: OnWatchFileChangesParam[]): Promise<void>;
86
92
  }
87
93
  export interface UpdateNonAstroFile {
88
- updateNonAstroFile(fileName: string, changes: TextDocumentContentChangeEvent[]): void;
94
+ updateNonAstroFile(fileName: string, changes: TextDocumentContentChangeEvent[], text?: string): void;
89
95
  }
90
- declare type ProviderBase = DiagnosticsProvider & HoverProvider & CompletionsProvider & DefinitionsProvider & TypeDefinitionProvider & FormattingProvider & FoldingRangesProvider & TagCompleteProvider & DocumentColorsProvider & ColorPresentationsProvider & DocumentSymbolsProvider & UpdateImportsProvider & CodeActionsProvider & FindReferencesProvider & RenameProvider & SignatureHelpProvider & SemanticTokensProvider & SelectionRangeProvider & OnWatchFileChangesProvider & LinkedEditingRangesProvider & InlayHintsProvider & UpdateNonAstroFile;
96
+ declare type ProviderBase = DiagnosticsProvider & HoverProvider & CompletionsProvider & FileReferencesProvider & DefinitionsProvider & TypeDefinitionsProvider & ImplementationProvider & FormattingProvider & FoldingRangesProvider & TagCompleteProvider & DocumentColorsProvider & ColorPresentationsProvider & DocumentSymbolsProvider & UpdateImportsProvider & CodeActionsProvider & FindReferencesProvider & RenameProvider & SignatureHelpProvider & SemanticTokensProvider & SelectionRangeProvider & OnWatchFileChangesProvider & LinkedEditingRangesProvider & InlayHintsProvider & UpdateNonAstroFile;
91
97
  export declare type LSProvider = ProviderBase;
92
98
  export declare type Plugin = Partial<ProviderBase> & {
93
99
  __name: string;
@@ -3,6 +3,7 @@ import type { ConfigManager } from '../../core/config';
3
3
  import type { AstroDocument, DocumentManager } from '../../core/documents';
4
4
  import { LanguageServiceContainer, LanguageServiceDocumentContext } from './language-service';
5
5
  import type { DocumentSnapshot } from './snapshots/DocumentSnapshot';
6
+ import { SnapshotManager } from './snapshots/SnapshotManager';
6
7
  export declare class LanguageServiceManager {
7
8
  private readonly docManager;
8
9
  private readonly workspaceUris;
@@ -31,11 +32,15 @@ export declare class LanguageServiceManager {
31
32
  /**
32
33
  * Updates file in all ts services where it exists
33
34
  */
34
- updateExistingNonAstroFile(path: string, changes?: TextDocumentContentChangeEvent[]): Promise<void>;
35
+ updateExistingNonAstroFile(path: string, changes?: TextDocumentContentChangeEvent[], text?: string): Promise<void>;
35
36
  getLSAndTSDoc(document: AstroDocument): Promise<{
36
37
  tsDoc: DocumentSnapshot;
37
38
  lang: ts.LanguageService;
38
39
  }>;
39
40
  getLSForPath(path: string): Promise<import("typescript/lib/tsserverlibrary").LanguageService>;
40
41
  getTypeScriptLanguageService(filePath: string): Promise<LanguageServiceContainer>;
42
+ /**
43
+ * @internal Public for tests only
44
+ */
45
+ getSnapshotManager(filePath: string): Promise<SnapshotManager>;
41
46
  }
@@ -63,7 +63,7 @@ class LanguageServiceManager {
63
63
  /**
64
64
  * Updates file in all ts services where it exists
65
65
  */
66
- async updateExistingNonAstroFile(path, changes) {
66
+ async updateExistingNonAstroFile(path, changes, text) {
67
67
  path = (0, utils_1.normalizePath)(path);
68
68
  // Only update once because all snapshots are shared between
69
69
  // services. Since we don't have a current version of TS/JS
@@ -72,7 +72,7 @@ class LanguageServiceManager {
72
72
  await (0, language_service_1.forAllLanguageServices)((service) => {
73
73
  if (service.hasFile(path) && !didUpdate) {
74
74
  didUpdate = true;
75
- service.updateNonAstroFile(path, changes);
75
+ service.updateNonAstroFile(path, changes, text);
76
76
  }
77
77
  });
78
78
  }
@@ -87,5 +87,11 @@ class LanguageServiceManager {
87
87
  async getTypeScriptLanguageService(filePath) {
88
88
  return (0, language_service_1.getLanguageService)(filePath, this.workspaceUris, this.docContext);
89
89
  }
90
+ /**
91
+ * @internal Public for tests only
92
+ */
93
+ async getSnapshotManager(filePath) {
94
+ return (await this.getTypeScriptLanguageService(filePath)).snapshotManager;
95
+ }
90
96
  }
91
97
  exports.LanguageServiceManager = LanguageServiceManager;
@@ -1,4 +1,4 @@
1
- import { CancellationToken, CodeAction, CodeActionContext, CompletionContext, DefinitionLink, Diagnostic, FoldingRange, Hover, InlayHint, Location, Position, Range, SemanticTokens, SignatureHelp, SignatureHelpContext, SymbolInformation, TextDocumentContentChangeEvent, WorkspaceEdit } from 'vscode-languageserver';
1
+ import { CancellationToken, CodeAction, CodeActionContext, CompletionContext, DefinitionLink, Diagnostic, FoldingRange, Hover, InlayHint, Location, Position, Range, ReferenceContext, SemanticTokens, SignatureHelp, SignatureHelpContext, SymbolInformation, TextDocumentContentChangeEvent, WorkspaceEdit } from 'vscode-languageserver';
2
2
  import type { ConfigManager } from '../../core/config';
3
3
  import type { AstroDocument } from '../../core/documents';
4
4
  import type { AppCompletionItem, AppCompletionList, OnWatchFileChangesParam, Plugin } from '../interfaces';
@@ -12,8 +12,11 @@ export declare class TypeScriptPlugin implements Plugin {
12
12
  private readonly codeActionsProvider;
13
13
  private readonly completionProvider;
14
14
  private readonly hoverProvider;
15
+ private readonly fileReferencesProvider;
15
16
  private readonly definitionsProvider;
16
17
  private readonly typeDefinitionsProvider;
18
+ private readonly implementationsProvider;
19
+ private readonly referencesProvider;
17
20
  private readonly signatureHelpProvider;
18
21
  private readonly diagnosticsProvider;
19
22
  private readonly documentSymbolsProvider;
@@ -31,12 +34,19 @@ export declare class TypeScriptPlugin implements Plugin {
31
34
  getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext, cancellationToken?: CancellationToken): Promise<AppCompletionList<CompletionItemData> | null>;
32
35
  resolveCompletion(document: AstroDocument, completionItem: AppCompletionItem<CompletionItemData>, cancellationToken?: CancellationToken): Promise<AppCompletionItem<CompletionItemData>>;
33
36
  getInlayHints(document: AstroDocument, range: Range): Promise<InlayHint[]>;
37
+ fileReferences(document: AstroDocument): Promise<Location[] | null>;
34
38
  getDefinitions(document: AstroDocument, position: Position): Promise<DefinitionLink[]>;
35
- getTypeDefinition(document: AstroDocument, position: Position): Promise<Location[] | null>;
39
+ getTypeDefinitions(document: AstroDocument, position: Position): Promise<Location[] | null>;
40
+ getImplementation(document: AstroDocument, position: Position): Promise<Location[] | null>;
41
+ findReferences(document: AstroDocument, position: Position, context: ReferenceContext): Promise<Location[] | null>;
36
42
  getDiagnostics(document: AstroDocument, cancellationToken?: CancellationToken): Promise<Diagnostic[]>;
37
43
  onWatchFileChanges(onWatchFileChangesParas: OnWatchFileChangesParam[]): Promise<void>;
38
- updateNonAstroFile(fileName: string, changes: TextDocumentContentChangeEvent[]): Promise<void>;
44
+ updateNonAstroFile(fileName: string, changes: TextDocumentContentChangeEvent[], text?: string): Promise<void>;
39
45
  getSignatureHelp(document: AstroDocument, position: Position, context: SignatureHelpContext | undefined, cancellationToken?: CancellationToken): Promise<SignatureHelp | null>;
40
46
  getTSXForDocument(document: AstroDocument): Astro2TSXResult;
47
+ /**
48
+ * @internal Public for tests only
49
+ */
50
+ getSnapshotManager(fileName: string): Promise<import("./snapshots/SnapshotManager").SnapshotManager>;
41
51
  private featureEnabled;
42
52
  }
@@ -11,9 +11,12 @@ const CompletionsProvider_1 = require("./features/CompletionsProvider");
11
11
  const DefinitionsProvider_1 = require("./features/DefinitionsProvider");
12
12
  const DiagnosticsProvider_1 = require("./features/DiagnosticsProvider");
13
13
  const DocumentSymbolsProvider_1 = require("./features/DocumentSymbolsProvider");
14
+ const FileReferencesProvider_1 = require("./features/FileReferencesProvider");
14
15
  const FoldingRangesProvider_1 = require("./features/FoldingRangesProvider");
15
16
  const HoverProvider_1 = require("./features/HoverProvider");
17
+ const ImplementationsProvider_1 = require("./features/ImplementationsProvider");
16
18
  const InlayHintsProvider_1 = require("./features/InlayHintsProvider");
19
+ const ReferencesProvider_1 = require("./features/ReferencesProvider");
17
20
  const SemanticTokenProvider_1 = require("./features/SemanticTokenProvider");
18
21
  const SignatureHelpProvider_1 = require("./features/SignatureHelpProvider");
19
22
  const TypeDefinitionsProvider_1 = require("./features/TypeDefinitionsProvider");
@@ -28,8 +31,11 @@ class TypeScriptPlugin {
28
31
  this.codeActionsProvider = new CodeActionsProvider_1.CodeActionsProviderImpl(this.languageServiceManager, this.configManager);
29
32
  this.completionProvider = new CompletionsProvider_1.CompletionsProviderImpl(this.languageServiceManager, this.configManager);
30
33
  this.hoverProvider = new HoverProvider_1.HoverProviderImpl(this.languageServiceManager);
34
+ this.fileReferencesProvider = new FileReferencesProvider_1.FileReferencesProviderImpl(this.languageServiceManager);
31
35
  this.definitionsProvider = new DefinitionsProvider_1.DefinitionsProviderImpl(this.languageServiceManager);
32
36
  this.typeDefinitionsProvider = new TypeDefinitionsProvider_1.TypeDefinitionsProviderImpl(this.languageServiceManager);
37
+ this.implementationsProvider = new ImplementationsProvider_1.ImplementationsProviderImpl(this.languageServiceManager);
38
+ this.referencesProvider = new ReferencesProvider_1.FindReferencesProviderImpl(this.languageServiceManager);
33
39
  this.signatureHelpProvider = new SignatureHelpProvider_1.SignatureHelpProviderImpl(this.languageServiceManager);
34
40
  this.diagnosticsProvider = new DiagnosticsProvider_1.DiagnosticsProviderImpl(this.languageServiceManager);
35
41
  this.documentSymbolsProvider = new DocumentSymbolsProvider_1.DocumentSymbolsProviderImpl(this.languageServiceManager);
@@ -101,12 +107,21 @@ class TypeScriptPlugin {
101
107
  async getInlayHints(document, range) {
102
108
  return this.inlayHintsProvider.getInlayHints(document, range);
103
109
  }
110
+ async fileReferences(document) {
111
+ return this.fileReferencesProvider.fileReferences(document);
112
+ }
104
113
  async getDefinitions(document, position) {
105
114
  return this.definitionsProvider.getDefinitions(document, position);
106
115
  }
107
- async getTypeDefinition(document, position) {
116
+ async getTypeDefinitions(document, position) {
108
117
  return this.typeDefinitionsProvider.getTypeDefinitions(document, position);
109
118
  }
119
+ async getImplementation(document, position) {
120
+ return this.implementationsProvider.getImplementation(document, position);
121
+ }
122
+ async findReferences(document, position, context) {
123
+ return this.referencesProvider.findReferences(document, position, context);
124
+ }
110
125
  async getDiagnostics(document, cancellationToken) {
111
126
  if (!(await this.featureEnabled(document, 'diagnostics'))) {
112
127
  return [];
@@ -117,7 +132,7 @@ class TypeScriptPlugin {
117
132
  let doneUpdateProjectFiles = false;
118
133
  for (const { fileName, changeType } of onWatchFileChangesParas) {
119
134
  const scriptKind = (0, utils_2.getScriptKindFromFileName)(fileName, this.ts);
120
- if (scriptKind === this.ts.ScriptKind.Unknown) {
135
+ if (scriptKind === this.ts.ScriptKind.Unknown && !(0, utils_2.isFrameworkFilePath)(fileName) && !(0, utils_2.isAstroFilePath)(fileName)) {
121
136
  continue;
122
137
  }
123
138
  if (changeType === vscode_languageserver_1.FileChangeType.Created && !doneUpdateProjectFiles) {
@@ -127,13 +142,14 @@ class TypeScriptPlugin {
127
142
  else if (changeType === vscode_languageserver_1.FileChangeType.Deleted) {
128
143
  await this.languageServiceManager.deleteSnapshot(fileName);
129
144
  }
130
- else {
145
+ else if (!(0, utils_2.isAstroFilePath)(fileName)) {
146
+ // Content updates for Astro files are handled through the documentManager and the 'documentChange' event
131
147
  await this.languageServiceManager.updateExistingNonAstroFile(fileName);
132
148
  }
133
149
  }
134
150
  }
135
- async updateNonAstroFile(fileName, changes) {
136
- await this.languageServiceManager.updateExistingNonAstroFile(fileName, changes);
151
+ async updateNonAstroFile(fileName, changes, text) {
152
+ await this.languageServiceManager.updateExistingNonAstroFile(fileName, changes, text);
137
153
  }
138
154
  async getSignatureHelp(document, position, context, cancellationToken) {
139
155
  return this.signatureHelpProvider.getSignatureHelp(document, position, context, cancellationToken);
@@ -141,6 +157,12 @@ class TypeScriptPlugin {
141
157
  getTSXForDocument(document) {
142
158
  return (0, astro2tsx_1.default)(document.getText(), (0, utils_1.classNameFromFilename)(document.getURL()));
143
159
  }
160
+ /**
161
+ * @internal Public for tests only
162
+ */
163
+ getSnapshotManager(fileName) {
164
+ return this.languageServiceManager.getSnapshotManager(fileName);
165
+ }
144
166
  async featureEnabled(document, feature) {
145
167
  return ((await this.configManager.isEnabled(document, 'typescript')) &&
146
168
  (await this.configManager.isEnabled(document, 'typescript', feature)));
@@ -20,7 +20,7 @@ function createAstroSys(getSnapshot, ts) {
20
20
  return snapshot.getText(0, snapshot.getLength());
21
21
  },
22
22
  readDirectory(path, extensions, exclude, include, depth) {
23
- const extensionsWithAstro = (extensions ?? []).concat(...['.astro', '.svelte', '.vue']);
23
+ const extensionsWithAstro = (extensions ?? []).concat(...['.astro', '.svelte', '.vue', '.md', '.mdx', '.html']);
24
24
  const result = ts.sys.readDirectory(path, extensionsWithAstro, exclude, include, depth);
25
25
  return result;
26
26
  },
@@ -166,7 +166,8 @@ class CodeActionsProviderImpl {
166
166
  // Since our last line is a (virtual) export, organize imports will try to rewrite it, so let's only take
167
167
  // changes that actually happens inside the script tag
168
168
  .filter((change) => {
169
- return scriptTagSnapshot.isInGenerated(document.positionAt(change.span.start));
169
+ return (scriptTagSnapshot.isInGenerated(document.positionAt(change.span.start)) &&
170
+ !change.newText.includes('export { }'));
170
171
  });
171
172
  return edit;
172
173
  });
@@ -0,0 +1,9 @@
1
+ import { Location } from 'vscode-languageserver';
2
+ import { AstroDocument } from '../../../core/documents';
3
+ import { FileReferencesProvider } from '../../interfaces';
4
+ import { LanguageServiceManager } from '../LanguageServiceManager';
5
+ export declare class FileReferencesProviderImpl implements FileReferencesProvider {
6
+ private languageServiceManager;
7
+ constructor(languageServiceManager: LanguageServiceManager);
8
+ fileReferences(document: AstroDocument): Promise<Location[] | null>;
9
+ }
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FileReferencesProviderImpl = void 0;
4
+ const vscode_languageserver_1 = require("vscode-languageserver");
5
+ const utils_1 = require("../../../utils");
6
+ const utils_2 = require("../utils");
7
+ const utils_3 = require("./utils");
8
+ class FileReferencesProviderImpl {
9
+ constructor(languageServiceManager) {
10
+ this.languageServiceManager = languageServiceManager;
11
+ }
12
+ async fileReferences(document) {
13
+ const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
14
+ const mainFragment = await tsDoc.createFragment();
15
+ const references = lang.getFileReferences(tsDoc.filePath);
16
+ if (!references) {
17
+ return null;
18
+ }
19
+ const docs = new utils_3.SnapshotFragmentMap(this.languageServiceManager);
20
+ docs.set(tsDoc.filePath, { fragment: mainFragment, snapshot: tsDoc });
21
+ const locations = await Promise.all(references.map(async (ref) => {
22
+ const defDoc = await docs.retrieveFragment(ref.fileName);
23
+ return vscode_languageserver_1.Location.create((0, utils_1.pathToUrl)(ref.fileName), (0, utils_2.convertToLocationRange)(defDoc, ref.textSpan));
24
+ }));
25
+ return locations;
26
+ }
27
+ }
28
+ exports.FileReferencesProviderImpl = FileReferencesProviderImpl;
@@ -0,0 +1,9 @@
1
+ import { Location, Position } from 'vscode-languageserver-types';
2
+ import { AstroDocument } from '../../../core/documents';
3
+ import { ImplementationProvider } from '../../interfaces';
4
+ import { LanguageServiceManager } from '../LanguageServiceManager';
5
+ export declare class ImplementationsProviderImpl implements ImplementationProvider {
6
+ private languageServiceManager;
7
+ constructor(languageServiceManager: LanguageServiceManager);
8
+ getImplementation(document: AstroDocument, position: Position): Promise<Location[] | null>;
9
+ }
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ImplementationsProviderImpl = void 0;
4
+ const vscode_languageserver_types_1 = require("vscode-languageserver-types");
5
+ const documents_1 = require("../../../core/documents");
6
+ const utils_1 = require("../../../utils");
7
+ const utils_2 = require("../utils");
8
+ const utils_3 = require("./utils");
9
+ class ImplementationsProviderImpl {
10
+ constructor(languageServiceManager) {
11
+ this.languageServiceManager = languageServiceManager;
12
+ }
13
+ async getImplementation(document, position) {
14
+ const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
15
+ const mainFragment = await tsDoc.createFragment();
16
+ const offset = mainFragment.offsetAt(mainFragment.getGeneratedPosition(position));
17
+ const node = document.html.findNodeAt(offset);
18
+ let implementations;
19
+ if (node.tag === 'script') {
20
+ const { snapshot: scriptTagSnapshot, filePath: scriptFilePath, offset: scriptOffset, } = (0, utils_2.getScriptTagSnapshot)(tsDoc, document, node, position);
21
+ implementations = lang.getImplementationAtPosition(scriptFilePath, scriptOffset);
22
+ if (implementations) {
23
+ implementations = implementations.map((impl) => {
24
+ const isInSameFile = impl.fileName === scriptFilePath;
25
+ impl.fileName = isInSameFile ? tsDoc.filePath : impl.fileName;
26
+ if (isInSameFile) {
27
+ impl.textSpan.start = mainFragment.offsetAt(scriptTagSnapshot.getOriginalPosition(scriptTagSnapshot.positionAt(impl.textSpan.start)));
28
+ }
29
+ return impl;
30
+ });
31
+ }
32
+ }
33
+ else {
34
+ implementations = lang.getImplementationAtPosition(tsDoc.filePath, offset);
35
+ }
36
+ const docs = new utils_3.SnapshotFragmentMap(this.languageServiceManager);
37
+ docs.set(tsDoc.filePath, { fragment: mainFragment, snapshot: tsDoc });
38
+ if (!implementations) {
39
+ return null;
40
+ }
41
+ const result = await Promise.all(implementations.map(async (implementation) => {
42
+ const { fragment } = await docs.retrieve(implementation.fileName);
43
+ const range = (0, documents_1.mapRangeToOriginal)(fragment, (0, utils_2.convertRange)(fragment, implementation.textSpan));
44
+ if (range.start.line >= 0 && range.end.line >= 0) {
45
+ return vscode_languageserver_types_1.Location.create((0, utils_1.pathToUrl)(implementation.fileName), range);
46
+ }
47
+ }));
48
+ return result.filter(utils_1.isNotNullOrUndefined);
49
+ }
50
+ }
51
+ exports.ImplementationsProviderImpl = ImplementationsProviderImpl;
@@ -0,0 +1,9 @@
1
+ import { Location, Position, ReferenceContext } from 'vscode-languageserver-types';
2
+ import { AstroDocument } from '../../../core/documents';
3
+ import type { FindReferencesProvider } from '../../interfaces';
4
+ import type { LanguageServiceManager } from '../LanguageServiceManager';
5
+ export declare class FindReferencesProviderImpl implements FindReferencesProvider {
6
+ private languageServiceManager;
7
+ constructor(languageServiceManager: LanguageServiceManager);
8
+ findReferences(document: AstroDocument, position: Position, context: ReferenceContext): Promise<Location[] | null>;
9
+ }
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FindReferencesProviderImpl = void 0;
4
+ const vscode_languageserver_types_1 = require("vscode-languageserver-types");
5
+ const documents_1 = require("../../../core/documents");
6
+ const utils_1 = require("../../../utils");
7
+ const utils_2 = require("../utils");
8
+ const utils_3 = require("./utils");
9
+ class FindReferencesProviderImpl {
10
+ constructor(languageServiceManager) {
11
+ this.languageServiceManager = languageServiceManager;
12
+ }
13
+ async findReferences(document, position, context) {
14
+ const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
15
+ const mainFragment = await tsDoc.createFragment();
16
+ const offset = mainFragment.offsetAt(mainFragment.getGeneratedPosition(position));
17
+ const node = document.html.findNodeAt(offset);
18
+ let references;
19
+ if (node.tag === 'script') {
20
+ const { snapshot: scriptTagSnapshot, filePath: scriptFilePath, offset: scriptOffset, } = (0, utils_2.getScriptTagSnapshot)(tsDoc, document, node, position);
21
+ references = lang.getReferencesAtPosition(scriptFilePath, scriptOffset);
22
+ if (references) {
23
+ references = references.map((ref) => {
24
+ const isInSameFile = ref.fileName === scriptFilePath;
25
+ ref.fileName = isInSameFile ? tsDoc.filePath : ref.fileName;
26
+ if (isInSameFile) {
27
+ ref.textSpan.start = mainFragment.offsetAt(scriptTagSnapshot.getOriginalPosition(scriptTagSnapshot.positionAt(ref.textSpan.start)));
28
+ }
29
+ return ref;
30
+ });
31
+ }
32
+ }
33
+ else {
34
+ references = lang.getReferencesAtPosition(tsDoc.filePath, offset);
35
+ }
36
+ if (!references) {
37
+ return null;
38
+ }
39
+ const docs = new utils_3.SnapshotFragmentMap(this.languageServiceManager);
40
+ docs.set(tsDoc.filePath, { fragment: mainFragment, snapshot: tsDoc });
41
+ const result = await Promise.all(references.map(async (reference) => {
42
+ if (!context.includeDeclaration) {
43
+ return null;
44
+ }
45
+ const { fragment } = await docs.retrieve(reference.fileName);
46
+ const range = (0, documents_1.mapRangeToOriginal)(fragment, (0, utils_2.convertRange)(fragment, reference.textSpan));
47
+ if (range.start.line >= 0 && range.end.line >= 0) {
48
+ return vscode_languageserver_types_1.Location.create((0, utils_1.pathToUrl)(reference.fileName), range);
49
+ }
50
+ }));
51
+ return result.filter(utils_1.isNotNullOrUndefined);
52
+ }
53
+ }
54
+ exports.FindReferencesProviderImpl = FindReferencesProviderImpl;
@@ -1,8 +1,8 @@
1
1
  import { Location, Position } from 'vscode-languageserver-protocol';
2
2
  import { AstroDocument } from '../../../core/documents';
3
- import type { TypeDefinitionProvider } from '../../interfaces';
3
+ import type { TypeDefinitionsProvider } from '../../interfaces';
4
4
  import type { LanguageServiceManager } from '../LanguageServiceManager';
5
- export declare class TypeDefinitionsProviderImpl implements TypeDefinitionProvider {
5
+ export declare class TypeDefinitionsProviderImpl implements TypeDefinitionsProvider {
6
6
  private languageServiceManager;
7
7
  constructor(languageServiceManager: LanguageServiceManager);
8
8
  getTypeDefinitions(document: AstroDocument, position: Position): Promise<Location[]>;
@@ -14,7 +14,7 @@ export interface LanguageServiceContainer {
14
14
  updateSnapshot(documentOrFilePath: AstroDocument | string, ts: typeof import('typescript/lib/tsserverlibrary')): DocumentSnapshot;
15
15
  deleteSnapshot(filePath: string): void;
16
16
  updateProjectFiles(): void;
17
- updateNonAstroFile(fileName: string, changes?: TextDocumentContentChangeEvent[]): void;
17
+ updateNonAstroFile(fileName: string, changes?: TextDocumentContentChangeEvent[], text?: string): void;
18
18
  /**
19
19
  * Checks if a file is present in the project.
20
20
  * Unlike `fileBelongsToProject`, this doesn't run a file search on disk.
@@ -214,11 +214,11 @@ async function createLanguageService(tsconfigPath, docContext, workspaceUris) {
214
214
  filePath = (0, utils_1.normalizePath)(filePath);
215
215
  return hasFile(filePath) || getParsedTSConfig().fileNames.includes(filePath);
216
216
  }
217
- function updateNonAstroFile(fileName, changes) {
217
+ function updateNonAstroFile(fileName, changes, text) {
218
218
  if (!snapshotManager.has(fileName)) {
219
219
  astroModuleLoader.deleteUnresolvedResolutionsFromCache(fileName);
220
220
  }
221
- snapshotManager.updateNonAstroFile(fileName, changes);
221
+ snapshotManager.updateNonAstroFile(fileName, changes, text);
222
222
  }
223
223
  function createScriptTagsSnapshots(fileName, document) {
224
224
  return document.scriptTags.map((scriptTag, index) => {
@@ -229,7 +229,7 @@ async function createLanguageService(tsconfigPath, docContext, workspaceUris) {
229
229
  });
230
230
  }
231
231
  function createDocumentSymbolSnapshot(doc) {
232
- return new DocumentSnapshot_1.TypeScriptDocumentSnapshot(doc.version, doc.filePath, doc.parent.getText(), docContext.ts.ScriptKind.Unknown);
232
+ return new DocumentSnapshot_1.TypeScriptDocumentSnapshot(doc.version, doc.filePath, doc.parent.getText(), docContext.ts.ScriptKind.Unknown, false);
233
233
  }
234
234
  function getParsedTSConfig() {
235
235
  let configJson = (tsconfigPath && docContext.ts.readConfigFile(tsconfigPath, docContext.ts.sys.readFile).config) || {};
@@ -1,6 +1,5 @@
1
1
  import type { Position, TextDocumentContentChangeEvent } from 'vscode-languageserver';
2
2
  import { AstroDocument, DocumentMapper, FragmentMapper, IdentityMapper, TagInformation } from '../../../core/documents';
3
- import type { FrameworkExt } from '../utils';
4
3
  export interface DocumentSnapshot extends ts.IScriptSnapshot {
5
4
  version: number;
6
5
  filePath: string;
@@ -92,10 +91,10 @@ export declare class TypeScriptDocumentSnapshot extends IdentityMapper implement
92
91
  version: number;
93
92
  readonly filePath: string;
94
93
  private text;
95
- readonly framework?: FrameworkExt | undefined;
94
+ readonly supportPartialUpdate: boolean;
96
95
  scriptKind: ts.ScriptKind;
97
96
  private lineOffsets?;
98
- constructor(version: number, filePath: string, text: string, scriptKind: ts.ScriptKind, framework?: FrameworkExt | undefined);
97
+ constructor(version: number, filePath: string, text: string, scriptKind: ts.ScriptKind, supportPartialUpdate: boolean);
99
98
  getText(start: number, end: number): string;
100
99
  getLength(): number;
101
100
  getFullText(): string;
@@ -119,12 +119,12 @@ exports.ScriptTagDocumentSnapshot = ScriptTagDocumentSnapshot;
119
119
  * It's both used for .js(x)/.ts(x) files and .svelte/.vue files
120
120
  */
121
121
  class TypeScriptDocumentSnapshot extends documents_1.IdentityMapper {
122
- constructor(version, filePath, text, scriptKind, framework) {
122
+ constructor(version, filePath, text, scriptKind, supportPartialUpdate) {
123
123
  super((0, utils_1.pathToUrl)(filePath));
124
124
  this.version = version;
125
125
  this.filePath = filePath;
126
126
  this.text = text;
127
- this.framework = framework;
127
+ this.supportPartialUpdate = supportPartialUpdate;
128
128
  this.scriptKind = scriptKind;
129
129
  }
130
130
  getText(start, end) {
@@ -13,7 +13,7 @@ export declare class GlobalSnapshotManager {
13
13
  get(fileName: string): DocumentSnapshot | undefined;
14
14
  set(fileName: string, document: DocumentSnapshot): void;
15
15
  delete(fileName: string): void;
16
- updateNonAstroFile(fileName: string, changes?: TextDocumentContentChangeEvent[]): TypeScriptDocumentSnapshot | undefined;
16
+ updateNonAstroFile(fileName: string, changes?: TextDocumentContentChangeEvent[], newText?: string): TypeScriptDocumentSnapshot | undefined;
17
17
  onChange(listener: (fileName: string, newDocument: DocumentSnapshot | undefined) => void): void;
18
18
  }
19
19
  export interface TsFilesSpec {
@@ -31,10 +31,9 @@ export declare class SnapshotManager {
31
31
  private ts;
32
32
  private documents;
33
33
  private lastLogged;
34
- private readonly watchExtensions;
35
34
  constructor(globalSnapshotsManager: GlobalSnapshotManager, projectFiles: string[], fileSpec: TsFilesSpec, workspaceRoot: string, ts: typeof import('typescript/lib/tsserverlibrary'));
36
35
  updateProjectFiles(): void;
37
- updateNonAstroFile(fileName: string, changes?: TextDocumentContentChangeEvent[]): void;
36
+ updateNonAstroFile(fileName: string, changes?: TextDocumentContentChangeEvent[], text?: string): void;
38
37
  has(fileName: string): boolean;
39
38
  set(fileName: string, snapshot: DocumentSnapshot): void;
40
39
  get(fileName: string): DocumentSnapshot | undefined;
@@ -26,7 +26,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.SnapshotManager = exports.GlobalSnapshotManager = void 0;
27
27
  const events_1 = require("events");
28
28
  const utils_1 = require("../../../utils");
29
- const utils_2 = require("../utils");
30
29
  const DocumentSnapshot_1 = require("./DocumentSnapshot");
31
30
  const DocumentSnapshotUtils = __importStar(require("./utils"));
32
31
  /**
@@ -58,20 +57,17 @@ class GlobalSnapshotManager {
58
57
  this.documents.delete(fileName);
59
58
  this.emitter.emit('change', fileName, undefined);
60
59
  }
61
- updateNonAstroFile(fileName, changes) {
60
+ updateNonAstroFile(fileName, changes, newText) {
62
61
  fileName = (0, utils_1.normalizePath)(fileName);
63
62
  const previousSnapshot = this.get(fileName);
64
- if (changes) {
65
- // We don't support incremental changes for Framework files, as they need to be rebuilt completely on every change
66
- if (!(previousSnapshot instanceof DocumentSnapshot_1.TypeScriptDocumentSnapshot) || previousSnapshot.framework) {
67
- return;
68
- }
63
+ const canBePartiallyUpdated = changes && previousSnapshot instanceof DocumentSnapshot_1.TypeScriptDocumentSnapshot && previousSnapshot.supportPartialUpdate;
64
+ if (canBePartiallyUpdated) {
69
65
  previousSnapshot.update(changes);
70
66
  this.emitter.emit('change', fileName, previousSnapshot);
71
67
  return previousSnapshot;
72
68
  }
73
69
  else {
74
- const newSnapshot = DocumentSnapshotUtils.createFromNonAstroFilePath(fileName, this.ts);
70
+ const newSnapshot = DocumentSnapshotUtils.createFromNonAstroFilePath(fileName, this.ts, newText);
75
71
  if (previousSnapshot) {
76
72
  newSnapshot.version = previousSnapshot.version + 1;
77
73
  }
@@ -81,6 +77,7 @@ class GlobalSnapshotManager {
81
77
  newSnapshot.version += 1;
82
78
  }
83
79
  this.set(fileName, newSnapshot);
80
+ this.emitter.emit('change', fileName, newSnapshot);
84
81
  return newSnapshot;
85
82
  }
86
83
  }
@@ -101,14 +98,6 @@ class SnapshotManager {
101
98
  this.ts = ts;
102
99
  this.documents = new Map();
103
100
  this.lastLogged = new Date(new Date().getTime() - 60001);
104
- this.watchExtensions = [
105
- this.ts.Extension.Dts,
106
- this.ts.Extension.Js,
107
- this.ts.Extension.Jsx,
108
- this.ts.Extension.Ts,
109
- this.ts.Extension.Tsx,
110
- this.ts.Extension.Json,
111
- ];
112
101
  this.globalSnapshotsManager.onChange((fileName, document) => {
113
102
  // Only delete/update snapshots, don't add new ones,
114
103
  // as they could be from another TS service and this
@@ -131,12 +120,12 @@ class SnapshotManager {
131
120
  return;
132
121
  }
133
122
  const projectFiles = this.ts.sys
134
- .readDirectory(this.workspaceRoot, this.watchExtensions, exclude, include)
123
+ .readDirectory(this.workspaceRoot, [...Object.values(this.ts.Extension), '.astro', '.svelte', '.vue'], exclude, include)
135
124
  .map(utils_1.normalizePath);
136
125
  this.projectFiles = Array.from(new Set([...this.projectFiles, ...projectFiles]));
137
126
  }
138
- updateNonAstroFile(fileName, changes) {
139
- const snapshot = this.globalSnapshotsManager.updateNonAstroFile(fileName, changes);
127
+ updateNonAstroFile(fileName, changes, text) {
128
+ const snapshot = this.globalSnapshotsManager.updateNonAstroFile(fileName, changes, text);
140
129
  // This isn't duplicated logic to the listener, because this could
141
130
  // be a new snapshot which the listener wouldn't add.
142
131
  if (snapshot) {
@@ -181,8 +170,7 @@ class SnapshotManager {
181
170
  if (date.getTime() - this.lastLogged.getTime() > 60000) {
182
171
  this.lastLogged = date;
183
172
  const projectFiles = this.getProjectFileNames();
184
- let allFiles = Array.from(new Set([...projectFiles, ...this.getFileNames()]));
185
- allFiles = allFiles.map((file) => (0, utils_2.ensureRealFilePath)(file));
173
+ const allFiles = Array.from(new Set([...projectFiles, ...this.getFileNames()]));
186
174
  // eslint-disable-next-line no-console
187
175
  console.log('SnapshotManager File Statistics:\n' +
188
176
  `Project files: ${projectFiles.length}\n` +
@@ -12,18 +12,18 @@ export declare function createFromFilePath(filePath: string, createDocument: (fi
12
12
  * Return a Framework or a TS snapshot from a file path, depending on the file contents
13
13
  * Unlike createFromFilePath, this does not support creating an Astro snapshot
14
14
  */
15
- export declare function createFromNonAstroFilePath(filePath: string, ts: typeof import('typescript/lib/tsserverlibrary')): TypeScriptDocumentSnapshot;
15
+ export declare function createFromNonAstroFilePath(filePath: string, ts: typeof import('typescript/lib/tsserverlibrary'), forceText?: string): TypeScriptDocumentSnapshot;
16
16
  /**
17
17
  * Returns a ts/js snapshot from a file path.
18
18
  * @param filePath path to the js/ts file
19
19
  * @param options options that apply in case it's a svelte file
20
20
  */
21
- export declare function createFromTSFilePath(filePath: string, ts: typeof import('typescript/lib/tsserverlibrary')): TypeScriptDocumentSnapshot;
21
+ export declare function createFromTSFilePath(filePath: string, ts: typeof import('typescript/lib/tsserverlibrary'), forceText?: string): TypeScriptDocumentSnapshot;
22
22
  /**
23
23
  * Returns an Astro snapshot from a file path.
24
24
  * @param filePath path to the Astro file
25
25
  * @param createDocument function that is used to create a document
26
26
  */
27
27
  export declare function createFromAstroFilePath(filePath: string, createDocument: (filePath: string, text: string) => AstroDocument, ts: typeof import('typescript/lib/tsserverlibrary')): AstroSnapshot;
28
- export declare function createFromFrameworkFilePath(filePath: string, framework: FrameworkExt, ts: typeof import('typescript/lib/tsserverlibrary')): TypeScriptDocumentSnapshot;
28
+ export declare function createFromFrameworkFilePath(filePath: string, framework: FrameworkExt, ts: typeof import('typescript/lib/tsserverlibrary'), forceText?: string): TypeScriptDocumentSnapshot;
29
29
  export declare function classNameFromFilename(filename: string): string;
@@ -38,13 +38,13 @@ exports.createFromFilePath = createFromFilePath;
38
38
  * Return a Framework or a TS snapshot from a file path, depending on the file contents
39
39
  * Unlike createFromFilePath, this does not support creating an Astro snapshot
40
40
  */
41
- function createFromNonAstroFilePath(filePath, ts) {
41
+ function createFromNonAstroFilePath(filePath, ts, forceText) {
42
42
  if ((0, utils_2.isFrameworkFilePath)(filePath)) {
43
43
  const framework = (0, utils_2.getFrameworkFromFilePath)(filePath);
44
- return createFromFrameworkFilePath(filePath, framework, ts);
44
+ return createFromFrameworkFilePath(filePath, framework, ts, forceText);
45
45
  }
46
46
  else {
47
- return createFromTSFilePath(filePath, ts);
47
+ return createFromTSFilePath(filePath, ts, forceText);
48
48
  }
49
49
  }
50
50
  exports.createFromNonAstroFilePath = createFromNonAstroFilePath;
@@ -53,9 +53,9 @@ exports.createFromNonAstroFilePath = createFromNonAstroFilePath;
53
53
  * @param filePath path to the js/ts file
54
54
  * @param options options that apply in case it's a svelte file
55
55
  */
56
- function createFromTSFilePath(filePath, ts) {
57
- const originalText = ts.sys.readFile(filePath) ?? '';
58
- return new DocumentSnapshot_1.TypeScriptDocumentSnapshot(0, filePath, originalText, (0, utils_2.getScriptKindFromFileName)(filePath, ts));
56
+ function createFromTSFilePath(filePath, ts, forceText) {
57
+ const originalText = forceText ?? ts.sys.readFile(filePath) ?? '';
58
+ return new DocumentSnapshot_1.TypeScriptDocumentSnapshot(0, filePath, originalText, (0, utils_2.getScriptKindFromFileName)(filePath, ts), true);
59
59
  }
60
60
  exports.createFromTSFilePath = createFromTSFilePath;
61
61
  /**
@@ -68,9 +68,9 @@ function createFromAstroFilePath(filePath, createDocument, ts) {
68
68
  return createFromDocument(createDocument(filePath, originalText), ts);
69
69
  }
70
70
  exports.createFromAstroFilePath = createFromAstroFilePath;
71
- function createFromFrameworkFilePath(filePath, framework, ts) {
71
+ function createFromFrameworkFilePath(filePath, framework, ts, forceText) {
72
72
  const className = classNameFromFilename(filePath);
73
- const originalText = ts.sys.readFile(filePath) ?? '';
73
+ const originalText = forceText ?? ts.sys.readFile(filePath) ?? '';
74
74
  let code = '';
75
75
  if (framework === 'svelte') {
76
76
  const svelteIntegration = (0, importPackage_1.importSvelteIntegration)(filePath);
@@ -84,7 +84,7 @@ function createFromFrameworkFilePath(filePath, framework, ts) {
84
84
  code = vueIntegration.toTSX(originalText, className);
85
85
  }
86
86
  }
87
- return new DocumentSnapshot_1.TypeScriptDocumentSnapshot(0, filePath, code, ts.ScriptKind.TSX);
87
+ return new DocumentSnapshot_1.TypeScriptDocumentSnapshot(0, filePath, code, ts.ScriptKind.TSX, false);
88
88
  }
89
89
  exports.createFromFrameworkFilePath = createFromFrameworkFilePath;
90
90
  function classNameFromFilename(filename) {
package/dist/server.js CHANGED
@@ -103,6 +103,8 @@ function startLanguageServer(connection, env) {
103
103
  foldingRangeProvider: true,
104
104
  definitionProvider: true,
105
105
  typeDefinitionProvider: true,
106
+ referencesProvider: true,
107
+ implementationProvider: true,
106
108
  renameProvider: true,
107
109
  documentFormattingProvider: true,
108
110
  codeActionProvider: {
@@ -184,20 +186,22 @@ function startLanguageServer(connection, env) {
184
186
  });
185
187
  const diagnosticsManager = new DiagnosticsManager_1.DiagnosticsManager(connection.sendDiagnostics, documentManager, pluginHost.getDiagnostics.bind(pluginHost));
186
188
  const updateAllDiagnostics = (0, utils_2.debounceThrottle)(() => diagnosticsManager.updateAll(), 1000);
187
- connection.onDidChangeWatchedFiles((evt) => {
189
+ connection.onDidChangeWatchedFiles(async (evt) => {
188
190
  const params = evt.changes
189
191
  .map((change) => ({
190
192
  fileName: (0, utils_2.urlToPath)(change.uri),
191
193
  changeType: change.type,
192
194
  }))
193
195
  .filter((change) => !!change.fileName);
194
- pluginHost.onWatchFileChanges(params);
196
+ await pluginHost.onWatchFileChanges(params);
195
197
  updateAllDiagnostics();
196
198
  });
197
199
  // Features
198
200
  connection.onHover((params) => pluginHost.doHover(params.textDocument, params.position));
199
201
  connection.onDefinition((evt) => pluginHost.getDefinitions(evt.textDocument, evt.position));
200
- connection.onTypeDefinition((evt) => pluginHost.getTypeDefinition(evt.textDocument, evt.position));
202
+ connection.onTypeDefinition((evt) => pluginHost.getTypeDefinitions(evt.textDocument, evt.position));
203
+ connection.onReferences((evt) => pluginHost.getReferences(evt.textDocument, evt.position, evt.context));
204
+ connection.onImplementation((evt) => pluginHost.getImplementations(evt.textDocument, evt.position));
201
205
  connection.onFoldingRanges((evt) => pluginHost.getFoldingRanges(evt.textDocument));
202
206
  connection.onCodeAction((evt, cancellationToken) => pluginHost.getCodeActions(evt.textDocument, evt.range, evt.context, cancellationToken));
203
207
  connection.onCompletion(async (evt) => {
@@ -226,21 +230,24 @@ function startLanguageServer(connection, env) {
226
230
  connection.onNotification('$/onDidChangeNonAstroFile', async (e) => {
227
231
  const path = (0, utils_2.urlToPath)(e.uri);
228
232
  if (path) {
229
- pluginHost.updateNonAstroFile(path, e.changes);
233
+ pluginHost.updateNonAstroFile(path, e.changes, e.text);
230
234
  }
231
235
  updateAllDiagnostics();
232
236
  });
237
+ connection.onRequest('$/getFileReferences', async (uri) => {
238
+ return pluginHost.fileReferences({ uri });
239
+ });
233
240
  connection.onRequest('$/getTSXOutput', async (uri) => {
234
241
  const doc = documentManager.get(uri);
235
242
  if (!doc) {
236
243
  return undefined;
237
244
  }
238
- if (doc) {
245
+ if (doc && typescriptPlugin) {
239
246
  const tsxOutput = typescriptPlugin.getTSXForDocument(doc);
240
247
  return tsxOutput.code;
241
248
  }
242
249
  });
243
- documentManager.on('documentChange', (0, utils_2.debounceThrottle)(async (document) => diagnosticsManager.update(document), 1000));
250
+ documentManager.on('documentChange', updateAllDiagnostics);
244
251
  documentManager.on('documentClose', (document) => {
245
252
  diagnosticsManager.removeDiagnostics(document);
246
253
  configManager.removeDocument(document.uri);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrojs/language-server",
3
- "version": "0.26.2",
3
+ "version": "0.28.0",
4
4
  "author": "withastro",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",
@@ -49,6 +49,7 @@
49
49
  "scripts": {
50
50
  "build": "tsc --project tsconfig.build.json",
51
51
  "dev": "astro-scripts dev \"src/**/*.ts\"",
52
- "test": "cross-env TS_NODE_TRANSPILE_ONLY=true mocha --timeout 20000 --require ts-node/register \"test/**/*.ts\" --exclude \"test/**/*.d.ts\""
52
+ "test": "cross-env TS_NODE_TRANSPILE_ONLY=true mocha --timeout 20000 --require ts-node/register \"test/**/*.ts\" --exclude \"test/**/*.d.ts\"",
53
+ "test:match": "pnpm run test -g"
53
54
  }
54
55
  }