🎉 initiate project *astro_rewrite*
This commit is contained in:
parent
ffd4d5e86c
commit
2ba37bfbe3
8658 changed files with 2268794 additions and 2538 deletions
42
node_modules/@astrojs/language-server/dist/plugins/PluginHost.d.ts
generated
vendored
Normal file
42
node_modules/@astrojs/language-server/dist/plugins/PluginHost.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
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';
|
||||
import type { DocumentManager } from '../core/documents/DocumentManager';
|
||||
import type { AppCompletionItem, Plugin } from './interfaces';
|
||||
export interface PluginHostConfig {
|
||||
filterIncompleteCompletions: boolean;
|
||||
definitionLinkSupport: boolean;
|
||||
}
|
||||
export declare class PluginHost {
|
||||
private docManager;
|
||||
private plugins;
|
||||
private pluginHostConfig;
|
||||
constructor(docManager: DocumentManager);
|
||||
initialize(pluginHostConfig: PluginHostConfig): void;
|
||||
registerPlugin(plugin: Plugin): void;
|
||||
getCompletions(textDocument: TextDocumentIdentifier, position: Position, completionContext?: CompletionContext, cancellationToken?: CancellationToken): Promise<CompletionList>;
|
||||
resolveCompletion(textDocument: TextDocumentIdentifier, completionItem: AppCompletionItem): Promise<CompletionItem>;
|
||||
getDiagnostics(textDocument: TextDocumentIdentifier): Promise<Diagnostic[]>;
|
||||
doHover(textDocument: TextDocumentIdentifier, position: Position): Promise<Hover | null>;
|
||||
formatDocument(textDocument: TextDocumentIdentifier, options: FormattingOptions): Promise<TextEdit[]>;
|
||||
getCodeActions(textDocument: TextDocumentIdentifier, range: Range, context: CodeActionContext, cancellationToken?: CancellationToken): Promise<CodeAction[]>;
|
||||
doTagComplete(textDocument: TextDocumentIdentifier, position: Position): Promise<string | null>;
|
||||
getFoldingRanges(textDocument: TextDocumentIdentifier): Promise<FoldingRange[] | null>;
|
||||
getDocumentSymbols(textDocument: TextDocumentIdentifier, cancellationToken?: CancellationToken): Promise<SymbolInformation[]>;
|
||||
getSemanticTokens(textDocument: TextDocumentIdentifier, range?: Range, cancellationToken?: CancellationToken): Promise<SemanticTokens | null>;
|
||||
getLinkedEditingRanges(textDocument: TextDocumentIdentifier, position: Position): Promise<LinkedEditingRanges | null>;
|
||||
fileReferences(textDocument: TextDocumentIdentifier): Promise<Location[] | null>;
|
||||
getDefinitions(textDocument: TextDocumentIdentifier, position: Position): Promise<DefinitionLink[] | Location[]>;
|
||||
getTypeDefinitions(textDocument: TextDocumentIdentifier, position: Position): Promise<Location[] | null>;
|
||||
getImplementations(textDocument: TextDocumentIdentifier, position: Position): Promise<Location[] | null>;
|
||||
getReferences(textdocument: TextDocumentIdentifier, position: Position, context: ReferenceContext): Promise<Location[] | null>;
|
||||
prepareRename(textDocument: TextDocumentIdentifier, position: Position): Promise<Range | null>;
|
||||
rename(textDocument: TextDocumentIdentifier, position: Position, newName: string): Promise<WorkspaceEdit | null>;
|
||||
getDocumentColors(textDocument: TextDocumentIdentifier): Promise<ColorInformation[]>;
|
||||
getColorPresentations(textDocument: TextDocumentIdentifier, range: Range, color: Color): Promise<ColorPresentation[]>;
|
||||
getInlayHints(textDocument: TextDocumentIdentifier, range: Range, cancellationToken?: CancellationToken): Promise<InlayHint[]>;
|
||||
getSignatureHelp(textDocument: TextDocumentIdentifier, position: Position, context: SignatureHelpContext | undefined, cancellationToken?: CancellationToken): Promise<SignatureHelp | null>;
|
||||
onWatchFileChanges(onWatchFileChangesParams: any[]): Promise<void>;
|
||||
updateNonAstroFile(fileName: string, changes: TextDocumentContentChangeEvent[], text?: string): void;
|
||||
private getDocument;
|
||||
private execute;
|
||||
private tryExecutePlugin;
|
||||
}
|
||||
206
node_modules/@astrojs/language-server/dist/plugins/PluginHost.js
generated
vendored
Normal file
206
node_modules/@astrojs/language-server/dist/plugins/PluginHost.js
generated
vendored
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.PluginHost = void 0;
|
||||
const vscode_languageserver_1 = require("vscode-languageserver");
|
||||
const documents_1 = require("../core/documents");
|
||||
const utils_1 = require("../utils");
|
||||
var ExecuteMode;
|
||||
(function (ExecuteMode) {
|
||||
ExecuteMode[ExecuteMode["None"] = 0] = "None";
|
||||
ExecuteMode[ExecuteMode["FirstNonNull"] = 1] = "FirstNonNull";
|
||||
ExecuteMode[ExecuteMode["Collect"] = 2] = "Collect";
|
||||
})(ExecuteMode || (ExecuteMode = {}));
|
||||
class PluginHost {
|
||||
constructor(docManager) {
|
||||
this.docManager = docManager;
|
||||
this.plugins = [];
|
||||
this.pluginHostConfig = {
|
||||
filterIncompleteCompletions: true,
|
||||
definitionLinkSupport: false,
|
||||
};
|
||||
}
|
||||
initialize(pluginHostConfig) {
|
||||
this.pluginHostConfig = pluginHostConfig;
|
||||
}
|
||||
registerPlugin(plugin) {
|
||||
this.plugins.push(plugin);
|
||||
}
|
||||
async getCompletions(textDocument, position, completionContext, cancellationToken) {
|
||||
const document = this.getDocument(textDocument.uri);
|
||||
const completions = await Promise.all(this.plugins.map(async (plugin) => {
|
||||
const result = await this.tryExecutePlugin(plugin, 'getCompletions', [document, position, completionContext, cancellationToken], null);
|
||||
if (result) {
|
||||
return { result: result, plugin: plugin.__name };
|
||||
}
|
||||
})).then((fullCompletions) => fullCompletions.filter(utils_1.isNotNullOrUndefined));
|
||||
const html = completions.find((completion) => completion.plugin === 'html');
|
||||
const ts = completions.find((completion) => completion.plugin === 'typescript');
|
||||
const astro = completions.find((completion) => completion.plugin === 'astro');
|
||||
if (html && ts) {
|
||||
const inComponentStartTag = (0, documents_1.isInComponentStartTag)(document.html, document.offsetAt(position));
|
||||
// If the HTML plugin returned completions, it's highly likely that TS ones are duplicate
|
||||
if (html.result.items.length > 0) {
|
||||
ts.result.items = [];
|
||||
}
|
||||
// Inside components, if the Astro plugin has completions we don't want the TS ones are they're duplicates
|
||||
if (astro && astro.result.items.length > 0 && inComponentStartTag) {
|
||||
ts.result.items = [];
|
||||
}
|
||||
}
|
||||
let flattenedCompletions = completions.flatMap((completion) => completion.result.items);
|
||||
const isIncomplete = completions.reduce((incomplete, completion) => incomplete || completion.result.isIncomplete, false);
|
||||
// If the result is incomplete, we need to filter the results ourselves
|
||||
// to throw out non-matching results. VSCode does filter client-side,
|
||||
// but other IDEs might not.
|
||||
if (isIncomplete && this.pluginHostConfig.filterIncompleteCompletions) {
|
||||
const offset = document.offsetAt(position);
|
||||
// Assumption for performance reasons:
|
||||
// Noone types import names longer than 20 characters and still expects perfect autocompletion.
|
||||
const text = document.getText().substring(Math.max(0, offset - 20), offset);
|
||||
const start = (0, utils_1.regexLastIndexOf)(text, /[\W\s]/g) + 1;
|
||||
const filterValue = text.substring(start).toLowerCase();
|
||||
flattenedCompletions = flattenedCompletions.filter((comp) => comp.label.toLowerCase().includes(filterValue));
|
||||
}
|
||||
return vscode_languageserver_1.CompletionList.create(flattenedCompletions, isIncomplete);
|
||||
}
|
||||
async resolveCompletion(textDocument, completionItem) {
|
||||
const document = this.getDocument(textDocument.uri);
|
||||
const result = await this.execute('resolveCompletion', [document, completionItem], ExecuteMode.FirstNonNull);
|
||||
return result ?? completionItem;
|
||||
}
|
||||
async getDiagnostics(textDocument) {
|
||||
const document = this.getDocument(textDocument.uri);
|
||||
const diagnostics = await this.execute('getDiagnostics', [document], ExecuteMode.Collect);
|
||||
return diagnostics;
|
||||
}
|
||||
async doHover(textDocument, position) {
|
||||
const document = this.getDocument(textDocument.uri);
|
||||
return this.execute('doHover', [document, position], ExecuteMode.FirstNonNull);
|
||||
}
|
||||
async formatDocument(textDocument, options) {
|
||||
const document = this.getDocument(textDocument.uri);
|
||||
return await this.execute('formatDocument', [document, options], ExecuteMode.Collect);
|
||||
}
|
||||
async getCodeActions(textDocument, range, context, cancellationToken) {
|
||||
const document = this.getDocument(textDocument.uri);
|
||||
return await this.execute('getCodeActions', [document, range, context, cancellationToken], ExecuteMode.Collect);
|
||||
}
|
||||
async doTagComplete(textDocument, position) {
|
||||
const document = this.getDocument(textDocument.uri);
|
||||
return this.execute('doTagComplete', [document, position], ExecuteMode.FirstNonNull);
|
||||
}
|
||||
async getFoldingRanges(textDocument) {
|
||||
const document = this.getDocument(textDocument.uri);
|
||||
return await this.execute('getFoldingRanges', [document], ExecuteMode.Collect);
|
||||
}
|
||||
async getDocumentSymbols(textDocument, cancellationToken) {
|
||||
const document = this.getDocument(textDocument.uri);
|
||||
return await this.execute('getDocumentSymbols', [document, cancellationToken], ExecuteMode.Collect);
|
||||
}
|
||||
async getSemanticTokens(textDocument, range, cancellationToken) {
|
||||
const document = this.getDocument(textDocument.uri);
|
||||
return await this.execute('getSemanticTokens', [document, range, cancellationToken], ExecuteMode.FirstNonNull);
|
||||
}
|
||||
async getLinkedEditingRanges(textDocument, position) {
|
||||
const document = this.getDocument(textDocument.uri);
|
||||
return await this.execute('getLinkedEditingRanges', [document, position], ExecuteMode.FirstNonNull);
|
||||
}
|
||||
async fileReferences(textDocument) {
|
||||
const document = this.getDocument(textDocument.uri);
|
||||
return await this.execute('fileReferences', [document], ExecuteMode.FirstNonNull);
|
||||
}
|
||||
async getDefinitions(textDocument, position) {
|
||||
const document = this.getDocument(textDocument.uri);
|
||||
const definitions = await this.execute('getDefinitions', [document, position], ExecuteMode.Collect);
|
||||
if (this.pluginHostConfig.definitionLinkSupport) {
|
||||
return definitions;
|
||||
}
|
||||
else {
|
||||
return definitions.map((def) => ({ range: def.targetSelectionRange, uri: def.targetUri }));
|
||||
}
|
||||
}
|
||||
getTypeDefinitions(textDocument, position) {
|
||||
const document = this.getDocument(textDocument.uri);
|
||||
return this.execute('getTypeDefinitions', [document, position], ExecuteMode.FirstNonNull);
|
||||
}
|
||||
getImplementations(textDocument, position) {
|
||||
const document = this.getDocument(textDocument.uri);
|
||||
return this.execute('getImplementation', [document, position], ExecuteMode.FirstNonNull);
|
||||
}
|
||||
getReferences(textdocument, position, context) {
|
||||
const document = this.getDocument(textdocument.uri);
|
||||
return this.execute('findReferences', [document, position, context], ExecuteMode.FirstNonNull);
|
||||
}
|
||||
async prepareRename(textDocument, position) {
|
||||
const document = this.getDocument(textDocument.uri);
|
||||
return await this.execute('prepareRename', [document, position], ExecuteMode.FirstNonNull);
|
||||
}
|
||||
async rename(textDocument, position, newName) {
|
||||
const document = this.getDocument(textDocument.uri);
|
||||
return this.execute('rename', [document, position, newName], ExecuteMode.FirstNonNull);
|
||||
}
|
||||
async getDocumentColors(textDocument) {
|
||||
const document = this.getDocument(textDocument.uri);
|
||||
return await this.execute('getDocumentColors', [document], ExecuteMode.Collect);
|
||||
}
|
||||
async getColorPresentations(textDocument, range, color) {
|
||||
const document = this.getDocument(textDocument.uri);
|
||||
return await this.execute('getColorPresentations', [document, range, color], ExecuteMode.Collect);
|
||||
}
|
||||
async getInlayHints(textDocument, range, cancellationToken) {
|
||||
const document = this.getDocument(textDocument.uri);
|
||||
return (await this.execute('getInlayHints', [document, range], ExecuteMode.FirstNonNull)) ?? [];
|
||||
}
|
||||
async getSignatureHelp(textDocument, position, context, cancellationToken) {
|
||||
const document = this.getDocument(textDocument.uri);
|
||||
return await this.execute('getSignatureHelp', [document, position, context, cancellationToken], ExecuteMode.FirstNonNull);
|
||||
}
|
||||
async onWatchFileChanges(onWatchFileChangesParams) {
|
||||
for (const support of this.plugins) {
|
||||
await support.onWatchFileChanges?.(onWatchFileChangesParams);
|
||||
}
|
||||
}
|
||||
updateNonAstroFile(fileName, changes, text) {
|
||||
for (const support of this.plugins) {
|
||||
support.updateNonAstroFile?.(fileName, changes, text);
|
||||
}
|
||||
}
|
||||
getDocument(uri) {
|
||||
const document = this.docManager.get(uri);
|
||||
if (!document) {
|
||||
throw new Error('Cannot call methods on an unopened document');
|
||||
}
|
||||
return document;
|
||||
}
|
||||
async execute(name, args, mode) {
|
||||
const plugins = this.plugins.filter((plugin) => typeof plugin[name] === 'function');
|
||||
switch (mode) {
|
||||
case ExecuteMode.FirstNonNull:
|
||||
for (const plugin of plugins) {
|
||||
const res = await this.tryExecutePlugin(plugin, name, args, null);
|
||||
if (res != null) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
case ExecuteMode.Collect:
|
||||
return (await Promise.all(plugins.map((plugin) => {
|
||||
let ret = this.tryExecutePlugin(plugin, name, args, []);
|
||||
return ret;
|
||||
}))).flat();
|
||||
case ExecuteMode.None:
|
||||
await Promise.all(plugins.map((plugin) => this.tryExecutePlugin(plugin, name, args, null)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
async tryExecutePlugin(plugin, fnName, args, failValue) {
|
||||
try {
|
||||
return await plugin[fnName](...args);
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
return failValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.PluginHost = PluginHost;
|
||||
17
node_modules/@astrojs/language-server/dist/plugins/astro/AstroPlugin.d.ts
generated
vendored
Normal file
17
node_modules/@astrojs/language-server/dist/plugins/astro/AstroPlugin.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import { CompletionContext, Diagnostic, FoldingRange, FormattingOptions, Position, TextEdit } from 'vscode-languageserver';
|
||||
import type { ConfigManager } from '../../core/config';
|
||||
import type { AstroDocument } from '../../core/documents';
|
||||
import type { AppCompletionList, Plugin } from '../interfaces';
|
||||
import type { LanguageServiceManager } from '../typescript/LanguageServiceManager';
|
||||
export declare class AstroPlugin implements Plugin {
|
||||
__name: string;
|
||||
private configManager;
|
||||
private readonly languageServiceManager;
|
||||
private readonly completionProvider;
|
||||
private readonly diagnosticsProvider;
|
||||
constructor(configManager: ConfigManager, languageServiceManager: LanguageServiceManager);
|
||||
getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext): Promise<AppCompletionList | null>;
|
||||
getDiagnostics(document: AstroDocument): Promise<Diagnostic[]>;
|
||||
formatDocument(document: AstroDocument, options: FormattingOptions): Promise<TextEdit[]>;
|
||||
getFoldingRanges(document: AstroDocument): FoldingRange[];
|
||||
}
|
||||
90
node_modules/@astrojs/language-server/dist/plugins/astro/AstroPlugin.js
generated
vendored
Normal file
90
node_modules/@astrojs/language-server/dist/plugins/astro/AstroPlugin.js
generated
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AstroPlugin = void 0;
|
||||
const vscode_languageserver_1 = require("vscode-languageserver");
|
||||
const importPackage_1 = require("../../importPackage");
|
||||
const CompletionsProvider_1 = require("./features/CompletionsProvider");
|
||||
const DiagnosticsProvider_1 = require("./features/DiagnosticsProvider");
|
||||
class AstroPlugin {
|
||||
constructor(configManager, languageServiceManager) {
|
||||
this.__name = 'astro';
|
||||
this.configManager = configManager;
|
||||
this.languageServiceManager = languageServiceManager;
|
||||
this.completionProvider = new CompletionsProvider_1.CompletionsProviderImpl(this.languageServiceManager);
|
||||
this.diagnosticsProvider = new DiagnosticsProvider_1.DiagnosticsProviderImpl(this.languageServiceManager);
|
||||
}
|
||||
async getCompletions(document, position, completionContext) {
|
||||
const completions = this.completionProvider.getCompletions(document, position, completionContext);
|
||||
return completions;
|
||||
}
|
||||
async getDiagnostics(document) {
|
||||
return await this.diagnosticsProvider.getDiagnostics(document);
|
||||
}
|
||||
async formatDocument(document, options) {
|
||||
const filePath = document.getFilePath();
|
||||
if (!filePath) {
|
||||
return [];
|
||||
}
|
||||
const prettier = (0, importPackage_1.importPrettier)(filePath);
|
||||
const prettierConfig = (await prettier.resolveConfig(filePath, { editorconfig: true, useCache: false })) ?? {};
|
||||
const prettierVSConfig = await this.configManager.getPrettierVSConfig(document);
|
||||
const editorFormatConfig = options !== undefined // We need to check for options existing here because some editors might not have it
|
||||
? {
|
||||
tabWidth: options.tabSize,
|
||||
useTabs: !options.insertSpaces,
|
||||
}
|
||||
: {};
|
||||
// Return a config with the following cascade:
|
||||
// - Prettier config file should always win if it exists, if it doesn't:
|
||||
// - Prettier config from the VS Code extension is used, if it doesn't exist:
|
||||
// - Use the editor's basic configuration settings
|
||||
const resultConfig = returnObjectIfHasKeys(prettierConfig) || returnObjectIfHasKeys(prettierVSConfig) || editorFormatConfig;
|
||||
const fileInfo = await prettier.getFileInfo(filePath, { ignorePath: '.prettierignore' });
|
||||
if (fileInfo.ignored) {
|
||||
return [];
|
||||
}
|
||||
const result = prettier.format(document.getText(), {
|
||||
...resultConfig,
|
||||
plugins: [...getAstroPrettierPlugin(), ...(resultConfig.plugins ?? [])],
|
||||
parser: 'astro',
|
||||
});
|
||||
return document.getText() === result
|
||||
? []
|
||||
: [vscode_languageserver_1.TextEdit.replace(vscode_languageserver_1.Range.create(document.positionAt(0), document.positionAt(document.getTextLength())), result)];
|
||||
function getAstroPrettierPlugin() {
|
||||
const hasPluginLoadedAlready = prettier.getSupportInfo().languages.some((l) => l.name === 'astro');
|
||||
return hasPluginLoadedAlready ? [] : [(0, importPackage_1.getPrettierPluginPath)(filePath)];
|
||||
}
|
||||
}
|
||||
getFoldingRanges(document) {
|
||||
const foldingRanges = [];
|
||||
const { frontmatter } = document.astroMeta;
|
||||
// Currently editing frontmatter, don't fold
|
||||
if (frontmatter.state !== 'closed')
|
||||
return foldingRanges;
|
||||
// The way folding ranges work is by folding anything between the starting position and the ending one, as such
|
||||
// the start in this case should be after the frontmatter start (after the starting ---) until the last character
|
||||
// of the last line of the frontmatter before its ending (before the closing ---)
|
||||
// ---
|
||||
// ^ -- start
|
||||
// console.log("Astro")
|
||||
// --- ^ -- end
|
||||
const start = document.positionAt(frontmatter.startOffset + 3);
|
||||
const end = document.positionAt(frontmatter.endOffset - 1);
|
||||
return [
|
||||
{
|
||||
startLine: start.line,
|
||||
startCharacter: start.character,
|
||||
endLine: end.line,
|
||||
endCharacter: end.character,
|
||||
kind: vscode_languageserver_1.FoldingRangeKind.Imports,
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
exports.AstroPlugin = AstroPlugin;
|
||||
function returnObjectIfHasKeys(obj) {
|
||||
if (Object.keys(obj || {}).length > 0) {
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
17
node_modules/@astrojs/language-server/dist/plugins/astro/features/CompletionsProvider.d.ts
generated
vendored
Normal file
17
node_modules/@astrojs/language-server/dist/plugins/astro/features/CompletionsProvider.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import { CompletionContext, Position } from 'vscode-languageserver';
|
||||
import type { AstroDocument } from '../../../core/documents';
|
||||
import type { AppCompletionList, CompletionsProvider } from '../../interfaces';
|
||||
import type { LanguageServiceManager } from '../../typescript/LanguageServiceManager';
|
||||
export declare class CompletionsProviderImpl implements CompletionsProvider {
|
||||
private readonly languageServiceManager;
|
||||
private readonly ts;
|
||||
private lastCompletion;
|
||||
directivesHTMLLang: import("vscode-html-languageservice").LanguageService;
|
||||
constructor(languageServiceManager: LanguageServiceManager);
|
||||
getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext): Promise<AppCompletionList | null>;
|
||||
private getComponentScriptCompletion;
|
||||
private getPropCompletionsAndFilePath;
|
||||
private getImportedSymbol;
|
||||
private getPropType;
|
||||
private getCompletionItemForProperty;
|
||||
}
|
||||
242
node_modules/@astrojs/language-server/dist/plugins/astro/features/CompletionsProvider.js
generated
vendored
Normal file
242
node_modules/@astrojs/language-server/dist/plugins/astro/features/CompletionsProvider.js
generated
vendored
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.CompletionsProviderImpl = void 0;
|
||||
const vscode_html_languageservice_1 = require("vscode-html-languageservice");
|
||||
const vscode_languageserver_1 = require("vscode-languageserver");
|
||||
const utils_1 = require("../../../core/documents/utils");
|
||||
const astro_attributes_1 = require("../../html/features/astro-attributes");
|
||||
const utils_2 = require("../../html/utils");
|
||||
const utils_3 = require("../../typescript/utils");
|
||||
class CompletionsProviderImpl {
|
||||
constructor(languageServiceManager) {
|
||||
this.lastCompletion = null;
|
||||
this.directivesHTMLLang = (0, vscode_html_languageservice_1.getLanguageService)({
|
||||
customDataProviders: [astro_attributes_1.astroDirectives],
|
||||
useDefaultDataProvider: false,
|
||||
});
|
||||
this.languageServiceManager = languageServiceManager;
|
||||
this.ts = languageServiceManager.docContext.ts;
|
||||
}
|
||||
async getCompletions(document, position, completionContext) {
|
||||
let items = [];
|
||||
const html = document.html;
|
||||
const offset = document.offsetAt(position);
|
||||
const node = html.findNodeAt(offset);
|
||||
const insideExpression = (0, utils_1.isInsideExpression)(document.getText(), node.start, offset);
|
||||
if (completionContext?.triggerCharacter === '-' && node.parent === undefined && !insideExpression) {
|
||||
const frontmatter = this.getComponentScriptCompletion(document, position);
|
||||
if (frontmatter)
|
||||
items.push(frontmatter);
|
||||
}
|
||||
if ((0, utils_1.isInComponentStartTag)(html, offset) && !insideExpression) {
|
||||
const { completions: props, componentFilePath } = await this.getPropCompletionsAndFilePath(document, position, completionContext);
|
||||
if (props.length) {
|
||||
items.push(...props);
|
||||
}
|
||||
const isAstro = componentFilePath?.endsWith('.astro');
|
||||
if (!isAstro && node.tag !== 'Fragment') {
|
||||
const directives = (0, utils_2.removeDataAttrCompletion)(this.directivesHTMLLang.doComplete(document, position, html).items);
|
||||
items.push(...directives);
|
||||
}
|
||||
}
|
||||
return vscode_languageserver_1.CompletionList.create(items, true);
|
||||
}
|
||||
getComponentScriptCompletion(document, position) {
|
||||
const base = {
|
||||
kind: vscode_languageserver_1.CompletionItemKind.Snippet,
|
||||
label: '---',
|
||||
sortText: '\0',
|
||||
preselect: true,
|
||||
detail: 'Create component script block',
|
||||
insertTextFormat: vscode_languageserver_1.InsertTextFormat.Snippet,
|
||||
commitCharacters: [],
|
||||
};
|
||||
const prefix = document.getLineUntilOffset(document.offsetAt(position));
|
||||
if (document.astroMeta.frontmatter.state === null) {
|
||||
return {
|
||||
...base,
|
||||
insertText: '---\n$0\n---',
|
||||
textEdit: prefix.match(/^\s*\-+/)
|
||||
? vscode_languageserver_1.TextEdit.replace({ start: { ...position, character: 0 }, end: position }, '---\n$0\n---')
|
||||
: undefined,
|
||||
};
|
||||
}
|
||||
if (document.astroMeta.frontmatter.state === 'open') {
|
||||
let insertText = '---';
|
||||
// If the current line is a full component script starter/ender, the user expects a full frontmatter
|
||||
// completion and not just a completion for "---" on the same line (which result in, well, nothing)
|
||||
if (prefix === '---') {
|
||||
insertText = '---\n$0\n---';
|
||||
}
|
||||
return {
|
||||
...base,
|
||||
insertText,
|
||||
detail: insertText === '---' ? 'Close component script block' : 'Create component script block',
|
||||
textEdit: prefix.match(/^\s*\-+/)
|
||||
? vscode_languageserver_1.TextEdit.replace({ start: { ...position, character: 0 }, end: position }, insertText)
|
||||
: undefined,
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
async getPropCompletionsAndFilePath(document, position, completionContext) {
|
||||
const offset = document.offsetAt(position);
|
||||
const html = document.html;
|
||||
const node = html.findNodeAt(offset);
|
||||
if (!(0, utils_1.isPossibleComponent)(node)) {
|
||||
return { completions: [], componentFilePath: null };
|
||||
}
|
||||
const inAttribute = node.start + node.tag.length < offset;
|
||||
if (!inAttribute) {
|
||||
return { completions: [], componentFilePath: null };
|
||||
}
|
||||
if (completionContext?.triggerCharacter === '/' || completionContext?.triggerCharacter === '>') {
|
||||
return { completions: [], componentFilePath: null };
|
||||
}
|
||||
// If inside of attribute value, skip.
|
||||
if (completionContext &&
|
||||
completionContext.triggerKind === vscode_languageserver_1.CompletionTriggerKind.TriggerCharacter &&
|
||||
completionContext.triggerCharacter === '"') {
|
||||
return { completions: [], componentFilePath: null };
|
||||
}
|
||||
const componentName = node.tag;
|
||||
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
||||
// Get the source file
|
||||
const tsFilePath = tsDoc.filePath;
|
||||
const program = lang.getProgram();
|
||||
const sourceFile = program?.getSourceFile(tsFilePath);
|
||||
const typeChecker = program?.getTypeChecker();
|
||||
if (!sourceFile || !typeChecker) {
|
||||
return { completions: [], componentFilePath: null };
|
||||
}
|
||||
// Get the import statement
|
||||
const imp = this.getImportedSymbol(sourceFile, componentName);
|
||||
const importType = imp && typeChecker.getTypeAtLocation(imp);
|
||||
if (!importType) {
|
||||
return { completions: [], componentFilePath: null };
|
||||
}
|
||||
const symbol = importType.getSymbol();
|
||||
if (!symbol) {
|
||||
return { completions: [], componentFilePath: null };
|
||||
}
|
||||
const symbolDeclaration = symbol.declarations;
|
||||
if (!symbolDeclaration) {
|
||||
return { completions: [], componentFilePath: null };
|
||||
}
|
||||
const filePath = symbolDeclaration[0].getSourceFile().fileName;
|
||||
const componentSnapshot = await this.languageServiceManager.getSnapshot(filePath);
|
||||
if (this.lastCompletion) {
|
||||
if (this.lastCompletion.tag === componentName &&
|
||||
this.lastCompletion.documentVersion == componentSnapshot.version) {
|
||||
return { completions: this.lastCompletion.completions, componentFilePath: filePath };
|
||||
}
|
||||
}
|
||||
// Get the component's props type
|
||||
const componentType = this.getPropType(symbolDeclaration, typeChecker);
|
||||
if (!componentType) {
|
||||
return { completions: [], componentFilePath: null };
|
||||
}
|
||||
let completionItems = [];
|
||||
// Add completions for this component's props type properties
|
||||
const properties = componentType.getProperties().filter((property) => property.name !== 'children') || [];
|
||||
properties.forEach((property) => {
|
||||
const type = typeChecker.getTypeOfSymbolAtLocation(property, imp);
|
||||
let completionItem = this.getCompletionItemForProperty(property, typeChecker, type);
|
||||
completionItems.push(completionItem);
|
||||
});
|
||||
this.lastCompletion = {
|
||||
tag: componentName,
|
||||
documentVersion: componentSnapshot.version,
|
||||
completions: completionItems,
|
||||
};
|
||||
return { completions: completionItems, componentFilePath: filePath };
|
||||
}
|
||||
getImportedSymbol(sourceFile, identifier) {
|
||||
for (let list of sourceFile.getChildren()) {
|
||||
for (let node of list.getChildren()) {
|
||||
if (this.ts.isImportDeclaration(node)) {
|
||||
let clauses = node.importClause;
|
||||
if (!clauses)
|
||||
continue;
|
||||
let namedImport = clauses.getChildAt(0);
|
||||
if (this.ts.isNamedImports(namedImport)) {
|
||||
for (let imp of namedImport.elements) {
|
||||
// Iterate the named imports
|
||||
if (imp.name.getText() === identifier) {
|
||||
return imp;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (this.ts.isIdentifier(namedImport)) {
|
||||
if (namedImport.getText() === identifier) {
|
||||
return namedImport;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
getPropType(declarations, typeChecker) {
|
||||
for (const decl of declarations) {
|
||||
const fileName = (0, utils_3.toVirtualFilePath)(decl.getSourceFile().fileName);
|
||||
if (fileName.endsWith('.tsx') || fileName.endsWith('.jsx') || fileName.endsWith('.d.ts')) {
|
||||
if (!this.ts.isFunctionDeclaration(decl) && !this.ts.isFunctionTypeNode(decl)) {
|
||||
console.error(`We only support functions declarations at the moment`);
|
||||
continue;
|
||||
}
|
||||
const fn = decl;
|
||||
if (!fn.parameters.length)
|
||||
continue;
|
||||
const param1 = fn.parameters[0];
|
||||
const propType = typeChecker.getTypeAtLocation(param1);
|
||||
return propType;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
getCompletionItemForProperty(mem, typeChecker, type) {
|
||||
const typeString = typeChecker.typeToString(type);
|
||||
let insertText = mem.name;
|
||||
switch (typeString) {
|
||||
case 'string':
|
||||
insertText = `${mem.name}="$1"`;
|
||||
break;
|
||||
case 'boolean':
|
||||
insertText = mem.name;
|
||||
break;
|
||||
default:
|
||||
insertText = `${mem.name}={$1}`;
|
||||
break;
|
||||
}
|
||||
let item = {
|
||||
label: mem.name,
|
||||
detail: typeString,
|
||||
insertText: insertText,
|
||||
insertTextFormat: vscode_languageserver_1.InsertTextFormat.Snippet,
|
||||
commitCharacters: [],
|
||||
// Ensure that props shows up first as a completion, despite this plugin being ran after the HTML one
|
||||
sortText: '\0',
|
||||
};
|
||||
if (mem.flags & this.ts.SymbolFlags.Optional) {
|
||||
item.filterText = item.label;
|
||||
item.label += '?';
|
||||
// Put optional props at a lower priority
|
||||
item.sortText = '_';
|
||||
}
|
||||
mem.getDocumentationComment(typeChecker);
|
||||
let description = mem
|
||||
.getDocumentationComment(typeChecker)
|
||||
.map((val) => val.text)
|
||||
.join('\n');
|
||||
if (description) {
|
||||
let docs = {
|
||||
kind: vscode_languageserver_1.MarkupKind.Markdown,
|
||||
value: description,
|
||||
};
|
||||
item.documentation = docs;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
}
|
||||
exports.CompletionsProviderImpl = CompletionsProviderImpl;
|
||||
10
node_modules/@astrojs/language-server/dist/plugins/astro/features/DiagnosticsProvider.d.ts
generated
vendored
Normal file
10
node_modules/@astrojs/language-server/dist/plugins/astro/features/DiagnosticsProvider.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import { Diagnostic } from 'vscode-languageserver-types';
|
||||
import { AstroDocument } from '../../../core/documents';
|
||||
import { DiagnosticsProvider } from '../../interfaces';
|
||||
import { LanguageServiceManager } from '../../typescript/LanguageServiceManager';
|
||||
export declare class DiagnosticsProviderImpl implements DiagnosticsProvider {
|
||||
private languageServiceManager;
|
||||
constructor(languageServiceManager: LanguageServiceManager);
|
||||
getDiagnostics(document: AstroDocument): Promise<Diagnostic[]>;
|
||||
private compilerMessageToDiagnostic;
|
||||
}
|
||||
23
node_modules/@astrojs/language-server/dist/plugins/astro/features/DiagnosticsProvider.js
generated
vendored
Normal file
23
node_modules/@astrojs/language-server/dist/plugins/astro/features/DiagnosticsProvider.js
generated
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.DiagnosticsProviderImpl = void 0;
|
||||
const vscode_languageserver_types_1 = require("vscode-languageserver-types");
|
||||
class DiagnosticsProviderImpl {
|
||||
constructor(languageServiceManager) {
|
||||
this.languageServiceManager = languageServiceManager;
|
||||
}
|
||||
async getDiagnostics(document) {
|
||||
const { tsDoc } = (await this.languageServiceManager.getLSAndTSDoc(document));
|
||||
return tsDoc.compilerDiagnostics.map(this.compilerMessageToDiagnostic);
|
||||
}
|
||||
compilerMessageToDiagnostic(message) {
|
||||
return {
|
||||
message: message.text + '\n\n' + message.hint,
|
||||
range: vscode_languageserver_types_1.Range.create(message.location.line - 1, message.location.column - 1, message.location.line, message.location.length),
|
||||
code: message.code,
|
||||
severity: message.severity,
|
||||
source: 'astro',
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.DiagnosticsProviderImpl = DiagnosticsProviderImpl;
|
||||
45
node_modules/@astrojs/language-server/dist/plugins/css/CSSDocument.d.ts
generated
vendored
Normal file
45
node_modules/@astrojs/language-server/dist/plugins/css/CSSDocument.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import type { Stylesheet, TextDocument } from 'vscode-css-languageservice';
|
||||
import type { Position } from 'vscode-languageserver';
|
||||
import { AstroDocument, DocumentMapper, ReadableDocument, TagInformation } from '../../core/documents';
|
||||
export interface CSSDocumentBase extends DocumentMapper, TextDocument {
|
||||
languageId: string;
|
||||
stylesheet: Stylesheet;
|
||||
}
|
||||
export declare class CSSDocument extends ReadableDocument implements DocumentMapper {
|
||||
private parent;
|
||||
private styleInfo;
|
||||
readonly version: number;
|
||||
stylesheet: Stylesheet;
|
||||
languageId: string;
|
||||
constructor(parent: AstroDocument, styleInfo: Pick<TagInformation, 'attributes' | 'start' | 'end'>);
|
||||
/**
|
||||
* Get the fragment position relative to the parent
|
||||
* @param pos Position in fragment
|
||||
*/
|
||||
getOriginalPosition(pos: Position): Position;
|
||||
/**
|
||||
* Get the position relative to the start of the fragment
|
||||
* @param pos Position in parent
|
||||
*/
|
||||
getGeneratedPosition(pos: Position): Position;
|
||||
/**
|
||||
* Returns true if the given parent position is inside of this fragment
|
||||
* @param pos Position in parent
|
||||
*/
|
||||
isInGenerated(pos: Position): boolean;
|
||||
/**
|
||||
* Get the fragment text from the parent
|
||||
*/
|
||||
getText(): string;
|
||||
/**
|
||||
* Returns the length of the fragment as calculated from the start and end position
|
||||
*/
|
||||
getTextLength(): number;
|
||||
/**
|
||||
* Return the parent file path
|
||||
*/
|
||||
getFilePath(): string | null;
|
||||
getURL(): string;
|
||||
getAttributes(): Record<string, string>;
|
||||
private get language();
|
||||
}
|
||||
68
node_modules/@astrojs/language-server/dist/plugins/css/CSSDocument.js
generated
vendored
Normal file
68
node_modules/@astrojs/language-server/dist/plugins/css/CSSDocument.js
generated
vendored
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.CSSDocument = void 0;
|
||||
const documents_1 = require("../../core/documents");
|
||||
const language_service_1 = require("./language-service");
|
||||
class CSSDocument extends documents_1.ReadableDocument {
|
||||
constructor(parent, styleInfo) {
|
||||
super();
|
||||
this.parent = parent;
|
||||
this.styleInfo = styleInfo;
|
||||
this.version = this.parent.version;
|
||||
this.languageId = this.language;
|
||||
this.stylesheet = (0, language_service_1.getLanguageService)(this.language).parseStylesheet(this);
|
||||
}
|
||||
/**
|
||||
* Get the fragment position relative to the parent
|
||||
* @param pos Position in fragment
|
||||
*/
|
||||
getOriginalPosition(pos) {
|
||||
const parentOffset = this.styleInfo.start + this.offsetAt(pos);
|
||||
return this.parent.positionAt(parentOffset);
|
||||
}
|
||||
/**
|
||||
* Get the position relative to the start of the fragment
|
||||
* @param pos Position in parent
|
||||
*/
|
||||
getGeneratedPosition(pos) {
|
||||
const fragmentOffset = this.parent.offsetAt(pos) - this.styleInfo.start;
|
||||
return this.positionAt(fragmentOffset);
|
||||
}
|
||||
/**
|
||||
* Returns true if the given parent position is inside of this fragment
|
||||
* @param pos Position in parent
|
||||
*/
|
||||
isInGenerated(pos) {
|
||||
const offset = this.parent.offsetAt(pos);
|
||||
return offset >= this.styleInfo.start && offset <= this.styleInfo.end;
|
||||
}
|
||||
/**
|
||||
* Get the fragment text from the parent
|
||||
*/
|
||||
getText() {
|
||||
return this.parent.getText().slice(this.styleInfo.start, this.styleInfo.end);
|
||||
}
|
||||
/**
|
||||
* Returns the length of the fragment as calculated from the start and end position
|
||||
*/
|
||||
getTextLength() {
|
||||
return this.styleInfo.end - this.styleInfo.start;
|
||||
}
|
||||
/**
|
||||
* Return the parent file path
|
||||
*/
|
||||
getFilePath() {
|
||||
return this.parent.getFilePath();
|
||||
}
|
||||
getURL() {
|
||||
return this.parent.getURL();
|
||||
}
|
||||
getAttributes() {
|
||||
return this.styleInfo.attributes;
|
||||
}
|
||||
get language() {
|
||||
const attrs = this.getAttributes();
|
||||
return attrs.lang || attrs.type || 'css';
|
||||
}
|
||||
}
|
||||
exports.CSSDocument = CSSDocument;
|
||||
39
node_modules/@astrojs/language-server/dist/plugins/css/CSSPlugin.d.ts
generated
vendored
Normal file
39
node_modules/@astrojs/language-server/dist/plugins/css/CSSPlugin.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import { Color, ColorInformation, ColorPresentation, CompletionContext, CompletionList, FoldingRange, Hover, Position, Range, SymbolInformation, WorkspaceEdit } from 'vscode-languageserver';
|
||||
import type { ConfigManager } from '../../core/config/ConfigManager';
|
||||
import { AstroDocument } from '../../core/documents';
|
||||
import type { Plugin } from '../interfaces';
|
||||
export declare class CSSPlugin implements Plugin {
|
||||
__name: string;
|
||||
private configManager;
|
||||
private cssDocuments;
|
||||
private triggerCharacters;
|
||||
constructor(configManager: ConfigManager);
|
||||
doHover(document: AstroDocument, position: Position): Promise<Hover | null>;
|
||||
private doHoverInternal;
|
||||
getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext): Promise<CompletionList | null>;
|
||||
private getCompletionsInternal;
|
||||
getDocumentColors(document: AstroDocument): Promise<ColorInformation[]>;
|
||||
getColorPresentations(document: AstroDocument, range: Range, color: Color): Promise<ColorPresentation[]>;
|
||||
prepareRename(document: AstroDocument, position: Position): Range | null;
|
||||
rename(document: AstroDocument, position: Position, newName: string): WorkspaceEdit | null;
|
||||
getFoldingRanges(document: AstroDocument): FoldingRange[] | null;
|
||||
getDocumentSymbols(document: AstroDocument): Promise<SymbolInformation[]>;
|
||||
private inStyleAttributeWithoutInterpolation;
|
||||
/**
|
||||
* Get the associated CSS Document for a style tag
|
||||
*/
|
||||
private getCSSDocumentForStyleTag;
|
||||
/**
|
||||
* Get all the CSSDocuments in a document
|
||||
*/
|
||||
private getCSSDocumentsForDocument;
|
||||
/**
|
||||
* Get all the stylesheets (Stylesheet type) in a document
|
||||
*/
|
||||
private getStylesheetsForDocument;
|
||||
/**
|
||||
* Get style tag at position for a document
|
||||
*/
|
||||
private getStyleTagForPosition;
|
||||
private featureEnabled;
|
||||
}
|
||||
274
node_modules/@astrojs/language-server/dist/plugins/css/CSSPlugin.js
generated
vendored
Normal file
274
node_modules/@astrojs/language-server/dist/plugins/css/CSSPlugin.js
generated
vendored
Normal file
|
|
@ -0,0 +1,274 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.CSSPlugin = void 0;
|
||||
const emmet_helper_1 = require("@vscode/emmet-helper");
|
||||
const vscode_languageserver_1 = require("vscode-languageserver");
|
||||
const documents_1 = require("../../core/documents");
|
||||
const parseHtml_1 = require("../../core/documents/parseHtml");
|
||||
const CSSDocument_1 = require("./CSSDocument");
|
||||
const getIdClassCompletions_1 = require("./features/getIdClassCompletions");
|
||||
const language_service_1 = require("./language-service");
|
||||
const StyleAttributeDocument_1 = require("./StyleAttributeDocument");
|
||||
class CSSPlugin {
|
||||
constructor(configManager) {
|
||||
this.__name = 'css';
|
||||
this.cssDocuments = new WeakMap();
|
||||
this.triggerCharacters = new Set(['.', ':', '-', '/']);
|
||||
this.configManager = configManager;
|
||||
}
|
||||
async doHover(document, position) {
|
||||
if (!(await this.featureEnabled(document, 'hover'))) {
|
||||
return null;
|
||||
}
|
||||
if ((0, documents_1.isInsideFrontmatter)(document.getText(), document.offsetAt(position))) {
|
||||
return null;
|
||||
}
|
||||
const styleTag = this.getStyleTagForPosition(document, position);
|
||||
// We technically can return results even for open tags, however, a lot of the info returned is not valid
|
||||
// Since most editors will automatically close the tag before the user start working in them, this shouldn't be a problem
|
||||
if (styleTag && !styleTag.closed) {
|
||||
return null;
|
||||
}
|
||||
// If we don't have a style tag at this position, we might be in a style property instead, let's check
|
||||
if (!styleTag) {
|
||||
const attributeContext = (0, parseHtml_1.getAttributeContextAtPosition)(document, position);
|
||||
if (!attributeContext) {
|
||||
return null;
|
||||
}
|
||||
if (this.inStyleAttributeWithoutInterpolation(attributeContext, document.getText())) {
|
||||
const [start, end] = attributeContext.valueRange;
|
||||
return this.doHoverInternal(new StyleAttributeDocument_1.StyleAttributeDocument(document, start, end), position);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
const cssDocument = this.getCSSDocumentForStyleTag(styleTag, document);
|
||||
const cssLang = extractLanguage(cssDocument);
|
||||
if (!isSupportedByLangService(cssLang)) {
|
||||
return null;
|
||||
}
|
||||
return this.doHoverInternal(cssDocument, position);
|
||||
}
|
||||
doHoverInternal(cssDocument, position) {
|
||||
const hoverInfo = (0, language_service_1.getLanguageService)(extractLanguage(cssDocument)).doHover(cssDocument, cssDocument.getGeneratedPosition(position), cssDocument.stylesheet);
|
||||
return hoverInfo ? (0, documents_1.mapHoverToParent)(cssDocument, hoverInfo) : hoverInfo;
|
||||
}
|
||||
async getCompletions(document, position, completionContext) {
|
||||
if (!(await this.featureEnabled(document, 'completions'))) {
|
||||
return null;
|
||||
}
|
||||
if ((0, documents_1.isInsideFrontmatter)(document.getText(), document.offsetAt(position))) {
|
||||
return null;
|
||||
}
|
||||
const triggerCharacter = completionContext?.triggerCharacter;
|
||||
const triggerKind = completionContext?.triggerKind;
|
||||
const isCustomTriggerCharacter = triggerKind === vscode_languageserver_1.CompletionTriggerKind.TriggerCharacter;
|
||||
if (isCustomTriggerCharacter && triggerCharacter && !this.triggerCharacters.has(triggerCharacter)) {
|
||||
return null;
|
||||
}
|
||||
const styleTag = this.getStyleTagForPosition(document, position);
|
||||
if (styleTag && !styleTag.closed) {
|
||||
return null;
|
||||
}
|
||||
if (!styleTag) {
|
||||
const attributeContext = (0, parseHtml_1.getAttributeContextAtPosition)(document, position);
|
||||
if (!attributeContext) {
|
||||
return null;
|
||||
}
|
||||
if (this.inStyleAttributeWithoutInterpolation(attributeContext, document.getText())) {
|
||||
const [start, end] = attributeContext.valueRange;
|
||||
return await this.getCompletionsInternal(document, position, new StyleAttributeDocument_1.StyleAttributeDocument(document, start, end));
|
||||
}
|
||||
// If we're not in a style attribute, instead give completions for ids and classes used in the current document
|
||||
else if ((attributeContext.name == 'id' || attributeContext.name == 'class') && attributeContext.inValue) {
|
||||
const stylesheets = this.getStylesheetsForDocument(document);
|
||||
return (0, getIdClassCompletions_1.getIdClassCompletion)(stylesheets, attributeContext);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
const cssDocument = this.getCSSDocumentForStyleTag(styleTag, document);
|
||||
return await this.getCompletionsInternal(document, position, cssDocument);
|
||||
}
|
||||
async getCompletionsInternal(document, position, cssDocument) {
|
||||
const emmetConfig = await this.configManager.getEmmetConfig(document);
|
||||
if (isSASS(cssDocument)) {
|
||||
// The CSS language service does not support SASS (not to be confused with SCSS)
|
||||
// however we can at least still at least provide Emmet completions in SASS blocks
|
||||
return (0, emmet_helper_1.doComplete)(document, position, 'sass', emmetConfig) || null;
|
||||
}
|
||||
const cssLang = extractLanguage(cssDocument);
|
||||
const langService = (0, language_service_1.getLanguageService)(cssLang);
|
||||
let emmetResults = {
|
||||
isIncomplete: false,
|
||||
items: [],
|
||||
};
|
||||
const extensionConfig = await this.configManager.getConfig('astro', document.uri);
|
||||
if (extensionConfig?.css?.completions?.emmet ?? true) {
|
||||
langService.setCompletionParticipants([
|
||||
{
|
||||
onCssProperty: (context) => {
|
||||
if (context?.propertyName) {
|
||||
emmetResults =
|
||||
(0, emmet_helper_1.doComplete)(cssDocument, cssDocument.getGeneratedPosition(position), (0, language_service_1.getLanguage)(cssLang), emmetConfig) || emmetResults;
|
||||
}
|
||||
},
|
||||
onCssPropertyValue: (context) => {
|
||||
if (context?.propertyValue) {
|
||||
emmetResults =
|
||||
(0, emmet_helper_1.doComplete)(cssDocument, cssDocument.getGeneratedPosition(position), (0, language_service_1.getLanguage)(cssLang), emmetConfig) || emmetResults;
|
||||
}
|
||||
},
|
||||
},
|
||||
]);
|
||||
}
|
||||
const results = langService.doComplete(cssDocument, cssDocument.getGeneratedPosition(position), cssDocument.stylesheet);
|
||||
return vscode_languageserver_1.CompletionList.create([...(results ? results.items : []), ...emmetResults.items].map((completionItem) => (0, documents_1.mapCompletionItemToOriginal)(cssDocument, completionItem)),
|
||||
// Emmet completions change on every keystroke, so they are never complete
|
||||
emmetResults.items.length > 0);
|
||||
}
|
||||
async getDocumentColors(document) {
|
||||
if (!(await this.featureEnabled(document, 'documentColors'))) {
|
||||
return [];
|
||||
}
|
||||
const allColorInfo = this.getCSSDocumentsForDocument(document).flatMap((cssDoc) => {
|
||||
const cssLang = extractLanguage(cssDoc);
|
||||
const langService = (0, language_service_1.getLanguageService)(cssLang);
|
||||
if (!isSupportedByLangService(cssLang)) {
|
||||
return [];
|
||||
}
|
||||
return langService
|
||||
.findDocumentColors(cssDoc, cssDoc.stylesheet)
|
||||
.map((colorInfo) => (0, documents_1.mapObjWithRangeToOriginal)(cssDoc, colorInfo));
|
||||
});
|
||||
return allColorInfo;
|
||||
}
|
||||
async getColorPresentations(document, range, color) {
|
||||
if (!(await this.featureEnabled(document, 'documentColors'))) {
|
||||
return [];
|
||||
}
|
||||
const allColorPres = this.getCSSDocumentsForDocument(document).flatMap((cssDoc) => {
|
||||
const cssLang = extractLanguage(cssDoc);
|
||||
const langService = (0, language_service_1.getLanguageService)(cssLang);
|
||||
if ((!cssDoc.isInGenerated(range.start) && !cssDoc.isInGenerated(range.end)) ||
|
||||
!isSupportedByLangService(cssLang)) {
|
||||
return [];
|
||||
}
|
||||
return langService
|
||||
.getColorPresentations(cssDoc, cssDoc.stylesheet, color, (0, documents_1.mapRangeToGenerated)(cssDoc, range))
|
||||
.map((colorPres) => (0, documents_1.mapColorPresentationToOriginal)(cssDoc, colorPres));
|
||||
});
|
||||
return allColorPres;
|
||||
}
|
||||
prepareRename(document, position) {
|
||||
const styleTag = this.getStyleTagForPosition(document, position);
|
||||
if (!styleTag) {
|
||||
return null;
|
||||
}
|
||||
const cssDocument = this.getCSSDocumentForStyleTag(styleTag, document);
|
||||
const cssLang = extractLanguage(cssDocument);
|
||||
const langService = (0, language_service_1.getLanguageService)(cssLang);
|
||||
const range = langService.prepareRename(cssDocument, cssDocument.getGeneratedPosition(position), cssDocument.stylesheet);
|
||||
if (!range) {
|
||||
return null;
|
||||
}
|
||||
return (0, documents_1.mapRangeToOriginal)(cssDocument, range);
|
||||
}
|
||||
rename(document, position, newName) {
|
||||
const styleTag = this.getStyleTagForPosition(document, position);
|
||||
if (!styleTag) {
|
||||
return null;
|
||||
}
|
||||
const cssDocument = this.getCSSDocumentForStyleTag(styleTag, document);
|
||||
const cssLang = extractLanguage(cssDocument);
|
||||
const langService = (0, language_service_1.getLanguageService)(cssLang);
|
||||
const renames = langService.doRename(cssDocument, cssDocument.getGeneratedPosition(position), newName, cssDocument.stylesheet);
|
||||
if (renames?.changes?.[document.uri]) {
|
||||
renames.changes[document.uri] = renames?.changes?.[document.uri].map((edit) => (0, documents_1.mapObjWithRangeToOriginal)(cssDocument, edit));
|
||||
}
|
||||
return renames;
|
||||
}
|
||||
getFoldingRanges(document) {
|
||||
const allFoldingRanges = this.getCSSDocumentsForDocument(document).flatMap((cssDoc) => {
|
||||
const cssLang = extractLanguage(cssDoc);
|
||||
const langService = (0, language_service_1.getLanguageService)(cssLang);
|
||||
return langService.getFoldingRanges(cssDoc).map((foldingRange) => (0, documents_1.mapFoldingRangeToParent)(cssDoc, foldingRange));
|
||||
});
|
||||
return allFoldingRanges;
|
||||
}
|
||||
async getDocumentSymbols(document) {
|
||||
if (!(await this.featureEnabled(document, 'documentSymbols'))) {
|
||||
return [];
|
||||
}
|
||||
const allDocumentSymbols = this.getCSSDocumentsForDocument(document).flatMap((cssDoc) => {
|
||||
return (0, language_service_1.getLanguageService)(extractLanguage(cssDoc))
|
||||
.findDocumentSymbols(cssDoc, cssDoc.stylesheet)
|
||||
.map((symbol) => (0, documents_1.mapSymbolInformationToOriginal)(cssDoc, symbol));
|
||||
});
|
||||
return allDocumentSymbols;
|
||||
}
|
||||
inStyleAttributeWithoutInterpolation(attrContext, text) {
|
||||
return (attrContext.name === 'style' &&
|
||||
!!attrContext.valueRange &&
|
||||
!text.substring(attrContext.valueRange[0], attrContext.valueRange[1]).includes('{'));
|
||||
}
|
||||
/**
|
||||
* Get the associated CSS Document for a style tag
|
||||
*/
|
||||
getCSSDocumentForStyleTag(tag, document) {
|
||||
let cssDoc = this.cssDocuments.get(tag);
|
||||
if (!cssDoc || cssDoc.version < document.version) {
|
||||
cssDoc = new CSSDocument_1.CSSDocument(document, tag);
|
||||
this.cssDocuments.set(tag, cssDoc);
|
||||
}
|
||||
return cssDoc;
|
||||
}
|
||||
/**
|
||||
* Get all the CSSDocuments in a document
|
||||
*/
|
||||
getCSSDocumentsForDocument(document) {
|
||||
return document.styleTags.map((tag) => this.getCSSDocumentForStyleTag(tag, document));
|
||||
}
|
||||
/**
|
||||
* Get all the stylesheets (Stylesheet type) in a document
|
||||
*/
|
||||
getStylesheetsForDocument(document) {
|
||||
return this.getCSSDocumentsForDocument(document).map((cssDoc) => cssDoc.stylesheet);
|
||||
}
|
||||
/**
|
||||
* Get style tag at position for a document
|
||||
*/
|
||||
getStyleTagForPosition(document, position) {
|
||||
return document.styleTags.find((styleTag) => {
|
||||
return (0, documents_1.isInTag)(position, styleTag);
|
||||
});
|
||||
}
|
||||
async featureEnabled(document, feature) {
|
||||
return ((await this.configManager.isEnabled(document, 'css')) &&
|
||||
(await this.configManager.isEnabled(document, 'css', feature)));
|
||||
}
|
||||
}
|
||||
exports.CSSPlugin = CSSPlugin;
|
||||
/**
|
||||
* Check is a CSSDocument's language is supported by the CSS language service
|
||||
*/
|
||||
function isSupportedByLangService(language) {
|
||||
switch (language) {
|
||||
case 'css':
|
||||
case 'scss':
|
||||
case 'less':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
function isSASS(document) {
|
||||
switch (extractLanguage(document)) {
|
||||
case 'sass':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
function extractLanguage(document) {
|
||||
const lang = document.languageId;
|
||||
return lang.replace(/^text\//, '');
|
||||
}
|
||||
40
node_modules/@astrojs/language-server/dist/plugins/css/StyleAttributeDocument.d.ts
generated
vendored
Normal file
40
node_modules/@astrojs/language-server/dist/plugins/css/StyleAttributeDocument.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
import type { Stylesheet } from 'vscode-css-languageservice';
|
||||
import type { Position } from 'vscode-languageserver';
|
||||
import { AstroDocument, DocumentMapper, ReadableDocument } from '../../core/documents';
|
||||
export declare class StyleAttributeDocument extends ReadableDocument implements DocumentMapper {
|
||||
private readonly parent;
|
||||
private readonly attrStart;
|
||||
private readonly attrEnd;
|
||||
readonly version: number;
|
||||
stylesheet: Stylesheet;
|
||||
languageId: string;
|
||||
constructor(parent: AstroDocument, attrStart: number, attrEnd: number);
|
||||
/**
|
||||
* Get the fragment position relative to the parent
|
||||
* @param pos Position in fragment
|
||||
*/
|
||||
getOriginalPosition(pos: Position): Position;
|
||||
/**
|
||||
* Get the position relative to the start of the fragment
|
||||
* @param pos Position in parent
|
||||
*/
|
||||
getGeneratedPosition(pos: Position): Position;
|
||||
/**
|
||||
* Returns true if the given parent position is inside of this fragment
|
||||
* @param pos Position in parent
|
||||
*/
|
||||
isInGenerated(pos: Position): boolean;
|
||||
/**
|
||||
* Get the fragment text from the parent
|
||||
*/
|
||||
getText(): string;
|
||||
/**
|
||||
* Returns the length of the fragment as calculated from the start and end position
|
||||
*/
|
||||
getTextLength(): number;
|
||||
/**
|
||||
* Return the parent file path
|
||||
*/
|
||||
getFilePath(): string | null;
|
||||
getURL(): string;
|
||||
}
|
||||
64
node_modules/@astrojs/language-server/dist/plugins/css/StyleAttributeDocument.js
generated
vendored
Normal file
64
node_modules/@astrojs/language-server/dist/plugins/css/StyleAttributeDocument.js
generated
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.StyleAttributeDocument = void 0;
|
||||
const documents_1 = require("../../core/documents");
|
||||
const language_service_1 = require("./language-service");
|
||||
const PREFIX = '__ {';
|
||||
const SUFFIX = '}';
|
||||
class StyleAttributeDocument extends documents_1.ReadableDocument {
|
||||
constructor(parent, attrStart, attrEnd) {
|
||||
super();
|
||||
this.parent = parent;
|
||||
this.attrStart = attrStart;
|
||||
this.attrEnd = attrEnd;
|
||||
this.version = this.parent.version;
|
||||
this.languageId = 'css';
|
||||
this.stylesheet = (0, language_service_1.getLanguageService)(this.languageId).parseStylesheet(this);
|
||||
}
|
||||
/**
|
||||
* Get the fragment position relative to the parent
|
||||
* @param pos Position in fragment
|
||||
*/
|
||||
getOriginalPosition(pos) {
|
||||
const parentOffset = this.attrStart + this.offsetAt(pos) - PREFIX.length;
|
||||
return this.parent.positionAt(parentOffset);
|
||||
}
|
||||
/**
|
||||
* Get the position relative to the start of the fragment
|
||||
* @param pos Position in parent
|
||||
*/
|
||||
getGeneratedPosition(pos) {
|
||||
const fragmentOffset = this.parent.offsetAt(pos) - this.attrStart + PREFIX.length;
|
||||
return this.positionAt(fragmentOffset);
|
||||
}
|
||||
/**
|
||||
* Returns true if the given parent position is inside of this fragment
|
||||
* @param pos Position in parent
|
||||
*/
|
||||
isInGenerated(pos) {
|
||||
const offset = this.parent.offsetAt(pos);
|
||||
return offset >= this.attrStart && offset <= this.attrEnd;
|
||||
}
|
||||
/**
|
||||
* Get the fragment text from the parent
|
||||
*/
|
||||
getText() {
|
||||
return PREFIX + this.parent.getText().slice(this.attrStart, this.attrEnd) + SUFFIX;
|
||||
}
|
||||
/**
|
||||
* Returns the length of the fragment as calculated from the start and end position
|
||||
*/
|
||||
getTextLength() {
|
||||
return PREFIX.length + this.attrEnd - this.attrStart + SUFFIX.length;
|
||||
}
|
||||
/**
|
||||
* Return the parent file path
|
||||
*/
|
||||
getFilePath() {
|
||||
return this.parent.getFilePath();
|
||||
}
|
||||
getURL() {
|
||||
return this.parent.getURL();
|
||||
}
|
||||
}
|
||||
exports.StyleAttributeDocument = StyleAttributeDocument;
|
||||
2
node_modules/@astrojs/language-server/dist/plugins/css/features/astro-selectors.d.ts
generated
vendored
Normal file
2
node_modules/@astrojs/language-server/dist/plugins/css/features/astro-selectors.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
import type { IPseudoClassData } from 'vscode-css-languageservice';
|
||||
export declare const pseudoClass: IPseudoClassData[];
|
||||
15
node_modules/@astrojs/language-server/dist/plugins/css/features/astro-selectors.js
generated
vendored
Normal file
15
node_modules/@astrojs/language-server/dist/plugins/css/features/astro-selectors.js
generated
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.pseudoClass = void 0;
|
||||
exports.pseudoClass = [
|
||||
{
|
||||
name: ':global()',
|
||||
description: 'Apply styles to a selector globally',
|
||||
references: [
|
||||
{
|
||||
name: 'Astro documentation',
|
||||
url: 'https://docs.astro.build/en/guides/styling/#global-styles-within-style-tag',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
19
node_modules/@astrojs/language-server/dist/plugins/css/features/getIdClassCompletions.d.ts
generated
vendored
Normal file
19
node_modules/@astrojs/language-server/dist/plugins/css/features/getIdClassCompletions.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import type { Stylesheet } from 'vscode-css-languageservice';
|
||||
import { CompletionItem, CompletionList } from 'vscode-languageserver';
|
||||
import type { AttributeContext } from '../../../core/documents/parseHtml';
|
||||
export declare function getIdClassCompletion(stylesheets: Stylesheet[], attributeContext: AttributeContext): CompletionList | null;
|
||||
/**
|
||||
* incomplete see
|
||||
* https://github.com/microsoft/vscode-css-languageservice/blob/master/src/parser/cssNodes.ts#L14
|
||||
* The enum is not exported. we have to update this whenever it changes
|
||||
*/
|
||||
export declare enum NodeType {
|
||||
ClassSelector = 14,
|
||||
IdentifierSelector = 15
|
||||
}
|
||||
export type CSSNode = {
|
||||
type: number;
|
||||
children: CSSNode[] | undefined;
|
||||
getText(): string;
|
||||
};
|
||||
export declare function collectSelectors(stylesheets: CSSNode[], type: number): CompletionItem[];
|
||||
57
node_modules/@astrojs/language-server/dist/plugins/css/features/getIdClassCompletions.js
generated
vendored
Normal file
57
node_modules/@astrojs/language-server/dist/plugins/css/features/getIdClassCompletions.js
generated
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.collectSelectors = exports.NodeType = exports.getIdClassCompletion = void 0;
|
||||
const vscode_languageserver_1 = require("vscode-languageserver");
|
||||
function getIdClassCompletion(stylesheets, attributeContext) {
|
||||
const collectingType = getCollectingType(attributeContext);
|
||||
if (!collectingType) {
|
||||
return null;
|
||||
}
|
||||
const items = collectSelectors(stylesheets, collectingType);
|
||||
return vscode_languageserver_1.CompletionList.create(items);
|
||||
}
|
||||
exports.getIdClassCompletion = getIdClassCompletion;
|
||||
function getCollectingType(attributeContext) {
|
||||
if (attributeContext.inValue) {
|
||||
if (attributeContext.name === 'class') {
|
||||
return NodeType.ClassSelector;
|
||||
}
|
||||
if (attributeContext.name === 'id') {
|
||||
return NodeType.IdentifierSelector;
|
||||
}
|
||||
}
|
||||
else if (attributeContext.name.startsWith('class:')) {
|
||||
return NodeType.ClassSelector;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* incomplete see
|
||||
* https://github.com/microsoft/vscode-css-languageservice/blob/master/src/parser/cssNodes.ts#L14
|
||||
* The enum is not exported. we have to update this whenever it changes
|
||||
*/
|
||||
var NodeType;
|
||||
(function (NodeType) {
|
||||
NodeType[NodeType["ClassSelector"] = 14] = "ClassSelector";
|
||||
NodeType[NodeType["IdentifierSelector"] = 15] = "IdentifierSelector";
|
||||
})(NodeType = exports.NodeType || (exports.NodeType = {}));
|
||||
function collectSelectors(stylesheets, type) {
|
||||
const result = [];
|
||||
stylesheets.forEach((stylesheet) => {
|
||||
walk(stylesheet, (node) => {
|
||||
if (node.type === type) {
|
||||
result.push(node);
|
||||
}
|
||||
});
|
||||
});
|
||||
return result.map((node) => ({
|
||||
label: node.getText().substring(1),
|
||||
kind: vscode_languageserver_1.CompletionItemKind.Keyword,
|
||||
}));
|
||||
}
|
||||
exports.collectSelectors = collectSelectors;
|
||||
function walk(node, callback) {
|
||||
callback(node);
|
||||
if (node.children) {
|
||||
node.children.forEach((childrenNode) => walk(childrenNode, callback));
|
||||
}
|
||||
}
|
||||
3
node_modules/@astrojs/language-server/dist/plugins/css/language-service.d.ts
generated
vendored
Normal file
3
node_modules/@astrojs/language-server/dist/plugins/css/language-service.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import { LanguageService } from 'vscode-css-languageservice';
|
||||
export declare function getLanguage(kind?: string): "css" | "less" | "scss";
|
||||
export declare function getLanguageService(kind?: string): LanguageService;
|
||||
47
node_modules/@astrojs/language-server/dist/plugins/css/language-service.js
generated
vendored
Normal file
47
node_modules/@astrojs/language-server/dist/plugins/css/language-service.js
generated
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getLanguageService = exports.getLanguage = void 0;
|
||||
const vscode_css_languageservice_1 = require("vscode-css-languageservice");
|
||||
const astro_selectors_1 = require("./features/astro-selectors");
|
||||
const customDataProvider = {
|
||||
providePseudoClasses() {
|
||||
return astro_selectors_1.pseudoClass;
|
||||
},
|
||||
provideProperties() {
|
||||
return [];
|
||||
},
|
||||
provideAtDirectives() {
|
||||
return [];
|
||||
},
|
||||
providePseudoElements() {
|
||||
return [];
|
||||
},
|
||||
};
|
||||
const [css, scss, less] = [vscode_css_languageservice_1.getCSSLanguageService, vscode_css_languageservice_1.getSCSSLanguageService, vscode_css_languageservice_1.getLESSLanguageService].map((getService) => getService({
|
||||
customDataProviders: [customDataProvider],
|
||||
}));
|
||||
const langs = {
|
||||
css,
|
||||
scss,
|
||||
less,
|
||||
};
|
||||
function getLanguage(kind) {
|
||||
switch (kind) {
|
||||
case 'scss':
|
||||
case 'text/scss':
|
||||
return 'scss';
|
||||
case 'less':
|
||||
case 'text/less':
|
||||
return 'less';
|
||||
case 'css':
|
||||
case 'text/css':
|
||||
default:
|
||||
return 'css';
|
||||
}
|
||||
}
|
||||
exports.getLanguage = getLanguage;
|
||||
function getLanguageService(kind) {
|
||||
const lang = getLanguage(kind);
|
||||
return langs[lang];
|
||||
}
|
||||
exports.getLanguageService = getLanguageService;
|
||||
33
node_modules/@astrojs/language-server/dist/plugins/html/HTMLPlugin.d.ts
generated
vendored
Normal file
33
node_modules/@astrojs/language-server/dist/plugins/html/HTMLPlugin.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import { CompletionList, FoldingRange, Hover, LinkedEditingRanges, Position, Range, SymbolInformation, WorkspaceEdit } from 'vscode-languageserver';
|
||||
import type { ConfigManager } from '../../core/config/ConfigManager';
|
||||
import type { AstroDocument } from '../../core/documents/AstroDocument';
|
||||
import type { Plugin } from '../interfaces';
|
||||
export declare class HTMLPlugin implements Plugin {
|
||||
__name: string;
|
||||
private lang;
|
||||
private attributeOnlyLang;
|
||||
private componentLang;
|
||||
private styleScriptTemplate;
|
||||
private configManager;
|
||||
constructor(configManager: ConfigManager);
|
||||
doHover(document: AstroDocument, position: Position): Promise<Hover | null>;
|
||||
/**
|
||||
* Get HTML completions
|
||||
*/
|
||||
getCompletions(document: AstroDocument, position: Position): Promise<CompletionList | null>;
|
||||
getFoldingRanges(document: AstroDocument): FoldingRange[] | null;
|
||||
getLinkedEditingRanges(document: AstroDocument, position: Position): LinkedEditingRanges | null;
|
||||
doTagComplete(document: AstroDocument, position: Position): Promise<string | null>;
|
||||
prepareRename(document: AstroDocument, position: Position): Range | null;
|
||||
rename(document: AstroDocument, position: Position, newName: string): WorkspaceEdit | null;
|
||||
getDocumentSymbols(document: AstroDocument): Promise<SymbolInformation[]>;
|
||||
/**
|
||||
* Get lang completions for style tags (ex: `<style lang="scss">`)
|
||||
*/
|
||||
private getLangCompletions;
|
||||
/**
|
||||
* Returns true if rename happens at the tag name, not anywhere inbetween.
|
||||
*/
|
||||
private isRenameAtTag;
|
||||
private featureEnabled;
|
||||
}
|
||||
198
node_modules/@astrojs/language-server/dist/plugins/html/HTMLPlugin.js
generated
vendored
Normal file
198
node_modules/@astrojs/language-server/dist/plugins/html/HTMLPlugin.js
generated
vendored
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.HTMLPlugin = void 0;
|
||||
const emmet_helper_1 = require("@vscode/emmet-helper");
|
||||
const vscode_html_languageservice_1 = require("vscode-html-languageservice");
|
||||
const vscode_languageserver_1 = require("vscode-languageserver");
|
||||
const utils_1 = require("../../core/documents/utils");
|
||||
const astro_attributes_1 = require("./features/astro-attributes");
|
||||
const utils_2 = require("./utils");
|
||||
class HTMLPlugin {
|
||||
constructor(configManager) {
|
||||
this.__name = 'html';
|
||||
this.lang = (0, vscode_html_languageservice_1.getLanguageService)({
|
||||
customDataProviders: [astro_attributes_1.astroAttributes, astro_attributes_1.astroElements, astro_attributes_1.classListAttribute],
|
||||
});
|
||||
this.attributeOnlyLang = (0, vscode_html_languageservice_1.getLanguageService)({
|
||||
customDataProviders: [astro_attributes_1.astroAttributes],
|
||||
useDefaultDataProvider: false,
|
||||
});
|
||||
this.componentLang = (0, vscode_html_languageservice_1.getLanguageService)({
|
||||
customDataProviders: [astro_attributes_1.astroAttributes, astro_attributes_1.astroDirectives],
|
||||
useDefaultDataProvider: false,
|
||||
});
|
||||
this.styleScriptTemplate = new Set(['style']);
|
||||
this.configManager = configManager;
|
||||
}
|
||||
async doHover(document, position) {
|
||||
if (!(await this.featureEnabled(document, 'hover'))) {
|
||||
return null;
|
||||
}
|
||||
const html = document.html;
|
||||
if (!html) {
|
||||
return null;
|
||||
}
|
||||
const node = html.findNodeAt(document.offsetAt(position));
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
// If the node we're hovering on is a component, instead only provide astro-specific hover info
|
||||
if ((0, utils_1.isPossibleComponent)(node) && node.tag !== 'Fragment') {
|
||||
return this.componentLang.doHover(document, position, html);
|
||||
}
|
||||
return this.lang.doHover(document, position, html);
|
||||
}
|
||||
/**
|
||||
* Get HTML completions
|
||||
*/
|
||||
async getCompletions(document, position) {
|
||||
if (!(await this.featureEnabled(document, 'completions'))) {
|
||||
return null;
|
||||
}
|
||||
const html = document.html;
|
||||
const offset = document.offsetAt(position);
|
||||
if (!html ||
|
||||
(0, utils_1.isInsideFrontmatter)(document.getText(), offset) ||
|
||||
(0, utils_1.isInsideExpression)(document.getText(), html.findNodeAt(offset).start, offset)) {
|
||||
return null;
|
||||
}
|
||||
// Get Emmet completions
|
||||
let emmetResults = {
|
||||
isIncomplete: true,
|
||||
items: [],
|
||||
};
|
||||
const emmetConfig = await this.configManager.getEmmetConfig(document);
|
||||
const extensionConfig = (await this.configManager.getConfig('astro', document.uri)) ?? {};
|
||||
if (extensionConfig?.html?.completions?.emmet ?? true) {
|
||||
this.lang.setCompletionParticipants([
|
||||
{
|
||||
onHtmlContent: () => (emmetResults = (0, emmet_helper_1.doComplete)(document, position, 'html', emmetConfig) || emmetResults),
|
||||
},
|
||||
]);
|
||||
}
|
||||
// If we're in a component starting tag, we do not want HTML language completions
|
||||
// as HTML attributes are not valid for components
|
||||
const inComponentTag = (0, utils_1.isInComponentStartTag)(html, offset);
|
||||
const inTagName = (0, utils_1.isInTagName)(html, offset);
|
||||
const results = inComponentTag && !inTagName
|
||||
? (0, utils_2.removeDataAttrCompletion)(this.attributeOnlyLang.doComplete(document, position, html).items)
|
||||
: this.lang.doComplete(document, position, html).items.filter(isNoAddedTagWithNoDocumentation);
|
||||
const langCompletions = inComponentTag ? [] : this.getLangCompletions(results);
|
||||
return vscode_languageserver_1.CompletionList.create([...results, ...langCompletions, ...emmetResults.items],
|
||||
// Emmet completions change on every keystroke, so they are never complete
|
||||
emmetResults.items.length > 0);
|
||||
// Filter script and style completions with no documentation to prevent duplicates
|
||||
// due to our added definitions for those tags
|
||||
function isNoAddedTagWithNoDocumentation(item) {
|
||||
return !(['script', 'style'].includes(item.label) && item.documentation === undefined);
|
||||
}
|
||||
}
|
||||
getFoldingRanges(document) {
|
||||
const html = document.html;
|
||||
if (!html) {
|
||||
return null;
|
||||
}
|
||||
return this.lang.getFoldingRanges(document);
|
||||
}
|
||||
getLinkedEditingRanges(document, position) {
|
||||
const html = document.html;
|
||||
if (!html) {
|
||||
return null;
|
||||
}
|
||||
const ranges = this.lang.findLinkedEditingRanges(document, position, html);
|
||||
if (!ranges) {
|
||||
return null;
|
||||
}
|
||||
return { ranges };
|
||||
}
|
||||
async doTagComplete(document, position) {
|
||||
if (!(await this.featureEnabled(document, 'tagComplete'))) {
|
||||
return null;
|
||||
}
|
||||
const html = document.html;
|
||||
const offset = document.offsetAt(position);
|
||||
if (!html ||
|
||||
(0, utils_1.isInsideFrontmatter)(document.getText(), offset) ||
|
||||
(0, utils_1.isInsideExpression)(document.getText(), html.findNodeAt(offset).start, offset)) {
|
||||
return null;
|
||||
}
|
||||
return this.lang.doTagComplete(document, position, html);
|
||||
}
|
||||
prepareRename(document, position) {
|
||||
const html = document.html;
|
||||
const offset = document.offsetAt(position);
|
||||
const node = html.findNodeAt(offset);
|
||||
if (!node || (0, utils_1.isPossibleComponent)(node) || !node.tag || !this.isRenameAtTag(node, offset)) {
|
||||
return null;
|
||||
}
|
||||
const tagNameStart = node.start + '<'.length;
|
||||
return vscode_languageserver_1.Range.create(document.positionAt(tagNameStart), document.positionAt(tagNameStart + node.tag.length));
|
||||
}
|
||||
rename(document, position, newName) {
|
||||
const html = document.html;
|
||||
const offset = document.offsetAt(position);
|
||||
if (!html || (0, utils_1.isInsideFrontmatter)(document.getText(), offset)) {
|
||||
return null;
|
||||
}
|
||||
const node = html.findNodeAt(offset);
|
||||
// The TypeScript plugin handles renaming for components
|
||||
if (!node || (0, utils_1.isPossibleComponent)(node) || !this.isRenameAtTag(node, offset)) {
|
||||
return null;
|
||||
}
|
||||
return this.lang.doRename(document, position, newName, html);
|
||||
}
|
||||
async getDocumentSymbols(document) {
|
||||
if (!(await this.featureEnabled(document, 'documentSymbols'))) {
|
||||
return [];
|
||||
}
|
||||
const html = document.html;
|
||||
if (!html) {
|
||||
return [];
|
||||
}
|
||||
return this.lang.findDocumentSymbols(document, html);
|
||||
}
|
||||
/**
|
||||
* Get lang completions for style tags (ex: `<style lang="scss">`)
|
||||
*/
|
||||
getLangCompletions(completions) {
|
||||
const styleScriptTemplateCompletions = completions.filter((completion) => completion.kind === vscode_languageserver_1.CompletionItemKind.Property && this.styleScriptTemplate.has(completion.label));
|
||||
const langCompletions = [];
|
||||
addLangCompletion('style', ['scss', 'sass', 'less', 'styl', 'stylus']);
|
||||
return langCompletions;
|
||||
/** Add language completions */
|
||||
function addLangCompletion(tag, languages) {
|
||||
const existingCompletion = styleScriptTemplateCompletions.find((completion) => completion.label === tag);
|
||||
if (!existingCompletion) {
|
||||
return;
|
||||
}
|
||||
languages.forEach((lang) => langCompletions.push({
|
||||
...existingCompletion,
|
||||
label: `${tag} (lang="${lang}")`,
|
||||
insertText: existingCompletion.insertText && `${existingCompletion.insertText} lang="${lang}"`,
|
||||
textEdit: existingCompletion.textEdit && vscode_languageserver_1.TextEdit.is(existingCompletion.textEdit)
|
||||
? {
|
||||
range: existingCompletion.textEdit.range,
|
||||
newText: `${existingCompletion.textEdit.newText} lang="${lang}"`,
|
||||
}
|
||||
: undefined,
|
||||
}));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns true if rename happens at the tag name, not anywhere inbetween.
|
||||
*/
|
||||
isRenameAtTag(node, offset) {
|
||||
if (!node.tag) {
|
||||
return false;
|
||||
}
|
||||
const startTagNameEnd = node.start + `<${node.tag}`.length;
|
||||
const isAtStartTag = offset > node.start && offset <= startTagNameEnd;
|
||||
const isAtEndTag = node.endTagStart !== undefined && offset >= node.endTagStart && offset < node.end;
|
||||
return isAtStartTag || isAtEndTag;
|
||||
}
|
||||
async featureEnabled(document, feature) {
|
||||
return ((await this.configManager.isEnabled(document, 'html')) &&
|
||||
(await this.configManager.isEnabled(document, 'html', feature)));
|
||||
}
|
||||
}
|
||||
exports.HTMLPlugin = HTMLPlugin;
|
||||
4
node_modules/@astrojs/language-server/dist/plugins/html/features/astro-attributes.d.ts
generated
vendored
Normal file
4
node_modules/@astrojs/language-server/dist/plugins/html/features/astro-attributes.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
export declare const classListAttribute: import("vscode-html-languageservice").IHTMLDataProvider;
|
||||
export declare const astroElements: import("vscode-html-languageservice").IHTMLDataProvider;
|
||||
export declare const astroAttributes: import("vscode-html-languageservice").IHTMLDataProvider;
|
||||
export declare const astroDirectives: import("vscode-html-languageservice").IHTMLDataProvider;
|
||||
235
node_modules/@astrojs/language-server/dist/plugins/html/features/astro-attributes.js
generated
vendored
Normal file
235
node_modules/@astrojs/language-server/dist/plugins/html/features/astro-attributes.js
generated
vendored
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.astroDirectives = exports.astroAttributes = exports.astroElements = exports.classListAttribute = void 0;
|
||||
const vscode_html_languageservice_1 = require("vscode-html-languageservice");
|
||||
const defaultProvider = (0, vscode_html_languageservice_1.getDefaultHTMLDataProvider)();
|
||||
const slotAttr = defaultProvider.provideAttributes('div').find((attr) => attr.name === 'slot');
|
||||
exports.classListAttribute = (0, vscode_html_languageservice_1.newHTMLDataProvider)('class-list', {
|
||||
version: 1,
|
||||
globalAttributes: [
|
||||
{
|
||||
name: 'class:list',
|
||||
description: 'Utility to provide a list of class',
|
||||
references: [
|
||||
{
|
||||
name: 'Astro reference',
|
||||
url: 'https://docs.astro.build/en/reference/directives-reference/#classlist',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
exports.astroElements = (0, vscode_html_languageservice_1.newHTMLDataProvider)('astro-elements', {
|
||||
version: 1,
|
||||
tags: [
|
||||
{
|
||||
name: 'slot',
|
||||
description: 'The slot element is a placeholder for external HTML content, allowing you to inject (or “slot”) child elements from other files into your component template.',
|
||||
references: [
|
||||
{
|
||||
name: 'Astro reference',
|
||||
url: 'https://docs.astro.build/en/core-concepts/astro-components/#slots',
|
||||
},
|
||||
],
|
||||
attributes: [
|
||||
{
|
||||
name: 'name',
|
||||
description: 'The name attribute allows you to pass only HTML elements with the corresponding slot name into a slot’s location.',
|
||||
references: [
|
||||
{
|
||||
name: 'Astro reference',
|
||||
url: 'https://docs.astro.build/en/core-concepts/astro-components/#named-slots',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'script',
|
||||
attributes: [
|
||||
{
|
||||
// The VS Code tag definitions does not provide a description for the deprecated `charset` attribute on script tags
|
||||
// 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
|
||||
name: 'charset',
|
||||
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.",
|
||||
},
|
||||
{
|
||||
name: 'define:vars',
|
||||
description: 'Passes serializable server-side variables into a client-side script element',
|
||||
references: [
|
||||
{
|
||||
name: 'Astro reference',
|
||||
url: 'https://docs.astro.build/en/reference/directives-reference/#definevars',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'hoist',
|
||||
description: '**Deprecated in Astro >= 0.26.0**\n\nBuilds, optimizes, and bundles your script with the other JavaScript on the page',
|
||||
valueSet: 'v',
|
||||
references: [
|
||||
{
|
||||
name: 'Astro reference',
|
||||
url: 'https://docs.astro.build/en/core-concepts/astro-components/#using-hoisted-scripts',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'is:inline',
|
||||
description: 'Leave a script tag inline in the page template. No processing will be done on its content',
|
||||
valueSet: 'v',
|
||||
references: [
|
||||
{
|
||||
name: 'Astro reference',
|
||||
url: 'https://docs.astro.build/en/reference/directives-reference/#isinline',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'style',
|
||||
attributes: [
|
||||
{
|
||||
name: 'define:vars',
|
||||
description: 'Passes serializable server-side variables into a client-side style element',
|
||||
references: [
|
||||
{
|
||||
name: 'Astro reference',
|
||||
url: 'https://docs.astro.build/en/reference/directives-reference/#definevars',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'global',
|
||||
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',
|
||||
valueSet: 'v',
|
||||
references: [
|
||||
{
|
||||
name: 'Astro reference',
|
||||
url: 'https://docs.astro.build/en/reference/directives-reference/#isglobal',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'is:global',
|
||||
description: 'Opts-out of automatic CSS scoping, all contents will be available globally',
|
||||
valueSet: 'v',
|
||||
references: [
|
||||
{
|
||||
name: 'Astro reference',
|
||||
url: 'https://docs.astro.build/en/reference/directives-reference/#isglobal',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'is:inline',
|
||||
description: 'Leave a style tag inline in the page template. No processing will be done on its content',
|
||||
valueSet: 'v',
|
||||
references: [
|
||||
{
|
||||
name: 'Astro reference',
|
||||
url: 'https://docs.astro.build/en/reference/directives-reference/#isinline',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)('astro-attributes', {
|
||||
version: 1,
|
||||
globalAttributes: [
|
||||
{
|
||||
name: 'set:html',
|
||||
description: 'Inject unescaped HTML into this tag',
|
||||
references: [
|
||||
{
|
||||
name: 'Astro reference',
|
||||
url: 'https://docs.astro.build/en/reference/directives-reference/#sethtml',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'set:text',
|
||||
description: 'Inject escaped text into this tag',
|
||||
references: [
|
||||
{
|
||||
name: 'Astro reference',
|
||||
url: 'https://docs.astro.build/en/reference/directives-reference/#settext',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'is:raw',
|
||||
description: 'Instructs the Astro compiler to treat any children of this element as text',
|
||||
valueSet: 'v',
|
||||
references: [
|
||||
{
|
||||
name: 'Astro reference',
|
||||
url: 'https://docs.astro.build/en/reference/directives-reference/#israw',
|
||||
},
|
||||
],
|
||||
},
|
||||
slotAttr,
|
||||
],
|
||||
});
|
||||
exports.astroDirectives = (0, vscode_html_languageservice_1.newHTMLDataProvider)('astro-directives', {
|
||||
version: 1,
|
||||
globalAttributes: [
|
||||
{
|
||||
name: 'client:load',
|
||||
description: 'Start importing the component JS at page load. Hydrate the component when import completes.',
|
||||
valueSet: 'v',
|
||||
references: [
|
||||
{
|
||||
name: 'Astro reference',
|
||||
url: 'https://docs.astro.build/en/reference/directives-reference/#clientload',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'client:idle',
|
||||
description: 'Start importing the component JS as soon as main thread is free (uses requestIdleCallback()). Hydrate the component when import completes.',
|
||||
valueSet: 'v',
|
||||
references: [
|
||||
{
|
||||
name: 'Astro reference',
|
||||
url: 'https://docs.astro.build/en/reference/directives-reference/#clientidle',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'client:visible',
|
||||
description: 'Start importing the component JS as soon as the element enters the viewport (uses IntersectionObserver). Hydrate the component when import completes. Useful for content lower down on the page.',
|
||||
valueSet: 'v',
|
||||
references: [
|
||||
{
|
||||
name: 'Astro reference',
|
||||
url: 'https://docs.astro.build/en/reference/directives-reference/#clientvisible',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'client:media',
|
||||
description: 'Start importing the component JS as soon as the browser matches the given media query (uses matchMedia). Hydrate the component when import completes. Useful for sidebar toggles, or other elements that should only display on mobile or desktop devices.',
|
||||
references: [
|
||||
{
|
||||
name: 'Astro reference',
|
||||
url: 'https://docs.astro.build/en/reference/directives-reference/#clientmedia',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'client:only',
|
||||
description: 'Start importing the component JS at page load and hydrate when the import completes, similar to client:load. The component will be skipped at build time, useful for components that are entirely dependent on client-side APIs. This is best avoided unless absolutely needed, in most cases it is best to render placeholder content on the server and delay any browser API calls until the component hydrates in the browser.',
|
||||
valueSet: 'v',
|
||||
references: [
|
||||
{
|
||||
name: 'Astro reference',
|
||||
url: 'https://docs.astro.build/en/reference/directives-reference/#clientonly',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
6
node_modules/@astrojs/language-server/dist/plugins/html/utils.d.ts
generated
vendored
Normal file
6
node_modules/@astrojs/language-server/dist/plugins/html/utils.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import type { CompletionItem } from 'vscode-languageserver-types';
|
||||
/**
|
||||
* The VS Code HTML language service provides a completion for data attributes that is independent from
|
||||
* data providers, which mean that you can't disable it, so this function removes them from completions
|
||||
*/
|
||||
export declare function removeDataAttrCompletion(items: CompletionItem[]): CompletionItem[];
|
||||
11
node_modules/@astrojs/language-server/dist/plugins/html/utils.js
generated
vendored
Normal file
11
node_modules/@astrojs/language-server/dist/plugins/html/utils.js
generated
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.removeDataAttrCompletion = void 0;
|
||||
/**
|
||||
* The VS Code HTML language service provides a completion for data attributes that is independent from
|
||||
* data providers, which mean that you can't disable it, so this function removes them from completions
|
||||
*/
|
||||
function removeDataAttrCompletion(items) {
|
||||
return items.filter((item) => !item.label.startsWith('data-'));
|
||||
}
|
||||
exports.removeDataAttrCompletion = removeDataAttrCompletion;
|
||||
6
node_modules/@astrojs/language-server/dist/plugins/index.d.ts
generated
vendored
Normal file
6
node_modules/@astrojs/language-server/dist/plugins/index.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
export * from './astro/AstroPlugin';
|
||||
export * from './css/CSSPlugin';
|
||||
export * from './html/HTMLPlugin';
|
||||
export * from './interfaces';
|
||||
export * from './PluginHost';
|
||||
export * from './typescript/TypeScriptPlugin';
|
||||
22
node_modules/@astrojs/language-server/dist/plugins/index.js
generated
vendored
Normal file
22
node_modules/@astrojs/language-server/dist/plugins/index.js
generated
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
__exportStar(require("./astro/AstroPlugin"), exports);
|
||||
__exportStar(require("./css/CSSPlugin"), exports);
|
||||
__exportStar(require("./html/HTMLPlugin"), exports);
|
||||
__exportStar(require("./interfaces"), exports);
|
||||
__exportStar(require("./PluginHost"), exports);
|
||||
__exportStar(require("./typescript/TypeScriptPlugin"), exports);
|
||||
101
node_modules/@astrojs/language-server/dist/plugins/interfaces.d.ts
generated
vendored
Normal file
101
node_modules/@astrojs/language-server/dist/plugins/interfaces.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
import type { CodeAction, CodeActionContext, Color, ColorInformation, ColorPresentation, CompletionContext, CompletionItem, CompletionList, DefinitionLink, Diagnostic, FileChangeType, FoldingRange, FormattingOptions, Hover, InlayHint, LinkedEditingRanges, Location, Position, Range, ReferenceContext, SelectionRange, SemanticTokens, SignatureHelp, SignatureHelpContext, SymbolInformation, TextDocumentContentChangeEvent, TextDocumentIdentifier, TextEdit, WorkspaceEdit } from 'vscode-languageserver';
|
||||
import type { TextDocument } from 'vscode-languageserver-textdocument';
|
||||
export type Resolvable<T> = T | Promise<T>;
|
||||
export interface AppCompletionItem<T extends TextDocumentIdentifier = any> extends CompletionItem {
|
||||
data?: T;
|
||||
}
|
||||
export interface AppCompletionList<T extends TextDocumentIdentifier = any> extends CompletionList {
|
||||
items: Array<AppCompletionItem<T>>;
|
||||
}
|
||||
export interface DiagnosticsProvider {
|
||||
getDiagnostics(document: TextDocument): Resolvable<Diagnostic[]>;
|
||||
}
|
||||
export interface HoverProvider {
|
||||
doHover(document: TextDocument, position: Position): Resolvable<Hover | null>;
|
||||
}
|
||||
export interface FoldingRangesProvider {
|
||||
getFoldingRanges(document: TextDocument): Resolvable<FoldingRange[] | null>;
|
||||
}
|
||||
export interface CompletionsProvider<T extends TextDocumentIdentifier = any> {
|
||||
getCompletions(document: TextDocument, position: Position, completionContext?: CompletionContext): Resolvable<AppCompletionList<T> | null>;
|
||||
resolveCompletion?(document: TextDocument, completionItem: AppCompletionItem<T>): Resolvable<AppCompletionItem<T>>;
|
||||
}
|
||||
export interface FormattingProvider {
|
||||
formatDocument(document: TextDocument, options: FormattingOptions): Resolvable<TextEdit[]>;
|
||||
}
|
||||
export interface TagCompleteProvider {
|
||||
doTagComplete(document: TextDocument, position: Position): Resolvable<string | null>;
|
||||
}
|
||||
export interface DocumentColorsProvider {
|
||||
getDocumentColors(document: TextDocument): Resolvable<ColorInformation[]>;
|
||||
}
|
||||
export interface ColorPresentationsProvider {
|
||||
getColorPresentations(document: TextDocument, range: Range, color: Color): Resolvable<ColorPresentation[]>;
|
||||
}
|
||||
export interface DocumentSymbolsProvider {
|
||||
getDocumentSymbols(document: TextDocument): Resolvable<SymbolInformation[]>;
|
||||
}
|
||||
export interface FileReferencesProvider {
|
||||
fileReferences(document: TextDocument): Promise<Location[] | null>;
|
||||
}
|
||||
export interface DefinitionsProvider {
|
||||
getDefinitions(document: TextDocument, position: Position): Resolvable<DefinitionLink[]>;
|
||||
}
|
||||
export interface BackwardsCompatibleDefinitionsProvider {
|
||||
getDefinitions(document: TextDocument, position: Position): Resolvable<DefinitionLink[] | Location[]>;
|
||||
}
|
||||
export interface CodeActionsProvider {
|
||||
getCodeActions(document: TextDocument, range: Range, context: CodeActionContext): Resolvable<CodeAction[]>;
|
||||
executeCommand?(document: TextDocument, command: string, args?: any[]): Resolvable<WorkspaceEdit | string | null>;
|
||||
}
|
||||
export interface FileRename {
|
||||
oldUri: string;
|
||||
newUri: string;
|
||||
}
|
||||
export interface UpdateImportsProvider {
|
||||
updateImports(fileRename: FileRename): Resolvable<WorkspaceEdit | null>;
|
||||
}
|
||||
export interface InlayHintsProvider {
|
||||
getInlayHints(document: TextDocument, range: Range): Resolvable<InlayHint[]>;
|
||||
}
|
||||
export interface RenameProvider {
|
||||
rename(document: TextDocument, position: Position, newName: string): Resolvable<WorkspaceEdit | null>;
|
||||
prepareRename(document: TextDocument, position: Position): Resolvable<Range | null>;
|
||||
}
|
||||
export interface FindReferencesProvider {
|
||||
findReferences(document: TextDocument, position: Position, context: ReferenceContext): Promise<Location[] | null>;
|
||||
}
|
||||
export interface SignatureHelpProvider {
|
||||
getSignatureHelp(document: TextDocument, position: Position, context: SignatureHelpContext | undefined): Resolvable<SignatureHelp | null>;
|
||||
}
|
||||
export interface SelectionRangeProvider {
|
||||
getSelectionRange(document: TextDocument, position: Position): Resolvable<SelectionRange | null>;
|
||||
}
|
||||
export interface SemanticTokensProvider {
|
||||
getSemanticTokens(textDocument: TextDocument, range?: Range): Resolvable<SemanticTokens | null>;
|
||||
}
|
||||
export interface LinkedEditingRangesProvider {
|
||||
getLinkedEditingRanges(document: TextDocument, position: Position): Resolvable<LinkedEditingRanges | null>;
|
||||
}
|
||||
export interface ImplementationProvider {
|
||||
getImplementation(document: TextDocument, position: Position): Resolvable<Location[] | null>;
|
||||
}
|
||||
export interface TypeDefinitionsProvider {
|
||||
getTypeDefinitions(document: TextDocument, position: Position): Resolvable<Location[] | null>;
|
||||
}
|
||||
export interface OnWatchFileChangesParam {
|
||||
fileName: string;
|
||||
changeType: FileChangeType;
|
||||
}
|
||||
export interface OnWatchFileChangesProvider {
|
||||
onWatchFileChanges(onWatchFileChangesParams: OnWatchFileChangesParam[]): Promise<void>;
|
||||
}
|
||||
export interface UpdateNonAstroFile {
|
||||
updateNonAstroFile(fileName: string, changes: TextDocumentContentChangeEvent[], text?: string): void;
|
||||
}
|
||||
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;
|
||||
export type LSProvider = ProviderBase;
|
||||
export type Plugin = Partial<ProviderBase> & {
|
||||
__name: string;
|
||||
};
|
||||
export {};
|
||||
2
node_modules/@astrojs/language-server/dist/plugins/interfaces.js
generated
vendored
Normal file
2
node_modules/@astrojs/language-server/dist/plugins/interfaces.js
generated
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
47
node_modules/@astrojs/language-server/dist/plugins/typescript/LanguageServiceManager.d.ts
generated
vendored
Normal file
47
node_modules/@astrojs/language-server/dist/plugins/typescript/LanguageServiceManager.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
import type ts from 'typescript';
|
||||
import type { TextDocumentContentChangeEvent } from 'vscode-languageserver';
|
||||
import type { ConfigManager } from '../../core/config';
|
||||
import type { AstroDocument, DocumentManager } from '../../core/documents';
|
||||
import { LanguageServiceContainer, LanguageServiceDocumentContext } from './language-service';
|
||||
import type { DocumentSnapshot } from './snapshots/DocumentSnapshot';
|
||||
import { SnapshotManager } from './snapshots/SnapshotManager';
|
||||
export declare class LanguageServiceManager {
|
||||
private readonly docManager;
|
||||
private readonly workspaceUris;
|
||||
private readonly configManager;
|
||||
docContext: LanguageServiceDocumentContext;
|
||||
private globalSnapshotManager;
|
||||
constructor(docManager: DocumentManager, workspaceUris: string[], configManager: ConfigManager, ts: typeof import('typescript/lib/tsserverlibrary'), tsLocalized?: Record<string, string> | undefined);
|
||||
/**
|
||||
* Create an AstroDocument (only for astro files)
|
||||
*/
|
||||
private createDocument;
|
||||
getSnapshot(document: AstroDocument): Promise<DocumentSnapshot>;
|
||||
getSnapshot(pathOrDoc: string | AstroDocument): Promise<DocumentSnapshot>;
|
||||
/**
|
||||
* Updates snapshot path in all existing ts services and retrieves snapshot
|
||||
*/
|
||||
updateSnapshotPath(oldPath: string, newPath: string): Promise<DocumentSnapshot>;
|
||||
/**
|
||||
* Deletes snapshot in all existing ts services
|
||||
*/
|
||||
deleteSnapshot(filePath: string): Promise<void>;
|
||||
/**
|
||||
* Updates project files in all existing ts services
|
||||
*/
|
||||
updateProjectFiles(): Promise<void>;
|
||||
/**
|
||||
* Updates file in all ts services where it exists
|
||||
*/
|
||||
updateExistingNonAstroFile(path: string, changes?: TextDocumentContentChangeEvent[], text?: string): Promise<void>;
|
||||
getLSAndTSDoc(document: AstroDocument): Promise<{
|
||||
tsDoc: DocumentSnapshot;
|
||||
lang: ts.LanguageService;
|
||||
}>;
|
||||
getLSForPath(path: string): Promise<ts.LanguageService>;
|
||||
getTypeScriptLanguageService(filePath: string): Promise<LanguageServiceContainer>;
|
||||
/**
|
||||
* @internal Public for tests only
|
||||
*/
|
||||
getSnapshotManager(filePath: string): Promise<SnapshotManager>;
|
||||
}
|
||||
97
node_modules/@astrojs/language-server/dist/plugins/typescript/LanguageServiceManager.js
generated
vendored
Normal file
97
node_modules/@astrojs/language-server/dist/plugins/typescript/LanguageServiceManager.js
generated
vendored
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.LanguageServiceManager = void 0;
|
||||
const utils_1 = require("../../utils");
|
||||
const language_service_1 = require("./language-service");
|
||||
const SnapshotManager_1 = require("./snapshots/SnapshotManager");
|
||||
class LanguageServiceManager {
|
||||
constructor(docManager, workspaceUris, configManager, ts, tsLocalized) {
|
||||
this.docManager = docManager;
|
||||
this.workspaceUris = workspaceUris;
|
||||
this.configManager = configManager;
|
||||
/**
|
||||
* Create an AstroDocument (only for astro files)
|
||||
*/
|
||||
this.createDocument = (fileName, content) => {
|
||||
const uri = (0, utils_1.pathToUrl)(fileName);
|
||||
const document = this.docManager.openDocument({
|
||||
text: content,
|
||||
uri,
|
||||
});
|
||||
this.docManager.lockDocument(uri);
|
||||
return document;
|
||||
};
|
||||
this.globalSnapshotManager = new SnapshotManager_1.GlobalSnapshotManager(ts);
|
||||
this.docContext = {
|
||||
createDocument: this.createDocument,
|
||||
globalSnapshotManager: this.globalSnapshotManager,
|
||||
configManager: this.configManager,
|
||||
ts,
|
||||
tsLocalized: tsLocalized,
|
||||
};
|
||||
const handleDocumentChange = (document) => {
|
||||
this.getSnapshot(document);
|
||||
};
|
||||
docManager.on('documentChange', (0, utils_1.debounceSameArg)(handleDocumentChange, (newDoc, prevDoc) => newDoc.uri === prevDoc?.uri, 1000));
|
||||
docManager.on('documentOpen', handleDocumentChange);
|
||||
}
|
||||
async getSnapshot(pathOrDoc) {
|
||||
const filePath = typeof pathOrDoc === 'string' ? pathOrDoc : pathOrDoc.getFilePath() || '';
|
||||
const tsService = await this.getTypeScriptLanguageService(filePath);
|
||||
return tsService.updateSnapshot(pathOrDoc, this.docContext.ts);
|
||||
}
|
||||
/**
|
||||
* Updates snapshot path in all existing ts services and retrieves snapshot
|
||||
*/
|
||||
async updateSnapshotPath(oldPath, newPath) {
|
||||
await this.deleteSnapshot(oldPath);
|
||||
return this.getSnapshot(newPath);
|
||||
}
|
||||
/**
|
||||
* Deletes snapshot in all existing ts services
|
||||
*/
|
||||
async deleteSnapshot(filePath) {
|
||||
await (0, language_service_1.forAllLanguageServices)((service) => service.deleteSnapshot(filePath));
|
||||
this.docManager.releaseDocument((0, utils_1.pathToUrl)(filePath));
|
||||
}
|
||||
/**
|
||||
* Updates project files in all existing ts services
|
||||
*/
|
||||
async updateProjectFiles() {
|
||||
await (0, language_service_1.forAllLanguageServices)((service) => service.updateProjectFiles());
|
||||
}
|
||||
/**
|
||||
* Updates file in all ts services where it exists
|
||||
*/
|
||||
async updateExistingNonAstroFile(path, changes, text) {
|
||||
path = (0, utils_1.normalizePath)(path);
|
||||
// Only update once because all snapshots are shared between
|
||||
// services. Since we don't have a current version of TS/JS
|
||||
// files, the operation wouldn't be idempotent.
|
||||
let didUpdate = false;
|
||||
await (0, language_service_1.forAllLanguageServices)((service) => {
|
||||
if (service.hasFile(path) && !didUpdate) {
|
||||
didUpdate = true;
|
||||
service.updateNonAstroFile(path, changes, text);
|
||||
}
|
||||
});
|
||||
}
|
||||
async getLSAndTSDoc(document) {
|
||||
const lang = await this.getLSForPath(document.getFilePath() || '');
|
||||
const tsDoc = await this.getSnapshot(document);
|
||||
return { tsDoc, lang };
|
||||
}
|
||||
async getLSForPath(path) {
|
||||
return (await this.getTypeScriptLanguageService(path)).getService();
|
||||
}
|
||||
async getTypeScriptLanguageService(filePath) {
|
||||
return (0, language_service_1.getLanguageService)(filePath, this.workspaceUris, this.docContext);
|
||||
}
|
||||
/**
|
||||
* @internal Public for tests only
|
||||
*/
|
||||
async getSnapshotManager(filePath) {
|
||||
return (await this.getTypeScriptLanguageService(filePath)).snapshotManager;
|
||||
}
|
||||
}
|
||||
exports.LanguageServiceManager = LanguageServiceManager;
|
||||
54
node_modules/@astrojs/language-server/dist/plugins/typescript/TypeScriptPlugin.d.ts
generated
vendored
Normal file
54
node_modules/@astrojs/language-server/dist/plugins/typescript/TypeScriptPlugin.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
import type { TSXResult } from '@astrojs/compiler/types';
|
||||
import { CancellationToken, CodeAction, CodeActionContext, CompletionContext, DefinitionLink, Diagnostic, FoldingRange, Hover, InlayHint, Location, Position, Range, ReferenceContext, SemanticTokens, SignatureHelp, SignatureHelpContext, SymbolInformation, TextDocumentContentChangeEvent, WorkspaceEdit } from 'vscode-languageserver';
|
||||
import type { ConfigManager } from '../../core/config';
|
||||
import type { AstroDocument } from '../../core/documents';
|
||||
import type { AppCompletionItem, AppCompletionList, OnWatchFileChangesParam, Plugin } from '../interfaces';
|
||||
import { CompletionItemData } from './features/CompletionsProvider';
|
||||
import type { LanguageServiceManager } from './LanguageServiceManager';
|
||||
export declare class TypeScriptPlugin implements Plugin {
|
||||
__name: string;
|
||||
private configManager;
|
||||
private readonly languageServiceManager;
|
||||
private readonly codeActionsProvider;
|
||||
private readonly completionProvider;
|
||||
private readonly hoverProvider;
|
||||
private readonly fileReferencesProvider;
|
||||
private readonly definitionsProvider;
|
||||
private readonly typeDefinitionsProvider;
|
||||
private readonly implementationsProvider;
|
||||
private readonly referencesProvider;
|
||||
private readonly signatureHelpProvider;
|
||||
private readonly diagnosticsProvider;
|
||||
private readonly documentSymbolsProvider;
|
||||
private readonly inlayHintsProvider;
|
||||
private readonly semanticTokensProvider;
|
||||
private readonly foldingRangesProvider;
|
||||
private readonly renameProvider;
|
||||
private readonly ts;
|
||||
constructor(configManager: ConfigManager, languageServiceManager: LanguageServiceManager);
|
||||
doHover(document: AstroDocument, position: Position): Promise<Hover | null>;
|
||||
prepareRename(document: AstroDocument, position: Position): Promise<Range | null>;
|
||||
rename(document: AstroDocument, position: Position, newName: string): Promise<WorkspaceEdit | null>;
|
||||
getFoldingRanges(document: AstroDocument): Promise<FoldingRange[] | null>;
|
||||
getSemanticTokens(document: AstroDocument, range?: Range, cancellationToken?: CancellationToken): Promise<SemanticTokens | null>;
|
||||
getDocumentSymbols(document: AstroDocument): Promise<SymbolInformation[]>;
|
||||
getCodeActions(document: AstroDocument, range: Range, context: CodeActionContext, cancellationToken?: CancellationToken): Promise<CodeAction[]>;
|
||||
getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext, cancellationToken?: CancellationToken): Promise<AppCompletionList<CompletionItemData> | null>;
|
||||
resolveCompletion(document: AstroDocument, completionItem: AppCompletionItem<CompletionItemData>, cancellationToken?: CancellationToken): Promise<AppCompletionItem<CompletionItemData>>;
|
||||
getInlayHints(document: AstroDocument, range: Range): Promise<InlayHint[]>;
|
||||
fileReferences(document: AstroDocument): Promise<Location[] | null>;
|
||||
getDefinitions(document: AstroDocument, position: Position): Promise<DefinitionLink[]>;
|
||||
getTypeDefinitions(document: AstroDocument, position: Position): Promise<Location[] | null>;
|
||||
getImplementation(document: AstroDocument, position: Position): Promise<Location[] | null>;
|
||||
findReferences(document: AstroDocument, position: Position, context: ReferenceContext): Promise<Location[] | null>;
|
||||
getDiagnostics(document: AstroDocument, cancellationToken?: CancellationToken): Promise<Diagnostic[]>;
|
||||
onWatchFileChanges(onWatchFileChangesParas: OnWatchFileChangesParam[]): Promise<void>;
|
||||
updateNonAstroFile(fileName: string, changes: TextDocumentContentChangeEvent[], text?: string): Promise<void>;
|
||||
getSignatureHelp(document: AstroDocument, position: Position, context: SignatureHelpContext | undefined, cancellationToken?: CancellationToken): Promise<SignatureHelp | null>;
|
||||
getTSXForDocument(document: AstroDocument): TSXResult;
|
||||
/**
|
||||
* @internal Public for tests only
|
||||
*/
|
||||
getSnapshotManager(fileName: string): Promise<import("./snapshots/SnapshotManager").SnapshotManager>;
|
||||
private featureEnabled;
|
||||
}
|
||||
152
node_modules/@astrojs/language-server/dist/plugins/typescript/TypeScriptPlugin.js
generated
vendored
Normal file
152
node_modules/@astrojs/language-server/dist/plugins/typescript/TypeScriptPlugin.js
generated
vendored
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.TypeScriptPlugin = void 0;
|
||||
const vscode_languageserver_1 = require("vscode-languageserver");
|
||||
const astro2tsx_1 = require("./astro2tsx");
|
||||
const CodeActionsProvider_1 = require("./features/CodeActionsProvider");
|
||||
const CompletionsProvider_1 = require("./features/CompletionsProvider");
|
||||
const DefinitionsProvider_1 = require("./features/DefinitionsProvider");
|
||||
const DiagnosticsProvider_1 = require("./features/DiagnosticsProvider");
|
||||
const DocumentSymbolsProvider_1 = require("./features/DocumentSymbolsProvider");
|
||||
const FileReferencesProvider_1 = require("./features/FileReferencesProvider");
|
||||
const FoldingRangesProvider_1 = require("./features/FoldingRangesProvider");
|
||||
const HoverProvider_1 = require("./features/HoverProvider");
|
||||
const ImplementationsProvider_1 = require("./features/ImplementationsProvider");
|
||||
const InlayHintsProvider_1 = require("./features/InlayHintsProvider");
|
||||
const ReferencesProvider_1 = require("./features/ReferencesProvider");
|
||||
const RenameProvider_1 = require("./features/RenameProvider");
|
||||
const SemanticTokenProvider_1 = require("./features/SemanticTokenProvider");
|
||||
const SignatureHelpProvider_1 = require("./features/SignatureHelpProvider");
|
||||
const TypeDefinitionsProvider_1 = require("./features/TypeDefinitionsProvider");
|
||||
const utils_1 = require("./utils");
|
||||
class TypeScriptPlugin {
|
||||
constructor(configManager, languageServiceManager) {
|
||||
this.__name = 'typescript';
|
||||
this.configManager = configManager;
|
||||
this.languageServiceManager = languageServiceManager;
|
||||
this.ts = languageServiceManager.docContext.ts;
|
||||
this.codeActionsProvider = new CodeActionsProvider_1.CodeActionsProviderImpl(this.languageServiceManager, this.configManager);
|
||||
this.completionProvider = new CompletionsProvider_1.CompletionsProviderImpl(this.languageServiceManager, this.configManager);
|
||||
this.hoverProvider = new HoverProvider_1.HoverProviderImpl(this.languageServiceManager);
|
||||
this.fileReferencesProvider = new FileReferencesProvider_1.FileReferencesProviderImpl(this.languageServiceManager);
|
||||
this.definitionsProvider = new DefinitionsProvider_1.DefinitionsProviderImpl(this.languageServiceManager);
|
||||
this.typeDefinitionsProvider = new TypeDefinitionsProvider_1.TypeDefinitionsProviderImpl(this.languageServiceManager);
|
||||
this.implementationsProvider = new ImplementationsProvider_1.ImplementationsProviderImpl(this.languageServiceManager);
|
||||
this.referencesProvider = new ReferencesProvider_1.FindReferencesProviderImpl(this.languageServiceManager);
|
||||
this.signatureHelpProvider = new SignatureHelpProvider_1.SignatureHelpProviderImpl(this.languageServiceManager);
|
||||
this.diagnosticsProvider = new DiagnosticsProvider_1.DiagnosticsProviderImpl(this.languageServiceManager);
|
||||
this.documentSymbolsProvider = new DocumentSymbolsProvider_1.DocumentSymbolsProviderImpl(this.languageServiceManager);
|
||||
this.semanticTokensProvider = new SemanticTokenProvider_1.SemanticTokensProviderImpl(this.languageServiceManager);
|
||||
this.inlayHintsProvider = new InlayHintsProvider_1.InlayHintsProviderImpl(this.languageServiceManager, this.configManager);
|
||||
this.foldingRangesProvider = new FoldingRangesProvider_1.FoldingRangesProviderImpl(this.languageServiceManager);
|
||||
this.renameProvider = new RenameProvider_1.RenameProviderImpl(this.languageServiceManager, this.configManager);
|
||||
}
|
||||
async doHover(document, position) {
|
||||
if (!(await this.featureEnabled(document, 'hover'))) {
|
||||
return null;
|
||||
}
|
||||
return this.hoverProvider.doHover(document, position);
|
||||
}
|
||||
async prepareRename(document, position) {
|
||||
return this.renameProvider.prepareRename(document, position);
|
||||
}
|
||||
async rename(document, position, newName) {
|
||||
return this.renameProvider.rename(document, position, newName);
|
||||
}
|
||||
async getFoldingRanges(document) {
|
||||
return this.foldingRangesProvider.getFoldingRanges(document);
|
||||
}
|
||||
async getSemanticTokens(document, range, cancellationToken) {
|
||||
if (!(await this.featureEnabled(document, 'semanticTokens'))) {
|
||||
return null;
|
||||
}
|
||||
return this.semanticTokensProvider.getSemanticTokens(document, range, cancellationToken);
|
||||
}
|
||||
async getDocumentSymbols(document) {
|
||||
if (!(await this.featureEnabled(document, 'documentSymbols'))) {
|
||||
return [];
|
||||
}
|
||||
const symbols = await this.documentSymbolsProvider.getDocumentSymbols(document);
|
||||
return symbols;
|
||||
}
|
||||
async getCodeActions(document, range, context, cancellationToken) {
|
||||
if (!(await this.featureEnabled(document, 'codeActions'))) {
|
||||
return [];
|
||||
}
|
||||
return this.codeActionsProvider.getCodeActions(document, range, context, cancellationToken);
|
||||
}
|
||||
async getCompletions(document, position, completionContext, cancellationToken) {
|
||||
if (!(await this.featureEnabled(document, 'completions'))) {
|
||||
return null;
|
||||
}
|
||||
const completions = await this.completionProvider.getCompletions(document, position, completionContext, cancellationToken);
|
||||
return completions;
|
||||
}
|
||||
async resolveCompletion(document, completionItem, cancellationToken) {
|
||||
return this.completionProvider.resolveCompletion(document, completionItem, cancellationToken);
|
||||
}
|
||||
async getInlayHints(document, range) {
|
||||
return this.inlayHintsProvider.getInlayHints(document, range);
|
||||
}
|
||||
async fileReferences(document) {
|
||||
return this.fileReferencesProvider.fileReferences(document);
|
||||
}
|
||||
async getDefinitions(document, position) {
|
||||
return this.definitionsProvider.getDefinitions(document, position);
|
||||
}
|
||||
async getTypeDefinitions(document, position) {
|
||||
return this.typeDefinitionsProvider.getTypeDefinitions(document, position);
|
||||
}
|
||||
async getImplementation(document, position) {
|
||||
return this.implementationsProvider.getImplementation(document, position);
|
||||
}
|
||||
async findReferences(document, position, context) {
|
||||
return this.referencesProvider.findReferences(document, position, context);
|
||||
}
|
||||
async getDiagnostics(document, cancellationToken) {
|
||||
if (!(await this.featureEnabled(document, 'diagnostics'))) {
|
||||
return [];
|
||||
}
|
||||
return this.diagnosticsProvider.getDiagnostics(document, cancellationToken);
|
||||
}
|
||||
async onWatchFileChanges(onWatchFileChangesParas) {
|
||||
let doneUpdateProjectFiles = false;
|
||||
for (const { fileName, changeType } of onWatchFileChangesParas) {
|
||||
const scriptKind = (0, utils_1.getScriptKindFromFileName)(fileName, this.ts);
|
||||
if (scriptKind === this.ts.ScriptKind.Unknown && !(0, utils_1.isFrameworkFilePath)(fileName) && !(0, utils_1.isAstroFilePath)(fileName)) {
|
||||
continue;
|
||||
}
|
||||
if (changeType === vscode_languageserver_1.FileChangeType.Created && !doneUpdateProjectFiles) {
|
||||
doneUpdateProjectFiles = true;
|
||||
await this.languageServiceManager.updateProjectFiles();
|
||||
}
|
||||
else if (changeType === vscode_languageserver_1.FileChangeType.Deleted) {
|
||||
await this.languageServiceManager.deleteSnapshot(fileName);
|
||||
}
|
||||
else if (!(0, utils_1.isAstroFilePath)(fileName)) {
|
||||
// Content updates for Astro files are handled through the documentManager and the 'documentChange' event
|
||||
await this.languageServiceManager.updateExistingNonAstroFile(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
async updateNonAstroFile(fileName, changes, text) {
|
||||
await this.languageServiceManager.updateExistingNonAstroFile(fileName, changes, text);
|
||||
}
|
||||
async getSignatureHelp(document, position, context, cancellationToken) {
|
||||
return this.signatureHelpProvider.getSignatureHelp(document, position, context, cancellationToken);
|
||||
}
|
||||
getTSXForDocument(document) {
|
||||
return (0, astro2tsx_1.astro2tsx)(document.getText(), document.getURL());
|
||||
}
|
||||
/**
|
||||
* @internal Public for tests only
|
||||
*/
|
||||
getSnapshotManager(fileName) {
|
||||
return this.languageServiceManager.getSnapshotManager(fileName);
|
||||
}
|
||||
async featureEnabled(document, feature) {
|
||||
return ((await this.configManager.isEnabled(document, 'typescript')) &&
|
||||
(await this.configManager.isEnabled(document, 'typescript', feature)));
|
||||
}
|
||||
}
|
||||
exports.TypeScriptPlugin = TypeScriptPlugin;
|
||||
8
node_modules/@astrojs/language-server/dist/plugins/typescript/astro-sys.d.ts
generated
vendored
Normal file
8
node_modules/@astrojs/language-server/dist/plugins/typescript/astro-sys.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import type ts from 'typescript';
|
||||
import type { DocumentSnapshot } from './snapshots/DocumentSnapshot';
|
||||
/**
|
||||
* This should only be accessed by TS Astro module resolution.
|
||||
*/
|
||||
export declare function createAstroSys(getSnapshot: (fileName: string) => DocumentSnapshot, ts: typeof import('typescript/lib/tsserverlibrary')): ts.System & {
|
||||
deleteFromCache: (path: string) => void;
|
||||
};
|
||||
46
node_modules/@astrojs/language-server/dist/plugins/typescript/astro-sys.js
generated
vendored
Normal file
46
node_modules/@astrojs/language-server/dist/plugins/typescript/astro-sys.js
generated
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createAstroSys = void 0;
|
||||
const utils_1 = require("./utils");
|
||||
/**
|
||||
* This should only be accessed by TS Astro module resolution.
|
||||
*/
|
||||
function createAstroSys(getSnapshot, ts) {
|
||||
const fileExistsCache = new Map();
|
||||
const AstroSys = {
|
||||
...ts.sys,
|
||||
fileExists(path) {
|
||||
path = (0, utils_1.ensureRealFilePath)(path);
|
||||
const exists = fileExistsCache.get(path) ?? ts.sys.fileExists(path);
|
||||
fileExistsCache.set(path, exists);
|
||||
return exists;
|
||||
},
|
||||
readFile(path) {
|
||||
const snapshot = getSnapshot(path);
|
||||
return snapshot.getText(0, snapshot.getLength());
|
||||
},
|
||||
readDirectory(path, extensions, exclude, include, depth) {
|
||||
const extensionsWithAstro = (extensions ?? []).concat(...['.astro', '.svelte', '.vue', '.md', '.mdx', '.html']);
|
||||
const result = ts.sys.readDirectory(path, extensionsWithAstro, exclude, include, depth);
|
||||
return result;
|
||||
},
|
||||
deleteFile(path) {
|
||||
fileExistsCache.delete((0, utils_1.ensureRealFilePath)(path));
|
||||
return ts.sys.deleteFile?.(path);
|
||||
},
|
||||
deleteFromCache(path) {
|
||||
fileExistsCache.delete((0, utils_1.ensureRealFilePath)(path));
|
||||
},
|
||||
};
|
||||
if (ts.sys.realpath) {
|
||||
const realpath = ts.sys.realpath;
|
||||
AstroSys.realpath = function (path) {
|
||||
if ((0, utils_1.isVirtualFilePath)(path)) {
|
||||
return realpath((0, utils_1.ensureRealFilePath)(path)) + '.tsx';
|
||||
}
|
||||
return realpath(path);
|
||||
};
|
||||
}
|
||||
return AstroSys;
|
||||
}
|
||||
exports.createAstroSys = createAstroSys;
|
||||
2
node_modules/@astrojs/language-server/dist/plugins/typescript/astro2tsx.d.ts
generated
vendored
Normal file
2
node_modules/@astrojs/language-server/dist/plugins/typescript/astro2tsx.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
import type { TSXResult } from '@astrojs/compiler/types';
|
||||
export declare function astro2tsx(content: string, fileName: string): TSXResult;
|
||||
26
node_modules/@astrojs/language-server/dist/plugins/typescript/astro2tsx.js
generated
vendored
Normal file
26
node_modules/@astrojs/language-server/dist/plugins/typescript/astro2tsx.js
generated
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.astro2tsx = void 0;
|
||||
const sync_1 = require("@astrojs/compiler/sync");
|
||||
function astro2tsx(content, fileName) {
|
||||
try {
|
||||
const tsx = (0, sync_1.convertToTSX)(content, { filename: fileName });
|
||||
return tsx;
|
||||
}
|
||||
catch (e) {
|
||||
console.error(`There was an error transforming ${fileName} to TSX. An empty file will be returned instead. Please create an issue: https://github.com/withastro/language-tools/issues\nError: ${e}.`);
|
||||
return {
|
||||
code: '',
|
||||
map: {
|
||||
file: fileName,
|
||||
sources: [],
|
||||
sourcesContent: [],
|
||||
names: [],
|
||||
mappings: '',
|
||||
version: 0,
|
||||
},
|
||||
diagnostics: [],
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.astro2tsx = astro2tsx;
|
||||
17
node_modules/@astrojs/language-server/dist/plugins/typescript/features/CodeActionsProvider.d.ts
generated
vendored
Normal file
17
node_modules/@astrojs/language-server/dist/plugins/typescript/features/CodeActionsProvider.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import type { CancellationToken } from 'vscode-languageserver';
|
||||
import { CodeAction, CodeActionContext, Range } from 'vscode-languageserver-types';
|
||||
import type { ConfigManager } from '../../../core/config';
|
||||
import { AstroDocument } from '../../../core/documents';
|
||||
import type { CodeActionsProvider } from '../../interfaces';
|
||||
import type { LanguageServiceManager } from '../LanguageServiceManager';
|
||||
export declare const sortImportKind: string;
|
||||
export declare class CodeActionsProviderImpl implements CodeActionsProvider {
|
||||
private languageServiceManager;
|
||||
private configManager;
|
||||
private ts;
|
||||
constructor(languageServiceManager: LanguageServiceManager, configManager: ConfigManager);
|
||||
getCodeActions(document: AstroDocument, range: Range, context: CodeActionContext, cancellationToken?: CancellationToken): Promise<CodeAction[]>;
|
||||
private getComponentQuickFix;
|
||||
private organizeSortImports;
|
||||
private fixIndentationOfImports;
|
||||
}
|
||||
212
node_modules/@astrojs/language-server/dist/plugins/typescript/features/CodeActionsProvider.js
generated
vendored
Normal file
212
node_modules/@astrojs/language-server/dist/plugins/typescript/features/CodeActionsProvider.js
generated
vendored
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.CodeActionsProviderImpl = exports.sortImportKind = void 0;
|
||||
const vscode_languageserver_types_1 = require("vscode-languageserver-types");
|
||||
const documents_1 = require("../../../core/documents");
|
||||
const utils_1 = require("../../../utils");
|
||||
const utils_2 = require("../utils");
|
||||
const CompletionsProvider_1 = require("./CompletionsProvider");
|
||||
const utils_3 = require("./utils");
|
||||
// These are VS Code specific CodeActionKind so they're not in the language server protocol
|
||||
exports.sortImportKind = `${vscode_languageserver_types_1.CodeActionKind.Source}.sortImports`;
|
||||
class CodeActionsProviderImpl {
|
||||
constructor(languageServiceManager, configManager) {
|
||||
this.languageServiceManager = languageServiceManager;
|
||||
this.configManager = configManager;
|
||||
this.ts = languageServiceManager.docContext.ts;
|
||||
}
|
||||
async getCodeActions(document, range, context, cancellationToken) {
|
||||
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
||||
const tsPreferences = await this.configManager.getTSPreferences(document);
|
||||
const formatOptions = await this.configManager.getTSFormatConfig(document);
|
||||
let result = [];
|
||||
if (cancellationToken?.isCancellationRequested) {
|
||||
return [];
|
||||
}
|
||||
if (context.only?.[0] === vscode_languageserver_types_1.CodeActionKind.SourceOrganizeImports) {
|
||||
return await this.organizeSortImports(document, false, cancellationToken);
|
||||
}
|
||||
// The difference between Sort Imports and Organize Imports is that Sort Imports won't do anything destructive.
|
||||
// For example, it won't remove unused imports whereas Organize Imports will
|
||||
if (context.only?.[0] === exports.sortImportKind) {
|
||||
return await this.organizeSortImports(document, true, cancellationToken);
|
||||
}
|
||||
if (context.only?.[0] === vscode_languageserver_types_1.CodeActionKind.Source) {
|
||||
return [
|
||||
...(await this.organizeSortImports(document, true, cancellationToken)),
|
||||
...(await this.organizeSortImports(document, false, cancellationToken)),
|
||||
];
|
||||
}
|
||||
if (context.diagnostics.length && (!context.only || context.only.includes(vscode_languageserver_types_1.CodeActionKind.QuickFix))) {
|
||||
const errorCodes = context.diagnostics
|
||||
.map((diag) => Number(diag.code))
|
||||
// We currently cannot support quick fix for unreachable code properly due to the way our TSX output is structured
|
||||
.filter((code) => code !== 7027);
|
||||
const html = document.html;
|
||||
const node = html.findNodeAt(document.offsetAt(range.start));
|
||||
let codeFixes;
|
||||
let isInsideScript = false;
|
||||
if (node.tag === 'script') {
|
||||
const { snapshot: scriptTagSnapshot, filePath: scriptFilePath } = (0, utils_2.getScriptTagSnapshot)(tsDoc, document, node);
|
||||
const start = scriptTagSnapshot.offsetAt(scriptTagSnapshot.getGeneratedPosition(range.start));
|
||||
const end = scriptTagSnapshot.offsetAt(scriptTagSnapshot.getGeneratedPosition(range.end));
|
||||
codeFixes = lang.getCodeFixesAtPosition(scriptFilePath, start, end, errorCodes, formatOptions, tsPreferences);
|
||||
codeFixes = codeFixes.map((fix) => ({
|
||||
...fix,
|
||||
changes: mapScriptTagFixToOriginal(fix.changes, scriptTagSnapshot),
|
||||
}));
|
||||
isInsideScript = true;
|
||||
}
|
||||
else {
|
||||
const start = tsDoc.offsetAt(tsDoc.getGeneratedPosition(range.start));
|
||||
const end = tsDoc.offsetAt(tsDoc.getGeneratedPosition(range.end));
|
||||
codeFixes = errorCodes.includes(2304)
|
||||
? this.getComponentQuickFix(start, end, lang, tsDoc.filePath, formatOptions, tsPreferences)
|
||||
: undefined;
|
||||
codeFixes =
|
||||
codeFixes ??
|
||||
lang.getCodeFixesAtPosition(tsDoc.filePath, start, end, errorCodes, formatOptions, tsPreferences);
|
||||
}
|
||||
const codeActions = codeFixes.map((fix) => codeFixToCodeAction(fix, context.diagnostics, context.only ? vscode_languageserver_types_1.CodeActionKind.QuickFix : vscode_languageserver_types_1.CodeActionKind.Empty, isInsideScript, this.ts));
|
||||
result.push(...codeActions);
|
||||
}
|
||||
return result;
|
||||
function codeFixToCodeAction(codeFix, diagnostics, kind, isInsideScript, ts) {
|
||||
const documentChanges = codeFix.changes.map((change) => {
|
||||
return vscode_languageserver_types_1.TextDocumentEdit.create(vscode_languageserver_types_1.OptionalVersionedTextDocumentIdentifier.create(document.getURL(), null), change.textChanges.map((edit) => {
|
||||
let originalRange = (0, documents_1.mapRangeToOriginal)(tsDoc, (0, utils_2.convertRange)(tsDoc, edit.span));
|
||||
// Inside scripts, we don't need to restrain the insertion of code inside a specific zone as it will be
|
||||
// restricted to the area of the script tag by default
|
||||
if (!isInsideScript) {
|
||||
if (codeFix.fixName === 'import') {
|
||||
return (0, CompletionsProvider_1.codeActionChangeToTextEdit)(document, tsDoc, false, edit, ts);
|
||||
}
|
||||
if (codeFix.fixName === 'fixMissingFunctionDeclaration') {
|
||||
originalRange = (0, utils_2.checkEndOfFileCodeInsert)(originalRange, document);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Make sure new imports are not added on the file line of the script tag
|
||||
if (codeFix.fixName === 'import') {
|
||||
const existingLine = (0, documents_1.getLineAtPosition)(document.positionAt(edit.span.start), document.getText());
|
||||
const isNewImport = !existingLine.trim().startsWith('import');
|
||||
if (!(edit.newText.startsWith('\n') || edit.newText.startsWith('\r\n')) && isNewImport) {
|
||||
edit.newText = ts.sys.newLine + edit.newText;
|
||||
}
|
||||
}
|
||||
}
|
||||
return vscode_languageserver_types_1.TextEdit.replace(originalRange, edit.newText);
|
||||
}));
|
||||
});
|
||||
const codeAction = vscode_languageserver_types_1.CodeAction.create(codeFix.description, {
|
||||
documentChanges,
|
||||
}, kind);
|
||||
codeAction.diagnostics = diagnostics;
|
||||
return codeAction;
|
||||
}
|
||||
function mapScriptTagFixToOriginal(changes, scriptTagSnapshot) {
|
||||
return changes.map((change) => {
|
||||
change.textChanges.map((edit) => {
|
||||
edit.span.start = (0, documents_1.mapScriptSpanStartToSnapshot)(edit.span, scriptTagSnapshot, tsDoc);
|
||||
return edit;
|
||||
});
|
||||
return change;
|
||||
});
|
||||
}
|
||||
}
|
||||
getComponentQuickFix(start, end, lang, filePath, formatOptions, tsPreferences) {
|
||||
const sourceFile = lang.getProgram()?.getSourceFile(filePath);
|
||||
if (!sourceFile) {
|
||||
return;
|
||||
}
|
||||
const node = (0, utils_3.findContainingNode)(sourceFile, {
|
||||
start,
|
||||
length: end - start,
|
||||
}, (n) => this.ts.isJsxClosingElement(n) || this.ts.isJsxOpeningLikeElement(n));
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
const tagName = node.tagName;
|
||||
// Unlike quick fixes, completions will be able to find the component, so let's use those to get it
|
||||
const completion = lang.getCompletionsAtPosition(filePath, tagName.getEnd(), tsPreferences, formatOptions);
|
||||
if (!completion) {
|
||||
return;
|
||||
}
|
||||
const name = tagName.getText();
|
||||
const suffixedName = name + '__AstroComponent_';
|
||||
const toFix = (c) => lang.getCompletionEntryDetails(filePath, end, c.name, {}, c.source, {}, c.data)?.codeActions?.map((a) => ({
|
||||
...a,
|
||||
description: (0, utils_2.removeAstroComponentSuffix)(a.description),
|
||||
fixName: 'import',
|
||||
})) ?? [];
|
||||
return completion.entries.filter((c) => c.name === name || c.name === suffixedName).flatMap(toFix);
|
||||
}
|
||||
async organizeSortImports(document, skipDestructiveCodeActions = false, cancellationToken) {
|
||||
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
||||
const filePath = tsDoc.filePath;
|
||||
if (cancellationToken?.isCancellationRequested) {
|
||||
return [];
|
||||
}
|
||||
let changes = [];
|
||||
if (document.astroMeta.frontmatter.state === 'closed') {
|
||||
changes.push(...lang.organizeImports({ fileName: filePath, type: 'file', skipDestructiveCodeActions }, {}, {}));
|
||||
}
|
||||
document.scriptTags.forEach((scriptTag) => {
|
||||
const { filePath: scriptFilePath, snapshot: scriptTagSnapshot } = (0, utils_2.getScriptTagSnapshot)(tsDoc, document, scriptTag.container);
|
||||
const edits = lang.organizeImports({ fileName: scriptFilePath, type: 'file', skipDestructiveCodeActions }, {}, {});
|
||||
edits.forEach((edit) => {
|
||||
edit.fileName = tsDoc.filePath;
|
||||
edit.textChanges = edit.textChanges
|
||||
.map((change) => {
|
||||
change.span.start = (0, documents_1.mapScriptSpanStartToSnapshot)(change.span, scriptTagSnapshot, tsDoc);
|
||||
// If the result ending position is unmapped, it usually means the ending position has a newline
|
||||
// inside the virtual part of the script tag, so let's just make it a character shorter
|
||||
const range = (0, documents_1.mapRangeToOriginal)(tsDoc, (0, utils_2.convertRange)(tsDoc, change.span));
|
||||
if (range.end.character === 0 && range.end.line === 0) {
|
||||
change.span.length -= 1;
|
||||
}
|
||||
return change;
|
||||
})
|
||||
// Since our last line is a (virtual) export, organize imports will try to rewrite it, so let's only take
|
||||
// changes that actually happens inside the script tag
|
||||
.filter((change) => {
|
||||
return (scriptTagSnapshot.isInGenerated(document.positionAt(change.span.start)) &&
|
||||
!change.newText.includes('export { }'));
|
||||
});
|
||||
return edit;
|
||||
});
|
||||
changes.push(...edits);
|
||||
});
|
||||
const documentChanges = changes.map((change) => {
|
||||
return vscode_languageserver_types_1.TextDocumentEdit.create(vscode_languageserver_types_1.OptionalVersionedTextDocumentIdentifier.create(document.url, null), change.textChanges.map((edit) => {
|
||||
const range = (0, documents_1.mapRangeToOriginal)(tsDoc, (0, utils_2.convertRange)(tsDoc, edit.span));
|
||||
if (document.offsetAt(range.start) < (document.astroMeta.content.firstNonWhitespaceOffset ?? 0)) {
|
||||
if (document.offsetAt(range.end) > document.astroMeta.frontmatter.endOffset) {
|
||||
range.end = document.positionAt(document.astroMeta.frontmatter.endOffset);
|
||||
}
|
||||
}
|
||||
return vscode_languageserver_types_1.TextEdit.replace(range, this.fixIndentationOfImports(edit.newText, range, document));
|
||||
}));
|
||||
});
|
||||
return [
|
||||
vscode_languageserver_types_1.CodeAction.create(skipDestructiveCodeActions ? 'Sort Imports' : 'Organize Imports', {
|
||||
documentChanges,
|
||||
}, skipDestructiveCodeActions ? exports.sortImportKind : vscode_languageserver_types_1.CodeActionKind.SourceOrganizeImports),
|
||||
];
|
||||
}
|
||||
// "Organize Imports" will have edits that delete all imports by return empty edits
|
||||
// and one edit which contains all the organized imports. Fix indentation
|
||||
// of that one by prepending all lines with the indentation of the first line.
|
||||
fixIndentationOfImports(edit, range, document) {
|
||||
if (!edit || range.start.character === 0) {
|
||||
return edit;
|
||||
}
|
||||
const existingLine = (0, documents_1.getLineAtPosition)(range.start, document.getText());
|
||||
const leadingChars = existingLine.substring(0, range.start.character);
|
||||
if (leadingChars.trim() !== '') {
|
||||
return edit;
|
||||
}
|
||||
return (0, utils_1.modifyLines)(edit, (line, idx) => (idx === 0 || !line ? line : leadingChars + line));
|
||||
}
|
||||
}
|
||||
exports.CodeActionsProviderImpl = CodeActionsProviderImpl;
|
||||
31
node_modules/@astrojs/language-server/dist/plugins/typescript/features/CompletionsProvider.d.ts
generated
vendored
Normal file
31
node_modules/@astrojs/language-server/dist/plugins/typescript/features/CompletionsProvider.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import type ts from 'typescript';
|
||||
import { CancellationToken, CompletionContext, Position, TextDocumentIdentifier, TextEdit } from 'vscode-languageserver';
|
||||
import type { ConfigManager } from '../../../core/config';
|
||||
import { AstroDocument } from '../../../core/documents';
|
||||
import type { AppCompletionItem, AppCompletionList, CompletionsProvider } from '../../interfaces';
|
||||
import type { LanguageServiceManager } from '../LanguageServiceManager';
|
||||
import type { DocumentSnapshot } from '../snapshots/DocumentSnapshot';
|
||||
export interface CompletionItemData extends TextDocumentIdentifier {
|
||||
filePath: string;
|
||||
offset: number;
|
||||
scriptTagIndex: number | undefined;
|
||||
originalItem: ts.CompletionEntry;
|
||||
}
|
||||
export declare class CompletionsProviderImpl implements CompletionsProvider<CompletionItemData> {
|
||||
private languageServiceManager;
|
||||
private configManager;
|
||||
private ts;
|
||||
constructor(languageServiceManager: LanguageServiceManager, configManager: ConfigManager);
|
||||
private readonly validTriggerCharacters;
|
||||
private isValidTriggerCharacter;
|
||||
private lastCompletion?;
|
||||
getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext, cancellationToken?: CancellationToken): Promise<AppCompletionList<CompletionItemData> | null>;
|
||||
resolveCompletion(document: AstroDocument, item: AppCompletionItem<CompletionItemData>, cancellationToken?: CancellationToken): Promise<AppCompletionItem<CompletionItemData>>;
|
||||
private toCompletionItem;
|
||||
private getCompletionDocument;
|
||||
private canReuseLastCompletion;
|
||||
private getExistingImports;
|
||||
private isAstroComponentImport;
|
||||
private isValidCompletion;
|
||||
}
|
||||
export declare function codeActionChangeToTextEdit(document: AstroDocument, snapshot: DocumentSnapshot, isInsideScriptTag: boolean, change: ts.TextChange, ts: typeof import('typescript/lib/tsserverlibrary')): TextEdit;
|
||||
294
node_modules/@astrojs/language-server/dist/plugins/typescript/features/CompletionsProvider.js
generated
vendored
Normal file
294
node_modules/@astrojs/language-server/dist/plugins/typescript/features/CompletionsProvider.js
generated
vendored
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.codeActionChangeToTextEdit = exports.CompletionsProviderImpl = void 0;
|
||||
const vscode_languageserver_1 = require("vscode-languageserver");
|
||||
const vscode_languageserver_protocol_1 = require("vscode-languageserver-protocol");
|
||||
const documents_1 = require("../../../core/documents");
|
||||
const utils_1 = require("../../../core/documents/utils");
|
||||
const utils_2 = require("../../../utils");
|
||||
const previewer_1 = require("../previewer");
|
||||
const utils_3 = require("../utils");
|
||||
const utils_4 = require("./utils");
|
||||
// `import {...} from '..'` or `import ... from '..'`
|
||||
// Note: Does not take into account if import is within a comment.
|
||||
const scriptImportRegex = /\bimport\s+{([^}]*?)}\s+?from\s+['"`].+?['"`]|\bimport\s+(\w+?)\s+from\s+['"`].+?['"`]/g;
|
||||
// When Svelte components are imported, we have to reference the svelte2tsx's types to properly type the component
|
||||
// An unfortunate downside of this is that it polutes completions, so let's filter those internal types manually
|
||||
const svelte2tsxTypes = new Set([
|
||||
'Svelte2TsxComponent',
|
||||
'Svelte2TsxComponentConstructorParameters',
|
||||
'SvelteComponentConstructor',
|
||||
'SvelteActionReturnType',
|
||||
'SvelteTransitionConfig',
|
||||
'SvelteTransitionReturnType',
|
||||
'SvelteAnimationReturnType',
|
||||
'SvelteWithOptionalProps',
|
||||
'SvelteAllProps',
|
||||
'SveltePropsAnyFallback',
|
||||
'SvelteSlotsAnyFallback',
|
||||
'SvelteRestProps',
|
||||
'SvelteSlots',
|
||||
'SvelteStore',
|
||||
]);
|
||||
class CompletionsProviderImpl {
|
||||
constructor(languageServiceManager, configManager) {
|
||||
this.languageServiceManager = languageServiceManager;
|
||||
this.configManager = configManager;
|
||||
this.validTriggerCharacters = ['.', '"', "'", '`', '/', '@', '<', '#'];
|
||||
this.ts = languageServiceManager.docContext.ts;
|
||||
}
|
||||
isValidTriggerCharacter(character) {
|
||||
return this.validTriggerCharacters.includes(character);
|
||||
}
|
||||
async getCompletions(document, position, completionContext, cancellationToken) {
|
||||
const triggerCharacter = completionContext?.triggerCharacter;
|
||||
const triggerKind = completionContext?.triggerKind;
|
||||
const validTriggerCharacter = this.isValidTriggerCharacter(triggerCharacter) ? triggerCharacter : undefined;
|
||||
const isCustomTriggerCharacter = triggerKind === vscode_languageserver_1.CompletionTriggerKind.TriggerCharacter;
|
||||
if ((isCustomTriggerCharacter && !validTriggerCharacter) || cancellationToken?.isCancellationRequested) {
|
||||
return null;
|
||||
}
|
||||
if (this.canReuseLastCompletion(this.lastCompletion, triggerKind, triggerCharacter, document, position)) {
|
||||
this.lastCompletion.position = position;
|
||||
return this.lastCompletion.completionList;
|
||||
}
|
||||
else {
|
||||
this.lastCompletion = undefined;
|
||||
}
|
||||
const html = document.html;
|
||||
const documentOffset = document.offsetAt(position);
|
||||
const node = html.findNodeAt(documentOffset);
|
||||
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
||||
const offset = tsDoc.offsetAt(tsDoc.getGeneratedPosition(position));
|
||||
let filePath = tsDoc.filePath;
|
||||
let completions;
|
||||
const isCompletionInsideFrontmatter = (0, utils_1.isInsideFrontmatter)(document.getText(), documentOffset);
|
||||
const isCompletionInsideExpression = (0, utils_1.isInsideExpression)(document.getText(), node.start, documentOffset);
|
||||
const tsPreferences = await this.configManager.getTSPreferences(document);
|
||||
const formatOptions = await this.configManager.getTSFormatConfig(document);
|
||||
let scriptTagIndex = undefined;
|
||||
if (node.tag === 'script') {
|
||||
const { filePath: scriptFilePath, offset: scriptOffset, index: scriptIndex, } = (0, utils_3.getScriptTagSnapshot)(tsDoc, document, node, position);
|
||||
filePath = scriptFilePath;
|
||||
scriptTagIndex = scriptIndex;
|
||||
completions = lang.getCompletionsAtPosition(scriptFilePath, scriptOffset, {
|
||||
...tsPreferences,
|
||||
triggerCharacter: validTriggerCharacter,
|
||||
}, formatOptions);
|
||||
}
|
||||
else {
|
||||
// PERF: Getting TS completions is fairly slow and I am currently not sure how to speed it up
|
||||
// As such, we'll try to avoid getting them when unneeded, such as when we're doing HTML stuff
|
||||
// If the user just typed `<` with nothing else, let's disable ourselves until we're more sure if the user wants TS completions
|
||||
if (!isCompletionInsideFrontmatter && node.parent && node.tag === undefined && !isCompletionInsideExpression) {
|
||||
return null;
|
||||
}
|
||||
// If the current node is not a component, let's disable ourselves as the user
|
||||
// is most likely looking for HTML completions
|
||||
if (!isCompletionInsideFrontmatter && !(0, utils_1.isPossibleComponent)(node) && !isCompletionInsideExpression) {
|
||||
return null;
|
||||
}
|
||||
completions = lang.getCompletionsAtPosition(filePath, offset, {
|
||||
...tsPreferences,
|
||||
triggerCharacter: validTriggerCharacter,
|
||||
}, formatOptions);
|
||||
}
|
||||
if (completions === undefined || completions.entries.length === 0) {
|
||||
return null;
|
||||
}
|
||||
const existingImports = this.getExistingImports(document);
|
||||
const completionItems = completions.entries
|
||||
.filter((completion) => this.isValidCompletion(completion, this.ts))
|
||||
.map((entry) => this.toCompletionItem(tsDoc, entry, filePath, offset, isCompletionInsideFrontmatter, scriptTagIndex, existingImports))
|
||||
.filter(utils_2.isNotNullOrUndefined);
|
||||
const completionList = vscode_languageserver_1.CompletionList.create(completionItems, true);
|
||||
this.lastCompletion = { key: document.getFilePath() || '', position, completionList };
|
||||
return completionList;
|
||||
}
|
||||
async resolveCompletion(document, item, cancellationToken) {
|
||||
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
||||
const tsPreferences = await this.configManager.getTSPreferences(document);
|
||||
const data = item.data;
|
||||
if (!data || !data.filePath || cancellationToken?.isCancellationRequested) {
|
||||
return item;
|
||||
}
|
||||
const detail = lang.getCompletionEntryDetails(data.filePath, // fileName
|
||||
data.offset, // position
|
||||
data.originalItem.name, // entryName
|
||||
{}, // formatOptions
|
||||
data.originalItem.source, // source
|
||||
tsPreferences, // preferences
|
||||
data.originalItem.data // data
|
||||
);
|
||||
if (detail) {
|
||||
const { detail: itemDetail, documentation: itemDocumentation } = this.getCompletionDocument(detail);
|
||||
// TODO: Add support for labelDetails
|
||||
// if (data.originalItem.source) {
|
||||
// item.labelDetails = { description: data.originalItem.source };
|
||||
// }
|
||||
item.detail = itemDetail;
|
||||
item.documentation = itemDocumentation;
|
||||
}
|
||||
const actions = detail?.codeActions;
|
||||
const isInsideScriptTag = data.scriptTagIndex !== undefined;
|
||||
let scriptTagSnapshot;
|
||||
if (isInsideScriptTag) {
|
||||
const { snapshot } = (0, utils_3.getScriptTagSnapshot)(tsDoc, document, document.scriptTags[data.scriptTagIndex].container);
|
||||
scriptTagSnapshot = snapshot;
|
||||
}
|
||||
if (actions) {
|
||||
const edit = [];
|
||||
for (const action of actions) {
|
||||
for (const change of action.changes) {
|
||||
if (isInsideScriptTag) {
|
||||
change.textChanges.forEach((textChange) => {
|
||||
const originalPosition = scriptTagSnapshot.getOriginalPosition(scriptTagSnapshot.positionAt(textChange.span.start));
|
||||
textChange.span.start = tsDoc.offsetAt(tsDoc.getGeneratedPosition(originalPosition));
|
||||
});
|
||||
}
|
||||
edit.push(...change.textChanges.map((textChange) => codeActionChangeToTextEdit(document, tsDoc, isInsideScriptTag, textChange, this.ts)));
|
||||
}
|
||||
}
|
||||
item.additionalTextEdits = (item.additionalTextEdits ?? []).concat(edit);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
toCompletionItem(snapshot, comp, filePath, offset, insideFrontmatter, scriptTagIndex, existingImports) {
|
||||
let item = vscode_languageserver_protocol_1.CompletionItem.create(comp.name);
|
||||
const isAstroComponent = this.isAstroComponentImport(comp.name);
|
||||
const isImport = comp.insertText?.includes('import');
|
||||
// Avoid showing completions for using components as functions
|
||||
if (isAstroComponent && !isImport && insideFrontmatter) {
|
||||
return null;
|
||||
}
|
||||
if (isAstroComponent) {
|
||||
item.label = (0, utils_3.removeAstroComponentSuffix)(comp.name);
|
||||
// Set component imports as file completion, that way we get cool icons
|
||||
item.kind = vscode_languageserver_protocol_1.CompletionItemKind.File;
|
||||
item.detail = comp.data?.moduleSpecifier;
|
||||
}
|
||||
else {
|
||||
item.kind = (0, utils_3.scriptElementKindToCompletionItemKind)(comp.kind, this.ts);
|
||||
}
|
||||
// TS may suggest another component even if there already exists an import with the same.
|
||||
// This happens because internally, components get suffixed with __AstroComponent_
|
||||
if (isAstroComponent && existingImports.has(item.label)) {
|
||||
return null;
|
||||
}
|
||||
if (comp.kindModifiers) {
|
||||
const kindModifiers = new Set(comp.kindModifiers.split(/,|\s+/g));
|
||||
if (kindModifiers.has(this.ts.ScriptElementKindModifier.optionalModifier)) {
|
||||
if (!item.insertText) {
|
||||
item.insertText = item.label;
|
||||
}
|
||||
if (!item.filterText) {
|
||||
item.filterText = item.label;
|
||||
}
|
||||
item.label += '?';
|
||||
}
|
||||
if (kindModifiers.has(this.ts.ScriptElementKindModifier.deprecatedModifier)) {
|
||||
item.tags = [vscode_languageserver_1.CompletionItemTag.Deprecated];
|
||||
}
|
||||
}
|
||||
// TODO: Add support for labelDetails
|
||||
// if (comp.sourceDisplay) {
|
||||
// item.labelDetails = { description: ts.displayPartsToString(comp.sourceDisplay) };
|
||||
// }
|
||||
item.commitCharacters = (0, utils_3.getCommitCharactersForScriptElement)(comp.kind, this.ts);
|
||||
item.sortText = comp.sortText;
|
||||
item.preselect = comp.isRecommended;
|
||||
if (comp.replacementSpan) {
|
||||
item.insertText = comp.insertText ? (0, utils_3.removeAstroComponentSuffix)(comp.insertText) : undefined;
|
||||
item.insertTextFormat = comp.isSnippet ? vscode_languageserver_1.InsertTextFormat.Snippet : vscode_languageserver_1.InsertTextFormat.PlainText;
|
||||
item.textEdit = comp.replacementSpan
|
||||
? vscode_languageserver_1.TextEdit.replace((0, utils_3.convertToLocationRange)(snapshot, comp.replacementSpan), item.insertText ?? item.label)
|
||||
: undefined;
|
||||
}
|
||||
return {
|
||||
...item,
|
||||
data: {
|
||||
uri: snapshot.getURL(),
|
||||
filePath,
|
||||
scriptTagIndex,
|
||||
offset,
|
||||
originalItem: comp,
|
||||
},
|
||||
};
|
||||
}
|
||||
getCompletionDocument(compDetail) {
|
||||
const { sourceDisplay, documentation: tsDocumentation, displayParts } = compDetail;
|
||||
let detail = (0, utils_3.removeAstroComponentSuffix)(this.ts.displayPartsToString(displayParts));
|
||||
if (sourceDisplay) {
|
||||
const importPath = this.ts.displayPartsToString(sourceDisplay);
|
||||
detail = importPath;
|
||||
}
|
||||
const documentation = {
|
||||
kind: 'markdown',
|
||||
value: (0, previewer_1.getMarkdownDocumentation)(tsDocumentation, compDetail.tags, this.ts),
|
||||
};
|
||||
return {
|
||||
documentation,
|
||||
detail,
|
||||
};
|
||||
}
|
||||
canReuseLastCompletion(lastCompletion, triggerKind, triggerCharacter, document, position) {
|
||||
return (!!lastCompletion &&
|
||||
lastCompletion.key === document.getFilePath() &&
|
||||
lastCompletion.position.line === position.line &&
|
||||
Math.abs(lastCompletion.position.character - position.character) < 2 &&
|
||||
(triggerKind === vscode_languageserver_1.CompletionTriggerKind.TriggerForIncompleteCompletions ||
|
||||
// Special case: `.` is a trigger character, but inside import path completions
|
||||
// it shouldn't trigger another completion because we can reuse the old one
|
||||
(triggerCharacter === '.' && (0, utils_4.isPartOfImportStatement)(document.getText(), position))));
|
||||
}
|
||||
getExistingImports(document) {
|
||||
const rawImports = (0, utils_2.getRegExpMatches)(scriptImportRegex, document.getText()).map((match) => (match[1] ?? match[2]).split(','));
|
||||
const tidiedImports = rawImports.flat().map((match) => match.trim());
|
||||
return new Set(tidiedImports);
|
||||
}
|
||||
isAstroComponentImport(className) {
|
||||
return className.endsWith('__AstroComponent_');
|
||||
}
|
||||
isValidCompletion(completion, ts) {
|
||||
// Remove completion for default exported function
|
||||
const isDefaultExport = completion.name === 'default' && completion.kindModifiers == ts.ScriptElementKindModifier.exportedModifier;
|
||||
// Remove completion for svelte2tsx internal types
|
||||
const isSvelte2tsxCompletion = completion.name.startsWith('__sveltets_') || svelte2tsxTypes.has(completion.name);
|
||||
if (isDefaultExport || isSvelte2tsxCompletion) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
exports.CompletionsProviderImpl = CompletionsProviderImpl;
|
||||
function codeActionChangeToTextEdit(document, snapshot, isInsideScriptTag, change, ts) {
|
||||
change.newText = (0, utils_3.removeAstroComponentSuffix)(change.newText);
|
||||
const { span } = change;
|
||||
let range;
|
||||
const virtualRange = (0, utils_3.convertRange)(snapshot, span);
|
||||
range = (0, documents_1.mapRangeToOriginal)(snapshot, virtualRange);
|
||||
if (!isInsideScriptTag) {
|
||||
// If we don't have a frontmatter already, create one with the import
|
||||
const frontmatterState = document.astroMeta.frontmatter.state;
|
||||
if (frontmatterState === null) {
|
||||
return vscode_languageserver_1.TextEdit.replace(vscode_languageserver_1.Range.create(vscode_languageserver_1.Position.create(0, 0), vscode_languageserver_1.Position.create(0, 0)), `---${ts.sys.newLine}${change.newText}---${ts.sys.newLine}${ts.sys.newLine}`);
|
||||
}
|
||||
if (!(0, utils_1.isInsideFrontmatter)(document.getText(), document.offsetAt(range.start))) {
|
||||
range = (0, utils_3.ensureFrontmatterInsert)(range, document);
|
||||
}
|
||||
// First import in a file will wrongly have a newline before it due to how the frontmatter is replaced by a comment
|
||||
if (range.start.line === 1 && (change.newText.startsWith('\n') || change.newText.startsWith('\r\n'))) {
|
||||
change.newText = change.newText.trimStart();
|
||||
}
|
||||
}
|
||||
else {
|
||||
const existingLine = (0, utils_1.getLineAtPosition)(document.positionAt(span.start), document.getText());
|
||||
const isNewImport = !existingLine.trim().startsWith('import');
|
||||
// Avoid putting new imports on the same line as the script tag opening
|
||||
if (!(change.newText.startsWith('\n') || change.newText.startsWith('\r\n')) && isNewImport) {
|
||||
change.newText = ts.sys.newLine + change.newText;
|
||||
}
|
||||
}
|
||||
return vscode_languageserver_1.TextEdit.replace(range, change.newText);
|
||||
}
|
||||
exports.codeActionChangeToTextEdit = codeActionChangeToTextEdit;
|
||||
9
node_modules/@astrojs/language-server/dist/plugins/typescript/features/DefinitionsProvider.d.ts
generated
vendored
Normal file
9
node_modules/@astrojs/language-server/dist/plugins/typescript/features/DefinitionsProvider.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import { LocationLink, Position } from 'vscode-languageserver-types';
|
||||
import { AstroDocument } from '../../../core/documents';
|
||||
import type { DefinitionsProvider } from '../../interfaces';
|
||||
import type { LanguageServiceManager } from '../LanguageServiceManager';
|
||||
export declare class DefinitionsProviderImpl implements DefinitionsProvider {
|
||||
private languageServiceManager;
|
||||
constructor(languageServiceManager: LanguageServiceManager);
|
||||
getDefinitions(document: AstroDocument, position: Position): Promise<LocationLink[]>;
|
||||
}
|
||||
58
node_modules/@astrojs/language-server/dist/plugins/typescript/features/DefinitionsProvider.js
generated
vendored
Normal file
58
node_modules/@astrojs/language-server/dist/plugins/typescript/features/DefinitionsProvider.js
generated
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.DefinitionsProviderImpl = void 0;
|
||||
const vscode_languageserver_types_1 = require("vscode-languageserver-types");
|
||||
const documents_1 = require("../../../core/documents");
|
||||
const utils_1 = require("../../../utils");
|
||||
const utils_2 = require("../utils");
|
||||
const utils_3 = require("./utils");
|
||||
class DefinitionsProviderImpl {
|
||||
constructor(languageServiceManager) {
|
||||
this.languageServiceManager = languageServiceManager;
|
||||
}
|
||||
async getDefinitions(document, position) {
|
||||
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
||||
const fragmentPosition = tsDoc.getGeneratedPosition(position);
|
||||
const fragmentOffset = tsDoc.offsetAt(fragmentPosition);
|
||||
let defs;
|
||||
const html = document.html;
|
||||
const offset = document.offsetAt(position);
|
||||
const node = html.findNodeAt(offset);
|
||||
if (node.tag === 'script') {
|
||||
const { snapshot: scriptTagSnapshot, filePath: scriptFilePath, offset: scriptOffset, } = (0, utils_2.getScriptTagSnapshot)(tsDoc, document, node, position);
|
||||
defs = lang.getDefinitionAndBoundSpan(scriptFilePath, scriptOffset);
|
||||
if (defs) {
|
||||
defs.definitions = defs.definitions?.map((def) => {
|
||||
const isInSameFile = def.fileName === scriptFilePath;
|
||||
def.fileName = isInSameFile ? tsDoc.filePath : def.fileName;
|
||||
if (isInSameFile) {
|
||||
def.textSpan.start = (0, documents_1.mapScriptSpanStartToSnapshot)(def.textSpan, scriptTagSnapshot, tsDoc);
|
||||
}
|
||||
return def;
|
||||
});
|
||||
defs.textSpan.start = (0, documents_1.mapScriptSpanStartToSnapshot)(defs.textSpan, scriptTagSnapshot, tsDoc);
|
||||
}
|
||||
}
|
||||
else {
|
||||
defs = lang.getDefinitionAndBoundSpan(tsDoc.filePath, fragmentOffset);
|
||||
}
|
||||
if (!defs || !defs.definitions) {
|
||||
return [];
|
||||
}
|
||||
const snapshots = new utils_3.SnapshotMap(this.languageServiceManager);
|
||||
snapshots.set(tsDoc.filePath, tsDoc);
|
||||
const result = await Promise.all(defs.definitions.map(async (def) => {
|
||||
const snapshot = await snapshots.retrieve(def.fileName);
|
||||
const fileName = (0, utils_2.ensureRealFilePath)(def.fileName);
|
||||
// For Astro, Svelte and Vue, the position is wrongly mapped to the end of the file due to the TSX output
|
||||
// So we'll instead redirect to the beginning of the file
|
||||
const isFramework = ((0, utils_2.isFrameworkFilePath)(def.fileName) || (0, utils_2.isAstroFilePath)(def.fileName)) && tsDoc.filePath !== def.fileName;
|
||||
const targetRange = isFramework
|
||||
? (0, utils_2.convertRange)(document, { start: 0, length: 0 })
|
||||
: (0, utils_2.convertToLocationRange)(snapshot, def.textSpan);
|
||||
return vscode_languageserver_types_1.LocationLink.create((0, utils_1.pathToUrl)(fileName), targetRange, targetRange, (0, utils_2.convertToLocationRange)(tsDoc, defs.textSpan));
|
||||
}));
|
||||
return result.filter(utils_1.isNotNullOrUndefined);
|
||||
}
|
||||
}
|
||||
exports.DefinitionsProviderImpl = DefinitionsProviderImpl;
|
||||
25
node_modules/@astrojs/language-server/dist/plugins/typescript/features/DiagnosticsProvider.d.ts
generated
vendored
Normal file
25
node_modules/@astrojs/language-server/dist/plugins/typescript/features/DiagnosticsProvider.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import type ts from 'typescript';
|
||||
import { CancellationToken, DiagnosticSeverity } from 'vscode-languageserver';
|
||||
import { Diagnostic } from 'vscode-languageserver-types';
|
||||
import { AstroDocument } from '../../../core/documents';
|
||||
import type { DiagnosticsProvider } from '../../interfaces';
|
||||
import type { LanguageServiceManager } from '../LanguageServiceManager';
|
||||
export declare enum DiagnosticCodes {
|
||||
SPREAD_EXPECTED = 1005,
|
||||
IS_NOT_A_MODULE = 2306,
|
||||
CANNOT_FIND_MODULE = 2307,
|
||||
DUPLICATED_JSX_ATTRIBUTES = 17001,
|
||||
CANT_RETURN_OUTSIDE_FUNC = 1108,
|
||||
ISOLATED_MODULE_COMPILE_ERR = 1208,
|
||||
TYPE_NOT_ASSIGNABLE = 2322,
|
||||
JSX_NO_CLOSING_TAG = 17008,
|
||||
JSX_ELEMENT_NO_CALL = 2604
|
||||
}
|
||||
export declare class DiagnosticsProviderImpl implements DiagnosticsProvider {
|
||||
private languageServiceManager;
|
||||
private ts;
|
||||
constructor(languageServiceManager: LanguageServiceManager);
|
||||
getDiagnostics(document: AstroDocument, _cancellationToken?: CancellationToken): Promise<Diagnostic[]>;
|
||||
private getTagBoundaries;
|
||||
mapSeverity(category: ts.DiagnosticCategory): DiagnosticSeverity;
|
||||
}
|
||||
249
node_modules/@astrojs/language-server/dist/plugins/typescript/features/DiagnosticsProvider.js
generated
vendored
Normal file
249
node_modules/@astrojs/language-server/dist/plugins/typescript/features/DiagnosticsProvider.js
generated
vendored
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.DiagnosticsProviderImpl = exports.DiagnosticCodes = void 0;
|
||||
const vscode_languageserver_1 = require("vscode-languageserver");
|
||||
const vscode_languageserver_types_1 = require("vscode-languageserver-types");
|
||||
const documents_1 = require("../../../core/documents");
|
||||
const utils_1 = require("../utils");
|
||||
// List of codes:
|
||||
// https://github.com/Microsoft/TypeScript/blob/main/src/compiler/diagnosticMessages.json
|
||||
var DiagnosticCodes;
|
||||
(function (DiagnosticCodes) {
|
||||
DiagnosticCodes[DiagnosticCodes["SPREAD_EXPECTED"] = 1005] = "SPREAD_EXPECTED";
|
||||
DiagnosticCodes[DiagnosticCodes["IS_NOT_A_MODULE"] = 2306] = "IS_NOT_A_MODULE";
|
||||
DiagnosticCodes[DiagnosticCodes["CANNOT_FIND_MODULE"] = 2307] = "CANNOT_FIND_MODULE";
|
||||
DiagnosticCodes[DiagnosticCodes["DUPLICATED_JSX_ATTRIBUTES"] = 17001] = "DUPLICATED_JSX_ATTRIBUTES";
|
||||
DiagnosticCodes[DiagnosticCodes["CANT_RETURN_OUTSIDE_FUNC"] = 1108] = "CANT_RETURN_OUTSIDE_FUNC";
|
||||
DiagnosticCodes[DiagnosticCodes["ISOLATED_MODULE_COMPILE_ERR"] = 1208] = "ISOLATED_MODULE_COMPILE_ERR";
|
||||
DiagnosticCodes[DiagnosticCodes["TYPE_NOT_ASSIGNABLE"] = 2322] = "TYPE_NOT_ASSIGNABLE";
|
||||
DiagnosticCodes[DiagnosticCodes["JSX_NO_CLOSING_TAG"] = 17008] = "JSX_NO_CLOSING_TAG";
|
||||
DiagnosticCodes[DiagnosticCodes["JSX_ELEMENT_NO_CALL"] = 2604] = "JSX_ELEMENT_NO_CALL";
|
||||
})(DiagnosticCodes = exports.DiagnosticCodes || (exports.DiagnosticCodes = {}));
|
||||
class DiagnosticsProviderImpl {
|
||||
constructor(languageServiceManager) {
|
||||
this.languageServiceManager = languageServiceManager;
|
||||
this.ts = languageServiceManager.docContext.ts;
|
||||
}
|
||||
async getDiagnostics(document, _cancellationToken) {
|
||||
// Don't return diagnostics for files inside node_modules. These are considered read-only
|
||||
// and they would pollute the output for astro check
|
||||
if (document.getFilePath()?.includes('/node_modules/') || document.getFilePath()?.includes('\\node_modules\\')) {
|
||||
return [];
|
||||
}
|
||||
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
||||
// If we have compiler errors, our TSX isn't valid so don't bother showing TS errors
|
||||
if (tsDoc.isInErrorState) {
|
||||
return [];
|
||||
}
|
||||
let scriptDiagnostics = [];
|
||||
document.scriptTags.forEach((scriptTag) => {
|
||||
const { filePath: scriptFilePath, snapshot: scriptTagSnapshot } = (0, utils_1.getScriptTagSnapshot)(tsDoc, document, scriptTag.container);
|
||||
const scriptDiagnostic = [
|
||||
...lang.getSyntacticDiagnostics(scriptFilePath),
|
||||
...lang.getSuggestionDiagnostics(scriptFilePath),
|
||||
...lang.getSemanticDiagnostics(scriptFilePath),
|
||||
]
|
||||
// We need to duplicate the diagnostic creation here because we can't map TS's diagnostics range to the original
|
||||
// file due to some internal cache inside TS that would cause it to being mapped twice in some cases
|
||||
.map((diagnostic) => ({
|
||||
range: (0, utils_1.convertRange)(scriptTagSnapshot, diagnostic),
|
||||
severity: this.mapSeverity(diagnostic.category),
|
||||
source: 'ts',
|
||||
message: this.ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'),
|
||||
code: diagnostic.code,
|
||||
tags: getDiagnosticTag(diagnostic),
|
||||
}))
|
||||
.map(mapRange(scriptTagSnapshot, document));
|
||||
scriptDiagnostics.push(...scriptDiagnostic);
|
||||
});
|
||||
const { script: scriptBoundaries } = this.getTagBoundaries(lang, tsDoc.filePath);
|
||||
const diagnostics = [
|
||||
...lang.getSyntacticDiagnostics(tsDoc.filePath),
|
||||
...lang.getSuggestionDiagnostics(tsDoc.filePath),
|
||||
...lang.getSemanticDiagnostics(tsDoc.filePath),
|
||||
].filter((diag) => {
|
||||
return isNoWithinBoundary(scriptBoundaries, diag, this.ts);
|
||||
});
|
||||
return [
|
||||
...diagnostics
|
||||
.map((diagnostic) => ({
|
||||
range: (0, utils_1.convertRange)(tsDoc, diagnostic),
|
||||
severity: this.mapSeverity(diagnostic.category),
|
||||
source: 'ts',
|
||||
message: this.ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'),
|
||||
code: diagnostic.code,
|
||||
tags: getDiagnosticTag(diagnostic),
|
||||
}))
|
||||
.map(mapRange(tsDoc, document)),
|
||||
...scriptDiagnostics,
|
||||
]
|
||||
.filter((diag) => {
|
||||
return (
|
||||
// Make sure the diagnostic is inside the document and not in generated code
|
||||
diag.range.start.line <= document.lineCount &&
|
||||
hasNoNegativeLines(diag) &&
|
||||
isNoCantReturnOutsideFunction(diag) &&
|
||||
isNoIsolatedModuleError(diag) &&
|
||||
isNoJsxCannotHaveMultipleAttrsError(diag));
|
||||
})
|
||||
.map(enhanceIfNecessary);
|
||||
}
|
||||
getTagBoundaries(lang, tsFilePath) {
|
||||
const program = lang.getProgram();
|
||||
const sourceFile = program?.getSourceFile(tsFilePath);
|
||||
const boundaries = {
|
||||
script: [],
|
||||
};
|
||||
if (!sourceFile) {
|
||||
return boundaries;
|
||||
}
|
||||
function findTags(parent, ts) {
|
||||
ts.forEachChild(parent, (node) => {
|
||||
if (ts.isJsxElement(node)) {
|
||||
let tagName = node.openingElement.tagName.getText();
|
||||
switch (tagName) {
|
||||
case 'script': {
|
||||
ts.getLineAndCharacterOfPosition(sourceFile, node.getStart());
|
||||
boundaries.script.push([node.getStart(), node.getEnd()]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
findTags(node, ts);
|
||||
});
|
||||
}
|
||||
findTags(sourceFile, this.ts);
|
||||
return boundaries;
|
||||
}
|
||||
mapSeverity(category) {
|
||||
switch (category) {
|
||||
case this.ts.DiagnosticCategory.Error:
|
||||
return vscode_languageserver_1.DiagnosticSeverity.Error;
|
||||
case this.ts.DiagnosticCategory.Warning:
|
||||
return vscode_languageserver_1.DiagnosticSeverity.Warning;
|
||||
case this.ts.DiagnosticCategory.Suggestion:
|
||||
return vscode_languageserver_1.DiagnosticSeverity.Hint;
|
||||
case this.ts.DiagnosticCategory.Message:
|
||||
return vscode_languageserver_1.DiagnosticSeverity.Information;
|
||||
default:
|
||||
return vscode_languageserver_1.DiagnosticSeverity.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.DiagnosticsProviderImpl = DiagnosticsProviderImpl;
|
||||
function isWithinBoundaries(boundaries, start) {
|
||||
for (let [bstart, bend] of boundaries) {
|
||||
if (start > bstart && start < bend) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function diagnosticIsWithinBoundaries(sourceFile, boundaries, diagnostic, ts) {
|
||||
if ('start' in diagnostic) {
|
||||
if (diagnostic.start == null)
|
||||
return false;
|
||||
return isWithinBoundaries(boundaries, diagnostic.start);
|
||||
}
|
||||
if (!sourceFile)
|
||||
return false;
|
||||
let startRange = diagnostic.range.start;
|
||||
let pos = ts.getPositionOfLineAndCharacter(sourceFile, startRange.line, startRange.character);
|
||||
return isWithinBoundaries(boundaries, pos);
|
||||
}
|
||||
function isNoWithinBoundary(boundaries, diagnostic, ts) {
|
||||
return !diagnosticIsWithinBoundaries(undefined, boundaries, diagnostic, ts);
|
||||
}
|
||||
function mapRange(snapshot, _document) {
|
||||
return (diagnostic) => {
|
||||
let range = (0, documents_1.mapRangeToOriginal)(snapshot, diagnostic.range);
|
||||
return { ...diagnostic, range };
|
||||
};
|
||||
}
|
||||
/**
|
||||
* In some rare cases mapping of diagnostics does not work and produces negative lines.
|
||||
* We filter out these diagnostics with negative lines because else the LSP
|
||||
* apparently has a hiccup and does not show any diagnostics at all.
|
||||
*/
|
||||
function hasNoNegativeLines(diagnostic) {
|
||||
return diagnostic.range.start.line >= 0 && diagnostic.range.end.line >= 0;
|
||||
}
|
||||
/**
|
||||
* Astro allows multiple attributes to have the same name
|
||||
*/
|
||||
function isNoJsxCannotHaveMultipleAttrsError(diagnostic) {
|
||||
return diagnostic.code !== DiagnosticCodes.DUPLICATED_JSX_ATTRIBUTES;
|
||||
}
|
||||
/**
|
||||
* Ignore "Can't return outside of function body"
|
||||
* Since the frontmatter is at the top level, users trying to return a Response for SSR mode run into this
|
||||
*/
|
||||
function isNoCantReturnOutsideFunction(diagnostic) {
|
||||
return diagnostic.code !== DiagnosticCodes.CANT_RETURN_OUTSIDE_FUNC;
|
||||
}
|
||||
/**
|
||||
* When the content of the file is invalid and can't be parsed properly for TSX generation, TS will show an error about
|
||||
* how the current module can't be compiled under --isolatedModule, this is confusing to users so let's ignore this
|
||||
*/
|
||||
function isNoIsolatedModuleError(diagnostic) {
|
||||
return diagnostic.code !== DiagnosticCodes.ISOLATED_MODULE_COMPILE_ERR;
|
||||
}
|
||||
/**
|
||||
* Some diagnostics have JSX-specific nomenclature or unclear description. Enhance them for more clarity.
|
||||
*/
|
||||
function enhanceIfNecessary(diagnostic) {
|
||||
// When the language integrations are not installed, the content of the imported snapshot is empty
|
||||
// As such, it triggers the "is not a module error", which we can enhance with a more helpful message for the related framework
|
||||
if (diagnostic.code === DiagnosticCodes.IS_NOT_A_MODULE) {
|
||||
if (diagnostic.message.includes('.svelte')) {
|
||||
diagnostic.message +=
|
||||
'\n\nIs the `@astrojs/svelte` package installed? You can add it to your project by running the following command: `astro add svelte`. If already installed, restarting the language server might be necessary in order for the change to take effect';
|
||||
}
|
||||
if (diagnostic.message.includes('.vue')) {
|
||||
diagnostic.message +=
|
||||
'\n\nIs the `@astrojs/vue` package installed? You can add it to your project by running the following command: `astro add vue`. If already installed, restarting the language server might be necessary in order for the change to take effect';
|
||||
}
|
||||
return diagnostic;
|
||||
}
|
||||
if (diagnostic.code === DiagnosticCodes.CANNOT_FIND_MODULE && diagnostic.message.includes('astro:content')) {
|
||||
diagnostic.message +=
|
||||
"\n\nIf you're using content collections, make sure to run `astro dev`, `astro build` or `astro sync` to first generate the types so you can import from them. If you already ran one of those commands, restarting the language server might be necessary in order for the change to take effect";
|
||||
return diagnostic;
|
||||
}
|
||||
// JSX element has no closing tag. JSX -> HTML
|
||||
if (diagnostic.code === DiagnosticCodes.JSX_NO_CLOSING_TAG) {
|
||||
return {
|
||||
...diagnostic,
|
||||
message: diagnostic.message.replace('JSX', 'HTML'),
|
||||
};
|
||||
}
|
||||
// JSX Element can't be constructed or called. This happens on syntax errors / invalid components
|
||||
if (diagnostic.code === DiagnosticCodes.JSX_ELEMENT_NO_CALL) {
|
||||
return {
|
||||
...diagnostic,
|
||||
message: diagnostic.message
|
||||
.replace('JSX element type', 'Component')
|
||||
.replace('does not have any construct or call signatures.', 'is not a valid component.\n\nIf this is a Svelte or Vue component, it might have a syntax error that makes it impossible to parse.'),
|
||||
};
|
||||
}
|
||||
// For the rare case where an user might try to put a client directive on something that is not a component
|
||||
if (diagnostic.code === DiagnosticCodes.TYPE_NOT_ASSIGNABLE) {
|
||||
if (diagnostic.message.includes("Property 'client:") && diagnostic.message.includes("to type 'HTMLAttributes")) {
|
||||
return {
|
||||
...diagnostic,
|
||||
message: 'Client directives are only available on framework components',
|
||||
};
|
||||
}
|
||||
}
|
||||
return diagnostic;
|
||||
}
|
||||
function getDiagnosticTag(diagnostic) {
|
||||
const tags = [];
|
||||
if (diagnostic.reportsUnnecessary) {
|
||||
tags.push(vscode_languageserver_types_1.DiagnosticTag.Unnecessary);
|
||||
}
|
||||
if (diagnostic.reportsDeprecated) {
|
||||
tags.push(vscode_languageserver_types_1.DiagnosticTag.Deprecated);
|
||||
}
|
||||
return tags;
|
||||
}
|
||||
11
node_modules/@astrojs/language-server/dist/plugins/typescript/features/DocumentSymbolsProvider.d.ts
generated
vendored
Normal file
11
node_modules/@astrojs/language-server/dist/plugins/typescript/features/DocumentSymbolsProvider.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { SymbolInformation } from 'vscode-languageserver-types';
|
||||
import { AstroDocument } from '../../../core/documents';
|
||||
import type { DocumentSymbolsProvider } from '../../interfaces';
|
||||
import type { LanguageServiceManager } from '../LanguageServiceManager';
|
||||
export declare class DocumentSymbolsProviderImpl implements DocumentSymbolsProvider {
|
||||
private languageServiceManager;
|
||||
private ts;
|
||||
constructor(languageServiceManager: LanguageServiceManager);
|
||||
getDocumentSymbols(document: AstroDocument): Promise<SymbolInformation[]>;
|
||||
private collectSymbols;
|
||||
}
|
||||
67
node_modules/@astrojs/language-server/dist/plugins/typescript/features/DocumentSymbolsProvider.js
generated
vendored
Normal file
67
node_modules/@astrojs/language-server/dist/plugins/typescript/features/DocumentSymbolsProvider.js
generated
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.DocumentSymbolsProviderImpl = void 0;
|
||||
const vscode_languageserver_types_1 = require("vscode-languageserver-types");
|
||||
const utils_1 = require("../utils");
|
||||
class DocumentSymbolsProviderImpl {
|
||||
constructor(languageServiceManager) {
|
||||
this.languageServiceManager = languageServiceManager;
|
||||
this.ts = languageServiceManager.docContext.ts;
|
||||
}
|
||||
async getDocumentSymbols(document) {
|
||||
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
||||
const navTree = lang.getNavigationTree(tsDoc.filePath + '?documentSymbols');
|
||||
if (!navTree) {
|
||||
return [];
|
||||
}
|
||||
const symbols = [];
|
||||
this.collectSymbols(navTree, document, undefined, (symbol) => symbols.push(symbol));
|
||||
const originalContainerName = symbols[0].name;
|
||||
const result = [];
|
||||
// Add a "Frontmatter" namespace for the frontmatter if we have a closed one
|
||||
if (document.astroMeta.frontmatter.state === 'closed') {
|
||||
result.push(vscode_languageserver_types_1.SymbolInformation.create('Frontmatter', vscode_languageserver_types_1.SymbolKind.Namespace, vscode_languageserver_types_1.Range.create(document.positionAt(document.astroMeta.frontmatter.startOffset), document.positionAt(document.astroMeta.frontmatter.endOffset)), document.getURL()));
|
||||
}
|
||||
// Add a "Template" namespace for everything under the frontmatter
|
||||
result.push(vscode_languageserver_types_1.SymbolInformation.create('Template', vscode_languageserver_types_1.SymbolKind.Namespace, vscode_languageserver_types_1.Range.create(document.positionAt(document.astroMeta.frontmatter.endOffset ?? 0), document.positionAt(document.getTextLength())), document.getURL()));
|
||||
for (let symbol of symbols.splice(1)) {
|
||||
if (document.offsetAt(symbol.location.range.end) >= (document.astroMeta.content.firstNonWhitespaceOffset ?? 0)) {
|
||||
if (symbol.containerName === originalContainerName) {
|
||||
symbol.containerName = 'Template';
|
||||
}
|
||||
// For some reason, it seems like TypeScript thinks that the "class" attribute is a real class, weird
|
||||
if (symbol.kind === vscode_languageserver_types_1.SymbolKind.Class && symbol.name === '<class>') {
|
||||
const node = document.html.findNodeAt(document.offsetAt(symbol.location.range.start));
|
||||
if (node.attributes?.class) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remove the exported function in our TSX output from the symbols
|
||||
if (document.offsetAt(symbol.location.range.start) >= document.getTextLength()) {
|
||||
continue;
|
||||
}
|
||||
result.push(symbol);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
collectSymbols(item, document, container, cb) {
|
||||
for (const span of item.spans) {
|
||||
const symbol = vscode_languageserver_types_1.SymbolInformation.create(item.text, (0, utils_1.symbolKindFromString)(item.kind), vscode_languageserver_types_1.Range.create(document.positionAt(span.start), document.positionAt(span.start + span.length)), document.getURL(), container);
|
||||
// TypeScript gives us kind modifiers as a string instead of an array
|
||||
const kindModifiers = new Set(item.kindModifiers.split(/,|\s+/g));
|
||||
if (kindModifiers.has(this.ts.ScriptElementKindModifier.deprecatedModifier)) {
|
||||
if (!symbol.tags)
|
||||
symbol.tags = [];
|
||||
symbol.tags.push(vscode_languageserver_types_1.SymbolTag.Deprecated);
|
||||
}
|
||||
cb(symbol);
|
||||
}
|
||||
if (item.childItems) {
|
||||
for (const child of item.childItems) {
|
||||
this.collectSymbols(child, document, item.text, cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.DocumentSymbolsProviderImpl = DocumentSymbolsProviderImpl;
|
||||
9
node_modules/@astrojs/language-server/dist/plugins/typescript/features/FileReferencesProvider.d.ts
generated
vendored
Normal file
9
node_modules/@astrojs/language-server/dist/plugins/typescript/features/FileReferencesProvider.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import { Location } from 'vscode-languageserver';
|
||||
import { AstroDocument } from '../../../core/documents';
|
||||
import { FileReferencesProvider } from '../../interfaces';
|
||||
import { LanguageServiceManager } from '../LanguageServiceManager';
|
||||
export declare class FileReferencesProviderImpl implements FileReferencesProvider {
|
||||
private languageServiceManager;
|
||||
constructor(languageServiceManager: LanguageServiceManager);
|
||||
fileReferences(document: AstroDocument): Promise<Location[] | null>;
|
||||
}
|
||||
27
node_modules/@astrojs/language-server/dist/plugins/typescript/features/FileReferencesProvider.js
generated
vendored
Normal file
27
node_modules/@astrojs/language-server/dist/plugins/typescript/features/FileReferencesProvider.js
generated
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.FileReferencesProviderImpl = void 0;
|
||||
const vscode_languageserver_1 = require("vscode-languageserver");
|
||||
const utils_1 = require("../../../utils");
|
||||
const utils_2 = require("../utils");
|
||||
const utils_3 = require("./utils");
|
||||
class FileReferencesProviderImpl {
|
||||
constructor(languageServiceManager) {
|
||||
this.languageServiceManager = languageServiceManager;
|
||||
}
|
||||
async fileReferences(document) {
|
||||
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
||||
const references = lang.getFileReferences(tsDoc.filePath);
|
||||
if (!references) {
|
||||
return null;
|
||||
}
|
||||
const snapshots = new utils_3.SnapshotMap(this.languageServiceManager);
|
||||
snapshots.set(tsDoc.filePath, tsDoc);
|
||||
const locations = await Promise.all(references.map(async (ref) => {
|
||||
const snapshot = await snapshots.retrieve(ref.fileName);
|
||||
return vscode_languageserver_1.Location.create((0, utils_1.pathToUrl)(ref.fileName), (0, utils_2.convertToLocationRange)(snapshot, ref.textSpan));
|
||||
}));
|
||||
return locations;
|
||||
}
|
||||
}
|
||||
exports.FileReferencesProviderImpl = FileReferencesProviderImpl;
|
||||
12
node_modules/@astrojs/language-server/dist/plugins/typescript/features/FoldingRangesProvider.d.ts
generated
vendored
Normal file
12
node_modules/@astrojs/language-server/dist/plugins/typescript/features/FoldingRangesProvider.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import type ts from 'typescript';
|
||||
import { FoldingRange } from 'vscode-languageserver';
|
||||
import type { AstroDocument } from '../../../core/documents';
|
||||
import type { FoldingRangesProvider } from '../../interfaces';
|
||||
import type { LanguageServiceManager } from '../LanguageServiceManager';
|
||||
export declare class FoldingRangesProviderImpl implements FoldingRangesProvider {
|
||||
private languageServiceManager;
|
||||
private ts;
|
||||
constructor(languageServiceManager: LanguageServiceManager);
|
||||
getFoldingRanges(document: AstroDocument): Promise<FoldingRange[] | null>;
|
||||
transformFoldingRangeKind(tsKind: ts.OutliningSpanKind): "imports" | "comment" | "region" | undefined;
|
||||
}
|
||||
71
node_modules/@astrojs/language-server/dist/plugins/typescript/features/FoldingRangesProvider.js
generated
vendored
Normal file
71
node_modules/@astrojs/language-server/dist/plugins/typescript/features/FoldingRangesProvider.js
generated
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.FoldingRangesProviderImpl = void 0;
|
||||
const vscode_languageserver_1 = require("vscode-languageserver");
|
||||
const utils_1 = require("../utils");
|
||||
class FoldingRangesProviderImpl {
|
||||
constructor(languageServiceManager) {
|
||||
this.languageServiceManager = languageServiceManager;
|
||||
this.ts = languageServiceManager.docContext.ts;
|
||||
}
|
||||
async getFoldingRanges(document) {
|
||||
const html = document.html;
|
||||
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
||||
const outliningSpans = lang.getOutliningSpans(tsDoc.filePath).filter((span) => {
|
||||
const node = html.findNodeAt(span.textSpan.start);
|
||||
// Due to how our TSX output transform those tags into function calls or template literals
|
||||
// TypeScript thinks of those as outlining spans, which is fine but we don't want folding ranges for those
|
||||
return node.tag !== 'script' && node.tag !== 'style';
|
||||
});
|
||||
const scriptOutliningSpans = [];
|
||||
document.scriptTags.forEach((scriptTag) => {
|
||||
const { snapshot: scriptTagSnapshot, filePath: scriptFilePath } = (0, utils_1.getScriptTagSnapshot)(tsDoc, document, scriptTag.container);
|
||||
scriptOutliningSpans.push(...lang.getOutliningSpans(scriptFilePath).map((span) => {
|
||||
span.textSpan.start = document.offsetAt(scriptTagSnapshot.getOriginalPosition(scriptTagSnapshot.positionAt(span.textSpan.start)));
|
||||
return span;
|
||||
}));
|
||||
});
|
||||
const foldingRanges = [];
|
||||
for (const span of [...outliningSpans, ...scriptOutliningSpans]) {
|
||||
const start = tsDoc.getOriginalPosition(tsDoc.positionAt(span.textSpan.start));
|
||||
const end = adjustFoldingEnd(start, document.positionAt(document.offsetAt(start) + span.textSpan.length), document);
|
||||
// When using this method for generating folding ranges, TypeScript tend to return some
|
||||
// one line / one character ones that we should be able to safely ignore
|
||||
if (start.line === end.line && start.character === end.character) {
|
||||
continue;
|
||||
}
|
||||
// Ignore folding ranges that are from unmapped regions
|
||||
if (start.line < 0 || end.line < 0) {
|
||||
continue;
|
||||
}
|
||||
foldingRanges.push(vscode_languageserver_1.FoldingRange.create(start.line, end.line, start.character, end.character, this.transformFoldingRangeKind(span.kind)));
|
||||
}
|
||||
return foldingRanges;
|
||||
}
|
||||
transformFoldingRangeKind(tsKind) {
|
||||
switch (tsKind) {
|
||||
case this.ts.OutliningSpanKind.Comment:
|
||||
return vscode_languageserver_1.FoldingRangeKind.Comment;
|
||||
case this.ts.OutliningSpanKind.Imports:
|
||||
return vscode_languageserver_1.FoldingRangeKind.Imports;
|
||||
case this.ts.OutliningSpanKind.Region:
|
||||
return vscode_languageserver_1.FoldingRangeKind.Region;
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.FoldingRangesProviderImpl = FoldingRangesProviderImpl;
|
||||
// https://github.com/microsoft/vscode/blob/bed61166fb604e519e82e4d1d1ed839bc45d65f8/extensions/typescript-language-features/src/languageFeatures/folding.ts#L61-L73
|
||||
function adjustFoldingEnd(start, end, document) {
|
||||
// workaround for #47240
|
||||
if (end.character > 0) {
|
||||
const foldEndCharacter = document.getText({
|
||||
start: { line: end.line, character: end.character - 1 },
|
||||
end,
|
||||
});
|
||||
if (['}', ']', ')', '`'].includes(foldEndCharacter)) {
|
||||
const endOffset = Math.max(document.offsetAt({ line: end.line, character: 0 }) - 1, document.offsetAt(start));
|
||||
return document.positionAt(endOffset);
|
||||
}
|
||||
}
|
||||
return end;
|
||||
}
|
||||
10
node_modules/@astrojs/language-server/dist/plugins/typescript/features/HoverProvider.d.ts
generated
vendored
Normal file
10
node_modules/@astrojs/language-server/dist/plugins/typescript/features/HoverProvider.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import type { Hover, Position } from 'vscode-languageserver';
|
||||
import { AstroDocument } from '../../../core/documents';
|
||||
import type { HoverProvider } from '../../interfaces';
|
||||
import type { LanguageServiceManager } from '../LanguageServiceManager';
|
||||
export declare class HoverProviderImpl implements HoverProvider {
|
||||
private languageServiceManager;
|
||||
private ts;
|
||||
constructor(languageServiceManager: LanguageServiceManager);
|
||||
doHover(document: AstroDocument, position: Position): Promise<Hover | null>;
|
||||
}
|
||||
50
node_modules/@astrojs/language-server/dist/plugins/typescript/features/HoverProvider.js
generated
vendored
Normal file
50
node_modules/@astrojs/language-server/dist/plugins/typescript/features/HoverProvider.js
generated
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.HoverProviderImpl = void 0;
|
||||
const documents_1 = require("../../../core/documents");
|
||||
const previewer_1 = require("../previewer");
|
||||
const utils_1 = require("../utils");
|
||||
const partsMap = new Map([['JSX attribute', 'HTML attribute']]);
|
||||
class HoverProviderImpl {
|
||||
constructor(languageServiceManager) {
|
||||
this.languageServiceManager = languageServiceManager;
|
||||
this.ts = languageServiceManager.docContext.ts;
|
||||
}
|
||||
async doHover(document, position) {
|
||||
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
||||
const offset = tsDoc.offsetAt(tsDoc.getGeneratedPosition(position));
|
||||
const html = document.html;
|
||||
const documentOffset = document.offsetAt(position);
|
||||
const node = html.findNodeAt(documentOffset);
|
||||
let info;
|
||||
if (node.tag === 'script') {
|
||||
const { snapshot: scriptTagSnapshot, filePath: scriptFilePath, offset: scriptOffset, } = (0, utils_1.getScriptTagSnapshot)(tsDoc, document, node, position);
|
||||
info = lang.getQuickInfoAtPosition(scriptFilePath, scriptOffset);
|
||||
if (info) {
|
||||
info.textSpan.start = (0, documents_1.mapScriptSpanStartToSnapshot)(info.textSpan, scriptTagSnapshot, tsDoc);
|
||||
}
|
||||
}
|
||||
else {
|
||||
info = lang.getQuickInfoAtPosition(tsDoc.filePath, offset);
|
||||
}
|
||||
if (!info) {
|
||||
return null;
|
||||
}
|
||||
const textSpan = info.textSpan;
|
||||
const displayParts = (info.displayParts || []).map((value) => ({
|
||||
text: partsMap.has(value.text) ? partsMap.get(value.text) : value.text,
|
||||
kind: value.kind,
|
||||
}));
|
||||
const declaration = this.ts.displayPartsToString(displayParts);
|
||||
const documentation = (0, previewer_1.getMarkdownDocumentation)(info.documentation, info.tags, this.ts);
|
||||
// https://microsoft.github.io/language-server-protocol/specification#textDocument_hover
|
||||
const contents = ['```typescript', declaration, '```']
|
||||
.concat(documentation ? ['---', documentation] : [])
|
||||
.join('\n');
|
||||
return (0, documents_1.mapObjWithRangeToOriginal)(tsDoc, {
|
||||
range: (0, utils_1.convertRange)(tsDoc, textSpan),
|
||||
contents,
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.HoverProviderImpl = HoverProviderImpl;
|
||||
9
node_modules/@astrojs/language-server/dist/plugins/typescript/features/ImplementationsProvider.d.ts
generated
vendored
Normal file
9
node_modules/@astrojs/language-server/dist/plugins/typescript/features/ImplementationsProvider.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import { Location, Position } from 'vscode-languageserver-types';
|
||||
import { AstroDocument } from '../../../core/documents';
|
||||
import { ImplementationProvider } from '../../interfaces';
|
||||
import { LanguageServiceManager } from '../LanguageServiceManager';
|
||||
export declare class ImplementationsProviderImpl implements ImplementationProvider {
|
||||
private languageServiceManager;
|
||||
constructor(languageServiceManager: LanguageServiceManager);
|
||||
getImplementation(document: AstroDocument, position: Position): Promise<Location[] | null>;
|
||||
}
|
||||
53
node_modules/@astrojs/language-server/dist/plugins/typescript/features/ImplementationsProvider.js
generated
vendored
Normal file
53
node_modules/@astrojs/language-server/dist/plugins/typescript/features/ImplementationsProvider.js
generated
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ImplementationsProviderImpl = void 0;
|
||||
const vscode_languageserver_types_1 = require("vscode-languageserver-types");
|
||||
const documents_1 = require("../../../core/documents");
|
||||
const utils_1 = require("../../../utils");
|
||||
const utils_2 = require("../utils");
|
||||
const utils_3 = require("./utils");
|
||||
class ImplementationsProviderImpl {
|
||||
constructor(languageServiceManager) {
|
||||
this.languageServiceManager = languageServiceManager;
|
||||
}
|
||||
async getImplementation(document, position) {
|
||||
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
||||
const fragmentPosition = tsDoc.getGeneratedPosition(position);
|
||||
const fragmentOffset = tsDoc.offsetAt(fragmentPosition);
|
||||
const html = document.html;
|
||||
const offset = document.offsetAt(position);
|
||||
const node = document.html.findNodeAt(offset);
|
||||
let implementations;
|
||||
if (node.tag === 'script') {
|
||||
const { snapshot: scriptTagSnapshot, filePath: scriptFilePath, offset: scriptOffset, } = (0, utils_2.getScriptTagSnapshot)(tsDoc, document, node, position);
|
||||
implementations = lang.getImplementationAtPosition(scriptFilePath, scriptOffset);
|
||||
if (implementations) {
|
||||
implementations = implementations.map((impl) => {
|
||||
const isInSameFile = impl.fileName === scriptFilePath;
|
||||
impl.fileName = isInSameFile ? tsDoc.filePath : impl.fileName;
|
||||
if (isInSameFile) {
|
||||
impl.textSpan.start = (0, documents_1.mapScriptSpanStartToSnapshot)(impl.textSpan, scriptTagSnapshot, tsDoc);
|
||||
}
|
||||
return impl;
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
implementations = lang.getImplementationAtPosition(tsDoc.filePath, fragmentOffset);
|
||||
}
|
||||
const snapshots = new utils_3.SnapshotMap(this.languageServiceManager);
|
||||
snapshots.set(tsDoc.filePath, tsDoc);
|
||||
if (!implementations) {
|
||||
return null;
|
||||
}
|
||||
const result = await Promise.all(implementations.map(async (implementation) => {
|
||||
const snapshot = await snapshots.retrieve(implementation.fileName);
|
||||
const range = (0, documents_1.mapRangeToOriginal)(snapshot, (0, utils_2.convertRange)(snapshot, implementation.textSpan));
|
||||
if (range.start.line >= 0 && range.end.line >= 0) {
|
||||
return vscode_languageserver_types_1.Location.create((0, utils_1.pathToUrl)(implementation.fileName), range);
|
||||
}
|
||||
}));
|
||||
return result.filter(utils_1.isNotNullOrUndefined);
|
||||
}
|
||||
}
|
||||
exports.ImplementationsProviderImpl = ImplementationsProviderImpl;
|
||||
13
node_modules/@astrojs/language-server/dist/plugins/typescript/features/InlayHintsProvider.d.ts
generated
vendored
Normal file
13
node_modules/@astrojs/language-server/dist/plugins/typescript/features/InlayHintsProvider.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import { InlayHint } from 'vscode-languageserver';
|
||||
import { Range } from 'vscode-languageserver-types';
|
||||
import type { ConfigManager } from '../../../core/config';
|
||||
import type { AstroDocument } from '../../../core/documents';
|
||||
import type { InlayHintsProvider } from '../../interfaces';
|
||||
import type { LanguageServiceManager } from '../LanguageServiceManager';
|
||||
export declare class InlayHintsProviderImpl implements InlayHintsProvider {
|
||||
private languageServiceManager;
|
||||
private configManager;
|
||||
private ts;
|
||||
constructor(languageServiceManager: LanguageServiceManager, configManager: ConfigManager);
|
||||
getInlayHints(document: AstroDocument, range: Range): Promise<InlayHint[]>;
|
||||
}
|
||||
30
node_modules/@astrojs/language-server/dist/plugins/typescript/features/InlayHintsProvider.js
generated
vendored
Normal file
30
node_modules/@astrojs/language-server/dist/plugins/typescript/features/InlayHintsProvider.js
generated
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.InlayHintsProviderImpl = void 0;
|
||||
const vscode_languageserver_1 = require("vscode-languageserver");
|
||||
const vscode_languageserver_types_1 = require("vscode-languageserver-types");
|
||||
class InlayHintsProviderImpl {
|
||||
constructor(languageServiceManager, configManager) {
|
||||
this.languageServiceManager = languageServiceManager;
|
||||
this.configManager = configManager;
|
||||
this.ts = languageServiceManager.docContext.ts;
|
||||
}
|
||||
async getInlayHints(document, range) {
|
||||
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
||||
const start = tsDoc.offsetAt(tsDoc.getGeneratedPosition(range.start));
|
||||
const end = tsDoc.offsetAt(tsDoc.getGeneratedPosition(range.end));
|
||||
const tsPreferences = await this.configManager.getTSPreferences(document);
|
||||
const inlayHints = lang.provideInlayHints(tsDoc.filePath, { start, length: end - start }, tsPreferences);
|
||||
return inlayHints.map((hint) => {
|
||||
const result = vscode_languageserver_1.InlayHint.create(tsDoc.getOriginalPosition(tsDoc.positionAt(hint.position)), hint.text, hint.kind === this.ts.InlayHintKind.Type
|
||||
? vscode_languageserver_types_1.InlayHintKind.Type
|
||||
: hint.kind === this.ts.InlayHintKind.Parameter
|
||||
? vscode_languageserver_types_1.InlayHintKind.Parameter
|
||||
: undefined);
|
||||
result.paddingLeft = hint.whitespaceBefore;
|
||||
result.paddingRight = hint.whitespaceAfter;
|
||||
return result;
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.InlayHintsProviderImpl = InlayHintsProviderImpl;
|
||||
9
node_modules/@astrojs/language-server/dist/plugins/typescript/features/ReferencesProvider.d.ts
generated
vendored
Normal file
9
node_modules/@astrojs/language-server/dist/plugins/typescript/features/ReferencesProvider.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import { Location, Position, ReferenceContext } from 'vscode-languageserver-types';
|
||||
import { AstroDocument } from '../../../core/documents';
|
||||
import type { FindReferencesProvider } from '../../interfaces';
|
||||
import type { LanguageServiceManager } from '../LanguageServiceManager';
|
||||
export declare class FindReferencesProviderImpl implements FindReferencesProvider {
|
||||
private languageServiceManager;
|
||||
constructor(languageServiceManager: LanguageServiceManager);
|
||||
findReferences(document: AstroDocument, position: Position, context: ReferenceContext): Promise<Location[] | null>;
|
||||
}
|
||||
55
node_modules/@astrojs/language-server/dist/plugins/typescript/features/ReferencesProvider.js
generated
vendored
Normal file
55
node_modules/@astrojs/language-server/dist/plugins/typescript/features/ReferencesProvider.js
generated
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.FindReferencesProviderImpl = void 0;
|
||||
const vscode_languageserver_types_1 = require("vscode-languageserver-types");
|
||||
const documents_1 = require("../../../core/documents");
|
||||
const utils_1 = require("../../../utils");
|
||||
const utils_2 = require("../utils");
|
||||
const utils_3 = require("./utils");
|
||||
class FindReferencesProviderImpl {
|
||||
constructor(languageServiceManager) {
|
||||
this.languageServiceManager = languageServiceManager;
|
||||
}
|
||||
async findReferences(document, position, context) {
|
||||
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
||||
const fragmentPosition = tsDoc.getGeneratedPosition(position);
|
||||
const fragmentOffset = tsDoc.offsetAt(fragmentPosition);
|
||||
const offset = document.offsetAt(position);
|
||||
const node = document.html.findNodeAt(offset);
|
||||
let references;
|
||||
if (node.tag === 'script') {
|
||||
const { snapshot: scriptTagSnapshot, filePath: scriptFilePath, offset: scriptOffset, } = (0, utils_2.getScriptTagSnapshot)(tsDoc, document, node, position);
|
||||
references = lang.getReferencesAtPosition(scriptFilePath, scriptOffset);
|
||||
if (references) {
|
||||
references = references.map((ref) => {
|
||||
const isInSameFile = ref.fileName === scriptFilePath;
|
||||
ref.fileName = isInSameFile ? tsDoc.filePath : ref.fileName;
|
||||
if (isInSameFile) {
|
||||
ref.textSpan.start = (0, documents_1.mapScriptSpanStartToSnapshot)(ref.textSpan, scriptTagSnapshot, tsDoc);
|
||||
}
|
||||
return ref;
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
references = lang.getReferencesAtPosition(tsDoc.filePath, fragmentOffset);
|
||||
}
|
||||
if (!references) {
|
||||
return null;
|
||||
}
|
||||
const snapshots = new utils_3.SnapshotMap(this.languageServiceManager);
|
||||
snapshots.set(tsDoc.filePath, tsDoc);
|
||||
const result = await Promise.all(references.map(async (reference) => {
|
||||
if (!context.includeDeclaration) {
|
||||
return null;
|
||||
}
|
||||
const snapshot = await snapshots.retrieve(reference.fileName);
|
||||
const range = (0, documents_1.mapRangeToOriginal)(snapshot, (0, utils_2.convertRange)(snapshot, reference.textSpan));
|
||||
if (range.start.line >= 0 && range.end.line >= 0) {
|
||||
return vscode_languageserver_types_1.Location.create((0, utils_1.pathToUrl)(reference.fileName), range);
|
||||
}
|
||||
}));
|
||||
return result.filter(utils_1.isNotNullOrUndefined);
|
||||
}
|
||||
}
|
||||
exports.FindReferencesProviderImpl = FindReferencesProviderImpl;
|
||||
13
node_modules/@astrojs/language-server/dist/plugins/typescript/features/RenameProvider.d.ts
generated
vendored
Normal file
13
node_modules/@astrojs/language-server/dist/plugins/typescript/features/RenameProvider.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import type { Position, Range, WorkspaceEdit } from 'vscode-languageserver-types';
|
||||
import type { ConfigManager } from '../../../core/config';
|
||||
import { AstroDocument } from '../../../core/documents';
|
||||
import type { RenameProvider } from '../../interfaces';
|
||||
import type { LanguageServiceManager } from '../LanguageServiceManager';
|
||||
export declare class RenameProviderImpl implements RenameProvider {
|
||||
private languageServiceManager;
|
||||
private configManager;
|
||||
private ts;
|
||||
constructor(languageServiceManager: LanguageServiceManager, configManager: ConfigManager);
|
||||
prepareRename(document: AstroDocument, position: Position): Promise<Range | null>;
|
||||
rename(document: AstroDocument, position: Position, newName: string): Promise<WorkspaceEdit | null>;
|
||||
}
|
||||
60
node_modules/@astrojs/language-server/dist/plugins/typescript/features/RenameProvider.js
generated
vendored
Normal file
60
node_modules/@astrojs/language-server/dist/plugins/typescript/features/RenameProvider.js
generated
vendored
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.RenameProviderImpl = void 0;
|
||||
const documents_1 = require("../../../core/documents");
|
||||
const utils_1 = require("../../../utils");
|
||||
const utils_2 = require("../utils");
|
||||
const utils_3 = require("./utils");
|
||||
class RenameProviderImpl {
|
||||
constructor(languageServiceManager, configManager) {
|
||||
this.languageServiceManager = languageServiceManager;
|
||||
this.configManager = configManager;
|
||||
this.ts = languageServiceManager.docContext.ts;
|
||||
}
|
||||
async prepareRename(document, position) {
|
||||
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
||||
const offset = tsDoc.offsetAt(tsDoc.getGeneratedPosition(position));
|
||||
// If our TSX isn't valid, we can't rename safely, so let's abort
|
||||
if (tsDoc.isInErrorState) {
|
||||
return null;
|
||||
}
|
||||
// TODO: Allow renaming of import paths
|
||||
// This requires a bit of work, because we need to create files for the new import paths
|
||||
const renameInfo = lang.getRenameInfo(tsDoc.filePath, offset, { allowRenameOfImportPath: false });
|
||||
if (!renameInfo.canRename) {
|
||||
return null;
|
||||
}
|
||||
return (0, documents_1.mapRangeToOriginal)(tsDoc, (0, utils_2.convertRange)(tsDoc, renameInfo.triggerSpan));
|
||||
}
|
||||
async rename(document, position, newName) {
|
||||
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
||||
const offset = tsDoc.offsetAt(tsDoc.getGeneratedPosition(position));
|
||||
const { providePrefixAndSuffixTextForRename } = await this.configManager.getTSPreferences(document);
|
||||
let renames = lang.findRenameLocations(tsDoc.filePath, offset, false, false, providePrefixAndSuffixTextForRename);
|
||||
if (!renames) {
|
||||
return null;
|
||||
}
|
||||
const docs = new utils_3.SnapshotMap(this.languageServiceManager);
|
||||
docs.set(tsDoc.filePath, tsDoc);
|
||||
const mappedRenames = await Promise.all(renames.map(async (rename) => {
|
||||
const snapshot = await docs.retrieve(rename.fileName);
|
||||
return {
|
||||
...rename,
|
||||
range: (0, documents_1.mapRangeToOriginal)(snapshot, (0, utils_2.convertRange)(snapshot, rename.textSpan)),
|
||||
newName,
|
||||
};
|
||||
}));
|
||||
return mappedRenames.reduce((acc, loc) => {
|
||||
const uri = (0, utils_1.pathToUrl)(loc.fileName);
|
||||
if (!acc.changes[uri]) {
|
||||
acc.changes[uri] = [];
|
||||
}
|
||||
acc.changes[uri].push({
|
||||
newText: (loc.prefixText || '') + (loc.newName || newName) + (loc.suffixText || ''),
|
||||
range: loc.range,
|
||||
});
|
||||
return acc;
|
||||
}, { changes: {} });
|
||||
}
|
||||
}
|
||||
exports.RenameProviderImpl = RenameProviderImpl;
|
||||
16
node_modules/@astrojs/language-server/dist/plugins/typescript/features/SemanticTokenProvider.d.ts
generated
vendored
Normal file
16
node_modules/@astrojs/language-server/dist/plugins/typescript/features/SemanticTokenProvider.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import { CancellationToken, Range, SemanticTokens } from 'vscode-languageserver';
|
||||
import { AstroDocument } from '../../../core/documents';
|
||||
import type { SemanticTokensProvider } from '../../interfaces';
|
||||
import type { LanguageServiceManager } from '../LanguageServiceManager';
|
||||
export declare class SemanticTokensProviderImpl implements SemanticTokensProvider {
|
||||
private languageServiceManager;
|
||||
private ts;
|
||||
constructor(languageServiceManager: LanguageServiceManager);
|
||||
getSemanticTokens(document: AstroDocument, range?: Range, cancellationToken?: CancellationToken): Promise<SemanticTokens | null>;
|
||||
private mapToOrigin;
|
||||
/**
|
||||
* TSClassification = (TokenType + 1) << TokenEncodingConsts.typeOffset + TokenModifier
|
||||
*/
|
||||
private getTokenTypeFromClassification;
|
||||
private getTokenModifierFromClassification;
|
||||
}
|
||||
75
node_modules/@astrojs/language-server/dist/plugins/typescript/features/SemanticTokenProvider.js
generated
vendored
Normal file
75
node_modules/@astrojs/language-server/dist/plugins/typescript/features/SemanticTokenProvider.js
generated
vendored
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SemanticTokensProviderImpl = void 0;
|
||||
const vscode_languageserver_1 = require("vscode-languageserver");
|
||||
const documents_1 = require("../../../core/documents");
|
||||
class SemanticTokensProviderImpl {
|
||||
constructor(languageServiceManager) {
|
||||
this.languageServiceManager = languageServiceManager;
|
||||
this.ts = languageServiceManager.docContext.ts;
|
||||
}
|
||||
async getSemanticTokens(document, range, cancellationToken) {
|
||||
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
||||
if (cancellationToken?.isCancellationRequested) {
|
||||
return null;
|
||||
}
|
||||
const start = range ? tsDoc.offsetAt(tsDoc.getGeneratedPosition(range.start)) : 0;
|
||||
const { spans } = lang.getEncodedSemanticClassifications(tsDoc.filePath, {
|
||||
start,
|
||||
length: range
|
||||
? tsDoc.offsetAt(tsDoc.getGeneratedPosition(range.end)) - start
|
||||
: // We don't want tokens for things added by astro2tsx
|
||||
tsDoc.getFullText().lastIndexOf('export default function ') || tsDoc.getLength(),
|
||||
}, this.ts.SemanticClassificationFormat.TwentyTwenty);
|
||||
const tokens = [];
|
||||
let i = 0;
|
||||
while (i < spans.length) {
|
||||
const offset = spans[i++];
|
||||
const generatedLength = spans[i++];
|
||||
const classification = spans[i++];
|
||||
const originalPosition = this.mapToOrigin(document, tsDoc, offset, generatedLength);
|
||||
if (!originalPosition) {
|
||||
continue;
|
||||
}
|
||||
const [line, character, length] = originalPosition;
|
||||
const classificationType = this.getTokenTypeFromClassification(classification);
|
||||
if (classificationType < 0) {
|
||||
continue;
|
||||
}
|
||||
const modifier = this.getTokenModifierFromClassification(classification);
|
||||
tokens.push([line, character, length, classificationType, modifier]);
|
||||
}
|
||||
const sorted = tokens.sort((a, b) => {
|
||||
const [lineA, charA] = a;
|
||||
const [lineB, charB] = b;
|
||||
return lineA - lineB || charA - charB;
|
||||
});
|
||||
const builder = new vscode_languageserver_1.SemanticTokensBuilder();
|
||||
sorted.forEach((tokenData) => builder.push(...tokenData));
|
||||
const build = builder.build();
|
||||
return build;
|
||||
}
|
||||
mapToOrigin(document, snapshot, generatedOffset, generatedLength) {
|
||||
const range = {
|
||||
start: snapshot.positionAt(generatedOffset),
|
||||
end: snapshot.positionAt(generatedOffset + generatedLength),
|
||||
};
|
||||
const { start: startPosition, end: endPosition } = (0, documents_1.mapRangeToOriginal)(snapshot, range);
|
||||
if (startPosition.line < 0 || endPosition.line < 0) {
|
||||
return;
|
||||
}
|
||||
const startOffset = document.offsetAt(startPosition);
|
||||
const endOffset = document.offsetAt(endPosition);
|
||||
return [startPosition.line, startPosition.character, endOffset - startOffset, startOffset];
|
||||
}
|
||||
/**
|
||||
* TSClassification = (TokenType + 1) << TokenEncodingConsts.typeOffset + TokenModifier
|
||||
*/
|
||||
getTokenTypeFromClassification(tsClassification) {
|
||||
return (tsClassification >> 8 /* TokenEncodingConsts.typeOffset */) - 1;
|
||||
}
|
||||
getTokenModifierFromClassification(tsClassification) {
|
||||
return tsClassification & 255 /* TokenEncodingConsts.modifierMask */;
|
||||
}
|
||||
}
|
||||
exports.SemanticTokensProviderImpl = SemanticTokensProviderImpl;
|
||||
22
node_modules/@astrojs/language-server/dist/plugins/typescript/features/SignatureHelpProvider.d.ts
generated
vendored
Normal file
22
node_modules/@astrojs/language-server/dist/plugins/typescript/features/SignatureHelpProvider.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import { CancellationToken, Position, SignatureHelp, SignatureHelpContext } from 'vscode-languageserver';
|
||||
import type { AstroDocument } from '../../../core/documents';
|
||||
import type { SignatureHelpProvider } from '../../interfaces';
|
||||
import type { LanguageServiceManager } from '../LanguageServiceManager';
|
||||
export declare class SignatureHelpProviderImpl implements SignatureHelpProvider {
|
||||
private languageServiceManager;
|
||||
private ts;
|
||||
constructor(languageServiceManager: LanguageServiceManager);
|
||||
private static readonly triggerCharacters;
|
||||
private static readonly retriggerCharacters;
|
||||
getSignatureHelp(document: AstroDocument, position: Position, context: SignatureHelpContext | undefined, cancellationToken?: CancellationToken): Promise<SignatureHelp | null>;
|
||||
private isReTrigger;
|
||||
private isTriggerCharacter;
|
||||
/**
|
||||
* adopted from https://github.com/microsoft/vscode/blob/265a2f6424dfbd3a9788652c7d376a7991d049a3/extensions/typescript-language-features/src/languageFeatures/signatureHelp.ts#L103
|
||||
*/
|
||||
private toTsTriggerReason;
|
||||
/**
|
||||
* adopted from https://github.com/microsoft/vscode/blob/265a2f6424dfbd3a9788652c7d376a7991d049a3/extensions/typescript-language-features/src/languageFeatures/signatureHelp.ts#L73
|
||||
*/
|
||||
private toSignatureHelpInformation;
|
||||
}
|
||||
111
node_modules/@astrojs/language-server/dist/plugins/typescript/features/SignatureHelpProvider.js
generated
vendored
Normal file
111
node_modules/@astrojs/language-server/dist/plugins/typescript/features/SignatureHelpProvider.js
generated
vendored
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SignatureHelpProviderImpl = void 0;
|
||||
const vscode_languageserver_1 = require("vscode-languageserver");
|
||||
const previewer_1 = require("../previewer");
|
||||
const utils_1 = require("../utils");
|
||||
class SignatureHelpProviderImpl {
|
||||
constructor(languageServiceManager) {
|
||||
this.languageServiceManager = languageServiceManager;
|
||||
this.ts = languageServiceManager.docContext.ts;
|
||||
}
|
||||
async getSignatureHelp(document, position, context, cancellationToken) {
|
||||
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
||||
if (cancellationToken?.isCancellationRequested) {
|
||||
return null;
|
||||
}
|
||||
const offset = tsDoc.offsetAt(tsDoc.getGeneratedPosition(position));
|
||||
const node = document.html.findNodeAt(offset);
|
||||
let info;
|
||||
const triggerReason = this.toTsTriggerReason(context);
|
||||
if (node.tag === 'script') {
|
||||
const { filePath: scriptFilePath, offset: scriptOffset } = (0, utils_1.getScriptTagSnapshot)(tsDoc, document, node, position);
|
||||
info = lang.getSignatureHelpItems(scriptFilePath, scriptOffset, triggerReason ? { triggerReason } : undefined);
|
||||
}
|
||||
else {
|
||||
info = lang.getSignatureHelpItems(tsDoc.filePath, offset, triggerReason ? { triggerReason } : undefined);
|
||||
}
|
||||
if (!info) {
|
||||
return null;
|
||||
}
|
||||
const signatures = info.items.map((item) => this.toSignatureHelpInformation(item, this.ts));
|
||||
return {
|
||||
signatures,
|
||||
activeSignature: info.selectedItemIndex,
|
||||
activeParameter: info.argumentIndex,
|
||||
};
|
||||
}
|
||||
isReTrigger(isRetrigger, triggerCharacter) {
|
||||
return (isRetrigger &&
|
||||
(this.isTriggerCharacter(triggerCharacter) ||
|
||||
SignatureHelpProviderImpl.retriggerCharacters.includes(triggerCharacter)));
|
||||
}
|
||||
isTriggerCharacter(triggerCharacter) {
|
||||
return SignatureHelpProviderImpl.triggerCharacters.includes(triggerCharacter);
|
||||
}
|
||||
/**
|
||||
* adopted from https://github.com/microsoft/vscode/blob/265a2f6424dfbd3a9788652c7d376a7991d049a3/extensions/typescript-language-features/src/languageFeatures/signatureHelp.ts#L103
|
||||
*/
|
||||
toTsTriggerReason(context) {
|
||||
switch (context?.triggerKind) {
|
||||
case vscode_languageserver_1.SignatureHelpTriggerKind.TriggerCharacter:
|
||||
if (context.triggerCharacter) {
|
||||
if (this.isReTrigger(context.isRetrigger, context.triggerCharacter)) {
|
||||
return { kind: 'retrigger', triggerCharacter: context.triggerCharacter };
|
||||
}
|
||||
if (this.isTriggerCharacter(context.triggerCharacter)) {
|
||||
return {
|
||||
kind: 'characterTyped',
|
||||
triggerCharacter: context.triggerCharacter,
|
||||
};
|
||||
}
|
||||
}
|
||||
return { kind: 'invoked' };
|
||||
case vscode_languageserver_1.SignatureHelpTriggerKind.ContentChange:
|
||||
return context.isRetrigger ? { kind: 'retrigger' } : { kind: 'invoked' };
|
||||
case vscode_languageserver_1.SignatureHelpTriggerKind.Invoked:
|
||||
default:
|
||||
return { kind: 'invoked' };
|
||||
}
|
||||
}
|
||||
/**
|
||||
* adopted from https://github.com/microsoft/vscode/blob/265a2f6424dfbd3a9788652c7d376a7991d049a3/extensions/typescript-language-features/src/languageFeatures/signatureHelp.ts#L73
|
||||
*/
|
||||
toSignatureHelpInformation(item, ts) {
|
||||
const [prefixLabel, separatorLabel, suffixLabel] = [
|
||||
item.prefixDisplayParts,
|
||||
item.separatorDisplayParts,
|
||||
item.suffixDisplayParts,
|
||||
].map(this.ts.displayPartsToString);
|
||||
let textIndex = prefixLabel.length;
|
||||
let signatureLabel = '';
|
||||
const parameters = [];
|
||||
const lastIndex = item.parameters.length - 1;
|
||||
item.parameters.forEach((parameter, index) => {
|
||||
const label = ts.displayPartsToString(parameter.displayParts);
|
||||
const startIndex = textIndex;
|
||||
const endIndex = textIndex + label.length;
|
||||
const doc = ts.displayPartsToString(parameter.documentation);
|
||||
signatureLabel += label;
|
||||
parameters.push(vscode_languageserver_1.ParameterInformation.create([startIndex, endIndex], doc));
|
||||
if (index < lastIndex) {
|
||||
textIndex = endIndex + separatorLabel.length;
|
||||
signatureLabel += separatorLabel;
|
||||
}
|
||||
});
|
||||
const signatureDocumentation = (0, previewer_1.getMarkdownDocumentation)(item.documentation, item.tags.filter((tag) => tag.name !== 'param'), ts);
|
||||
return {
|
||||
label: prefixLabel + signatureLabel + suffixLabel,
|
||||
documentation: signatureDocumentation
|
||||
? {
|
||||
value: signatureDocumentation,
|
||||
kind: vscode_languageserver_1.MarkupKind.Markdown,
|
||||
}
|
||||
: undefined,
|
||||
parameters,
|
||||
};
|
||||
}
|
||||
}
|
||||
SignatureHelpProviderImpl.triggerCharacters = ['(', ',', '<'];
|
||||
SignatureHelpProviderImpl.retriggerCharacters = [')'];
|
||||
exports.SignatureHelpProviderImpl = SignatureHelpProviderImpl;
|
||||
9
node_modules/@astrojs/language-server/dist/plugins/typescript/features/TypeDefinitionsProvider.d.ts
generated
vendored
Normal file
9
node_modules/@astrojs/language-server/dist/plugins/typescript/features/TypeDefinitionsProvider.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import { Location, Position } from 'vscode-languageserver-protocol';
|
||||
import { AstroDocument } from '../../../core/documents';
|
||||
import type { TypeDefinitionsProvider } from '../../interfaces';
|
||||
import type { LanguageServiceManager } from '../LanguageServiceManager';
|
||||
export declare class TypeDefinitionsProviderImpl implements TypeDefinitionsProvider {
|
||||
private languageServiceManager;
|
||||
constructor(languageServiceManager: LanguageServiceManager);
|
||||
getTypeDefinitions(document: AstroDocument, position: Position): Promise<Location[]>;
|
||||
}
|
||||
54
node_modules/@astrojs/language-server/dist/plugins/typescript/features/TypeDefinitionsProvider.js
generated
vendored
Normal file
54
node_modules/@astrojs/language-server/dist/plugins/typescript/features/TypeDefinitionsProvider.js
generated
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.TypeDefinitionsProviderImpl = void 0;
|
||||
const vscode_languageserver_protocol_1 = require("vscode-languageserver-protocol");
|
||||
const documents_1 = require("../../../core/documents");
|
||||
const utils_1 = require("../../../utils");
|
||||
const utils_2 = require("../utils");
|
||||
const utils_3 = require("./utils");
|
||||
class TypeDefinitionsProviderImpl {
|
||||
constructor(languageServiceManager) {
|
||||
this.languageServiceManager = languageServiceManager;
|
||||
}
|
||||
async getTypeDefinitions(document, position) {
|
||||
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
||||
const fragmentPosition = tsDoc.getGeneratedPosition(position);
|
||||
const fragmentOffset = tsDoc.offsetAt(fragmentPosition);
|
||||
const html = document.html;
|
||||
const offset = document.offsetAt(position);
|
||||
const node = html.findNodeAt(offset);
|
||||
let typeDefs;
|
||||
if (node.tag === 'script') {
|
||||
const { snapshot: scriptTagSnapshot, filePath: scriptFilePath, offset: scriptOffset, } = (0, utils_2.getScriptTagSnapshot)(tsDoc, document, node, position);
|
||||
typeDefs = lang.getTypeDefinitionAtPosition(scriptFilePath, scriptOffset);
|
||||
if (typeDefs) {
|
||||
typeDefs = typeDefs.map((def) => {
|
||||
const isInSameFile = def.fileName === scriptFilePath;
|
||||
def.fileName = isInSameFile ? tsDoc.filePath : def.fileName;
|
||||
if (isInSameFile) {
|
||||
def.textSpan.start = (0, documents_1.mapScriptSpanStartToSnapshot)(def.textSpan, scriptTagSnapshot, tsDoc);
|
||||
}
|
||||
return def;
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
typeDefs = lang.getTypeDefinitionAtPosition(tsDoc.filePath, fragmentOffset);
|
||||
}
|
||||
const snapshots = new utils_3.SnapshotMap(this.languageServiceManager);
|
||||
snapshots.set(tsDoc.filePath, tsDoc);
|
||||
if (!typeDefs) {
|
||||
return [];
|
||||
}
|
||||
const result = await Promise.all(typeDefs.map(async (typeDef) => {
|
||||
const snapshot = await snapshots.retrieve(typeDef.fileName);
|
||||
const fileName = (0, utils_2.ensureRealFilePath)(typeDef.fileName);
|
||||
const range = (0, documents_1.mapRangeToOriginal)(snapshot, (0, utils_2.convertRange)(snapshot, typeDef.textSpan));
|
||||
if (range.start.line >= 0 && range.end.line >= 0) {
|
||||
return vscode_languageserver_protocol_1.Location.create((0, utils_1.pathToUrl)(fileName), range);
|
||||
}
|
||||
}));
|
||||
return result.filter(utils_1.isNotNullOrUndefined);
|
||||
}
|
||||
}
|
||||
exports.TypeDefinitionsProviderImpl = TypeDefinitionsProviderImpl;
|
||||
14
node_modules/@astrojs/language-server/dist/plugins/typescript/features/utils.d.ts
generated
vendored
Normal file
14
node_modules/@astrojs/language-server/dist/plugins/typescript/features/utils.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import type ts from 'typescript';
|
||||
import type { Position } from 'vscode-languageserver';
|
||||
import type { LanguageServiceManager } from '../LanguageServiceManager';
|
||||
import type { DocumentSnapshot } from '../snapshots/DocumentSnapshot';
|
||||
export declare function isPartOfImportStatement(text: string, position: Position): boolean;
|
||||
export declare class SnapshotMap {
|
||||
private languageServiceManager;
|
||||
private map;
|
||||
constructor(languageServiceManager: LanguageServiceManager);
|
||||
set(fileName: string, snapshot: DocumentSnapshot): void;
|
||||
get(fileName: string): DocumentSnapshot | undefined;
|
||||
retrieve(fileName: string): Promise<DocumentSnapshot>;
|
||||
}
|
||||
export declare function findContainingNode<T extends ts.Node>(node: ts.Node, textSpan: ts.TextSpan, predicate: (node: ts.Node) => node is T): T | undefined;
|
||||
48
node_modules/@astrojs/language-server/dist/plugins/typescript/features/utils.js
generated
vendored
Normal file
48
node_modules/@astrojs/language-server/dist/plugins/typescript/features/utils.js
generated
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.findContainingNode = exports.SnapshotMap = exports.isPartOfImportStatement = void 0;
|
||||
const documents_1 = require("../../../core/documents");
|
||||
function isPartOfImportStatement(text, position) {
|
||||
const line = (0, documents_1.getLineAtPosition)(position, text);
|
||||
return /\s*from\s+["'][^"']*/.test(line.slice(0, position.character));
|
||||
}
|
||||
exports.isPartOfImportStatement = isPartOfImportStatement;
|
||||
class SnapshotMap {
|
||||
constructor(languageServiceManager) {
|
||||
this.languageServiceManager = languageServiceManager;
|
||||
this.map = new Map();
|
||||
}
|
||||
set(fileName, snapshot) {
|
||||
this.map.set(fileName, snapshot);
|
||||
}
|
||||
get(fileName) {
|
||||
return this.map.get(fileName);
|
||||
}
|
||||
async retrieve(fileName) {
|
||||
let snapshot = this.get(fileName);
|
||||
if (!snapshot) {
|
||||
const snap = await this.languageServiceManager.getSnapshot(fileName);
|
||||
this.set(fileName, snap);
|
||||
snapshot = snap;
|
||||
}
|
||||
return snapshot;
|
||||
}
|
||||
}
|
||||
exports.SnapshotMap = SnapshotMap;
|
||||
function findContainingNode(node, textSpan, predicate) {
|
||||
const children = node.getChildren();
|
||||
const end = textSpan.start + textSpan.length;
|
||||
for (const child of children) {
|
||||
if (!(child.getStart() <= textSpan.start && child.getEnd() >= end)) {
|
||||
continue;
|
||||
}
|
||||
if (predicate(child)) {
|
||||
return child;
|
||||
}
|
||||
const foundInChildren = findContainingNode(child, textSpan, predicate);
|
||||
if (foundInChildren) {
|
||||
return foundInChildren;
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.findContainingNode = findContainingNode;
|
||||
42
node_modules/@astrojs/language-server/dist/plugins/typescript/language-service.d.ts
generated
vendored
Normal file
42
node_modules/@astrojs/language-server/dist/plugins/typescript/language-service.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import type ts from 'typescript';
|
||||
import type { TextDocumentContentChangeEvent } from 'vscode-languageserver';
|
||||
import type { ConfigManager } from '../../core/config';
|
||||
import type { AstroDocument } from '../../core/documents';
|
||||
import { DocumentSnapshot } from './snapshots/DocumentSnapshot';
|
||||
import { GlobalSnapshotManager, SnapshotManager } from './snapshots/SnapshotManager';
|
||||
export interface LanguageServiceContainer {
|
||||
readonly tsconfigPath: string;
|
||||
readonly compilerOptions: ts.CompilerOptions;
|
||||
/**
|
||||
* @internal Public for tests only
|
||||
*/
|
||||
readonly snapshotManager: SnapshotManager;
|
||||
getService(): ts.LanguageService;
|
||||
updateSnapshot(documentOrFilePath: AstroDocument | string, ts: typeof import('typescript/lib/tsserverlibrary')): DocumentSnapshot;
|
||||
deleteSnapshot(filePath: string): void;
|
||||
updateProjectFiles(): void;
|
||||
updateNonAstroFile(fileName: string, changes?: TextDocumentContentChangeEvent[], text?: string): void;
|
||||
/**
|
||||
* Checks if a file is present in the project.
|
||||
* Unlike `fileBelongsToProject`, this doesn't run a file search on disk.
|
||||
*/
|
||||
hasFile(filePath: string): boolean;
|
||||
/**
|
||||
* Careful, don't call often, or it will hurt performance.
|
||||
*/
|
||||
fileBelongsToProject(filePath: string): boolean;
|
||||
}
|
||||
export interface LanguageServiceDocumentContext {
|
||||
createDocument: (fileName: string, content: string) => AstroDocument;
|
||||
globalSnapshotManager: GlobalSnapshotManager;
|
||||
configManager: ConfigManager;
|
||||
ts: typeof import('typescript/lib/tsserverlibrary');
|
||||
tsLocalized: Record<string, string> | undefined;
|
||||
}
|
||||
export declare function getLanguageService(path: string, workspaceUris: string[], docContext: LanguageServiceDocumentContext): Promise<LanguageServiceContainer>;
|
||||
export declare function forAllLanguageServices(cb: (service: LanguageServiceContainer) => any): Promise<void>;
|
||||
/**
|
||||
* @param tsconfigPath has to be absolute
|
||||
* @param docContext
|
||||
*/
|
||||
export declare function getLanguageServiceForTsconfig(tsconfigPath: string, docContext: LanguageServiceDocumentContext, workspaceUris: string[]): Promise<LanguageServiceContainer>;
|
||||
278
node_modules/@astrojs/language-server/dist/plugins/typescript/language-service.js
generated
vendored
Normal file
278
node_modules/@astrojs/language-server/dist/plugins/typescript/language-service.js
generated
vendored
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getLanguageServiceForTsconfig = exports.forAllLanguageServices = exports.getLanguageService = void 0;
|
||||
const path_1 = require("path");
|
||||
const utils_1 = require("../../utils");
|
||||
const module_loader_1 = require("./module-loader");
|
||||
const DocumentSnapshot_1 = require("./snapshots/DocumentSnapshot");
|
||||
const SnapshotManager_1 = require("./snapshots/SnapshotManager");
|
||||
const DocumentSnapshotUtils = __importStar(require("./snapshots/utils"));
|
||||
const utils_2 = require("./utils");
|
||||
const services = new Map();
|
||||
async function getLanguageService(path, workspaceUris, docContext) {
|
||||
const tsconfigPath = (0, utils_2.findTsConfigPath)(path, workspaceUris, docContext.ts);
|
||||
return getLanguageServiceForTsconfig(tsconfigPath, docContext, workspaceUris);
|
||||
}
|
||||
exports.getLanguageService = getLanguageService;
|
||||
async function forAllLanguageServices(cb) {
|
||||
for (const service of services.values()) {
|
||||
cb(await service);
|
||||
}
|
||||
}
|
||||
exports.forAllLanguageServices = forAllLanguageServices;
|
||||
/**
|
||||
* @param tsconfigPath has to be absolute
|
||||
* @param docContext
|
||||
*/
|
||||
async function getLanguageServiceForTsconfig(tsconfigPath, docContext, workspaceUris) {
|
||||
let service;
|
||||
if (docContext.configManager.shouldRefreshTSServices) {
|
||||
services.clear();
|
||||
docContext.configManager.shouldRefreshTSServices = false;
|
||||
}
|
||||
if (services.has(tsconfigPath)) {
|
||||
service = await services.get(tsconfigPath);
|
||||
}
|
||||
else {
|
||||
const newService = createLanguageService(tsconfigPath, docContext, workspaceUris);
|
||||
services.set(tsconfigPath, newService);
|
||||
service = await newService;
|
||||
}
|
||||
return service;
|
||||
}
|
||||
exports.getLanguageServiceForTsconfig = getLanguageServiceForTsconfig;
|
||||
async function createLanguageService(tsconfigPath, docContext, workspaceUris) {
|
||||
const tsconfigRoot = tsconfigPath ? (0, path_1.dirname)(tsconfigPath) : process.cwd();
|
||||
const workspacePaths = workspaceUris.map((uri) => (0, utils_1.urlToPath)(uri));
|
||||
const workspacePath = workspacePaths.find((p) => tsconfigRoot.startsWith(p)) || workspacePaths[0];
|
||||
const astroInstall = (0, utils_1.getAstroInstall)([tsconfigRoot, workspacePath]);
|
||||
const workspaceUri = workspacePath ? (0, utils_1.pathToUrl)(workspacePath) : '';
|
||||
const config = (await docContext.configManager.getConfig('astro.typescript', workspaceUri)) ?? {};
|
||||
const allowArbitraryAttrs = config.allowArbitraryAttributes ?? false;
|
||||
// `raw` here represent the tsconfig merged with any extended config
|
||||
const { compilerOptions, fileNames: files, raw: fullConfig } = getParsedTSConfig();
|
||||
let projectVersion = 0;
|
||||
const snapshotManager = new SnapshotManager_1.SnapshotManager(docContext.globalSnapshotManager, files, fullConfig, tsconfigRoot || process.cwd(), docContext.ts);
|
||||
const astroModuleLoader = (0, module_loader_1.createAstroModuleLoader)(getScriptSnapshot, compilerOptions, docContext.ts);
|
||||
const scriptFileNames = [];
|
||||
if (astroInstall) {
|
||||
scriptFileNames.push(...['./env.d.ts', './astro-jsx.d.ts'].map((f) => docContext.ts.sys.resolvePath((0, path_1.resolve)(astroInstall.path, f))));
|
||||
}
|
||||
let languageServerDirectory;
|
||||
try {
|
||||
languageServerDirectory = (0, path_1.dirname)(require.resolve('@astrojs/language-server'));
|
||||
}
|
||||
catch (e) {
|
||||
languageServerDirectory = __dirname;
|
||||
}
|
||||
// Fallback to internal types when Astro is not installed or the Astro version is too old
|
||||
if (!astroInstall ||
|
||||
((astroInstall.version.major === 0 || astroInstall.version.full === '1.0.0-beta.0') &&
|
||||
!astroInstall.version.full.startsWith('0.0.0-rc-')) // 1.0.0's RC is considered to be 0.0.0, so we have to check for it
|
||||
) {
|
||||
scriptFileNames.push(...['../types/astro-jsx.d.ts', '../types/env.d.ts'].map((f) => docContext.ts.sys.resolvePath((0, path_1.resolve)(languageServerDirectory, f))));
|
||||
console.warn("Couldn't load types from Astro, using internal types instead");
|
||||
}
|
||||
if (allowArbitraryAttrs) {
|
||||
const arbitraryAttrsDTS = docContext.ts.sys.resolvePath((0, path_1.resolve)(languageServerDirectory, '../types/arbitrary-attrs.d.ts'));
|
||||
scriptFileNames.push(arbitraryAttrsDTS);
|
||||
}
|
||||
const host = {
|
||||
getNewLine: () => docContext.ts.sys.newLine,
|
||||
useCaseSensitiveFileNames: () => docContext.ts.sys.useCaseSensitiveFileNames,
|
||||
getDirectories: docContext.ts.sys.getDirectories,
|
||||
resolveModuleNames: astroModuleLoader.resolveModuleNames,
|
||||
readFile: astroModuleLoader.readFile,
|
||||
fileExists: astroModuleLoader.fileExists,
|
||||
readDirectory: astroModuleLoader.readDirectory,
|
||||
getCompilationSettings: () => compilerOptions,
|
||||
getCurrentDirectory: () => tsconfigRoot,
|
||||
getDefaultLibFileName: docContext.ts.getDefaultLibFilePath,
|
||||
getProjectVersion: () => projectVersion.toString(),
|
||||
getScriptFileNames: () => Array.from(new Set([...snapshotManager.getProjectFileNames(), ...snapshotManager.getFileNames(), ...scriptFileNames])),
|
||||
getScriptSnapshot,
|
||||
getScriptKind: (fileName) => getScriptSnapshot(fileName).scriptKind,
|
||||
getScriptVersion: (fileName) => getScriptSnapshot(fileName).version.toString(),
|
||||
};
|
||||
if (docContext.tsLocalized) {
|
||||
host.getLocalizedDiagnosticMessages = () => docContext.tsLocalized;
|
||||
}
|
||||
let languageService = docContext.ts.createLanguageService(host);
|
||||
docContext.globalSnapshotManager.onChange(() => {
|
||||
projectVersion++;
|
||||
});
|
||||
return {
|
||||
tsconfigPath,
|
||||
compilerOptions,
|
||||
getService: () => languageService,
|
||||
updateSnapshot,
|
||||
deleteSnapshot,
|
||||
updateProjectFiles,
|
||||
updateNonAstroFile,
|
||||
hasFile,
|
||||
fileBelongsToProject,
|
||||
snapshotManager,
|
||||
};
|
||||
function deleteSnapshot(filePath) {
|
||||
astroModuleLoader.deleteFromModuleCache(filePath);
|
||||
snapshotManager.delete(filePath);
|
||||
}
|
||||
function updateSnapshot(documentOrFilePath) {
|
||||
return typeof documentOrFilePath === 'string'
|
||||
? updateSnapshotFromFilePath(documentOrFilePath)
|
||||
: updateSnapshotFromDocument(documentOrFilePath);
|
||||
}
|
||||
function updateSnapshotFromDocument(document) {
|
||||
const filePath = document.getFilePath() || '';
|
||||
const prevSnapshot = snapshotManager.get(filePath);
|
||||
if (prevSnapshot?.version === document.version) {
|
||||
return prevSnapshot;
|
||||
}
|
||||
if (!prevSnapshot) {
|
||||
astroModuleLoader.deleteUnresolvedResolutionsFromCache(filePath);
|
||||
}
|
||||
const newSnapshot = DocumentSnapshotUtils.createFromDocument(document, docContext.ts);
|
||||
snapshotManager.set(filePath, newSnapshot);
|
||||
const scriptTagSnapshots = createScriptTagsSnapshots(filePath, document);
|
||||
scriptTagSnapshots.forEach((snapshot) => {
|
||||
snapshotManager.set(snapshot.filePath, snapshot);
|
||||
newSnapshot.scriptTagSnapshots?.push(snapshot);
|
||||
});
|
||||
if (prevSnapshot && prevSnapshot.scriptKind !== newSnapshot.scriptKind) {
|
||||
// Restart language service as it doesn't handle script kind changes.
|
||||
languageService.dispose();
|
||||
languageService = docContext.ts.createLanguageService(host);
|
||||
}
|
||||
return newSnapshot;
|
||||
}
|
||||
function updateSnapshotFromFilePath(filePath) {
|
||||
const prevSnapshot = snapshotManager.get(filePath);
|
||||
if (prevSnapshot) {
|
||||
return prevSnapshot;
|
||||
}
|
||||
astroModuleLoader.deleteUnresolvedResolutionsFromCache(filePath);
|
||||
const newSnapshot = DocumentSnapshotUtils.createFromFilePath(filePath, docContext.createDocument, docContext.ts);
|
||||
snapshotManager.set(filePath, newSnapshot);
|
||||
return newSnapshot;
|
||||
}
|
||||
function getScriptSnapshot(fileName) {
|
||||
const realFileName = (0, utils_2.ensureRealFilePath)(fileName);
|
||||
let doc = snapshotManager.get(realFileName);
|
||||
if (doc) {
|
||||
if ((0, utils_2.isDocumentSymbolsPath)(fileName)) {
|
||||
return createDocumentSymbolSnapshot(doc);
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
astroModuleLoader.deleteUnresolvedResolutionsFromCache(realFileName);
|
||||
doc = DocumentSnapshotUtils.createFromFilePath(realFileName, docContext.createDocument, docContext.ts);
|
||||
snapshotManager.set(realFileName, doc);
|
||||
if ((0, utils_2.isDocumentSymbolsPath)(fileName)) {
|
||||
return createDocumentSymbolSnapshot(doc);
|
||||
}
|
||||
// If we needed to create an Astro snapshot, also create its script tags snapshots
|
||||
if ((0, utils_2.isAstroFilePath)(realFileName)) {
|
||||
const document = doc.parent;
|
||||
const scriptTagSnapshots = createScriptTagsSnapshots(realFileName, document);
|
||||
scriptTagSnapshots.forEach((snapshot) => {
|
||||
snapshotManager.set(snapshot.filePath, snapshot);
|
||||
doc.scriptTagSnapshots?.push(snapshot);
|
||||
});
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
function updateProjectFiles() {
|
||||
projectVersion++;
|
||||
snapshotManager.updateProjectFiles();
|
||||
}
|
||||
function hasFile(filePath) {
|
||||
return snapshotManager.has(filePath);
|
||||
}
|
||||
function fileBelongsToProject(filePath) {
|
||||
filePath = (0, utils_1.normalizePath)(filePath);
|
||||
return hasFile(filePath) || getParsedTSConfig().fileNames.includes(filePath);
|
||||
}
|
||||
function updateNonAstroFile(fileName, changes, text) {
|
||||
if (!snapshotManager.has(fileName)) {
|
||||
astroModuleLoader.deleteUnresolvedResolutionsFromCache(fileName);
|
||||
}
|
||||
snapshotManager.updateNonAstroFile(fileName, changes, text);
|
||||
}
|
||||
function createScriptTagsSnapshots(fileName, document) {
|
||||
return document.scriptTags.map((scriptTag, index) => {
|
||||
const scriptTagLanguage = (0, utils_2.getScriptTagLanguage)(scriptTag);
|
||||
const scriptFilePath = fileName + `.__script${index}.${scriptTagLanguage}`;
|
||||
const scriptSnapshot = new DocumentSnapshot_1.ScriptTagDocumentSnapshot(scriptTag, document, scriptFilePath, scriptTagLanguage === 'ts' ? docContext.ts.ScriptKind.TS : docContext.ts.ScriptKind.JS);
|
||||
return scriptSnapshot;
|
||||
});
|
||||
}
|
||||
function createDocumentSymbolSnapshot(doc) {
|
||||
return new DocumentSnapshot_1.TypeScriptDocumentSnapshot(doc.version, doc.filePath, doc.parent.getText(), docContext.ts.ScriptKind.Unknown, false);
|
||||
}
|
||||
function getParsedTSConfig() {
|
||||
let configJson = (tsconfigPath && docContext.ts.readConfigFile(tsconfigPath, docContext.ts.sys.readFile).config) || {};
|
||||
// Delete include so that .astro files don't get mistakenly excluded by the user
|
||||
delete configJson.include;
|
||||
// If the user supplied exclude, let's use theirs otherwise, use ours
|
||||
configJson.exclude ?? (configJson.exclude = getDefaultExclude());
|
||||
// Everything here will always, unconditionally, be in the resulting config
|
||||
const forcedCompilerOptions = {
|
||||
noEmit: true,
|
||||
declaration: false,
|
||||
resolveJsonModule: true,
|
||||
allowSyntheticDefaultImports: true,
|
||||
allowNonTsExtensions: true,
|
||||
allowJs: true,
|
||||
jsx: docContext.ts.JsxEmit.Preserve,
|
||||
jsxImportSource: undefined,
|
||||
jsxFactory: 'astroHTML',
|
||||
module: docContext.ts.ModuleKind.ESNext,
|
||||
target: docContext.ts.ScriptTarget.ESNext,
|
||||
isolatedModules: true,
|
||||
};
|
||||
const project = docContext.ts.parseJsonConfigFileContent(configJson, docContext.ts.sys, tsconfigRoot, forcedCompilerOptions, tsconfigPath, undefined, [
|
||||
{ extension: 'vue', isMixedContent: true, scriptKind: docContext.ts.ScriptKind.Deferred },
|
||||
{ extension: 'svelte', isMixedContent: true, scriptKind: docContext.ts.ScriptKind.Deferred },
|
||||
{ extension: 'astro', isMixedContent: true, scriptKind: docContext.ts.ScriptKind.Deferred },
|
||||
]);
|
||||
const resultOptions = {
|
||||
...project.options,
|
||||
...forcedCompilerOptions,
|
||||
};
|
||||
if (!resultOptions.moduleResolution ||
|
||||
resultOptions.moduleResolution === docContext.ts.ModuleResolutionKind.Classic) {
|
||||
resultOptions.moduleResolution = docContext.ts.ModuleResolutionKind.NodeJs;
|
||||
}
|
||||
return {
|
||||
...project,
|
||||
fileNames: project.fileNames.map(utils_1.normalizePath),
|
||||
compilerOptions: resultOptions,
|
||||
};
|
||||
}
|
||||
}
|
||||
function getDefaultExclude() {
|
||||
return ['dist', 'node_modules'];
|
||||
}
|
||||
23
node_modules/@astrojs/language-server/dist/plugins/typescript/module-loader.d.ts
generated
vendored
Normal file
23
node_modules/@astrojs/language-server/dist/plugins/typescript/module-loader.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import type ts from 'typescript';
|
||||
import type { ResolvedModule } from 'typescript';
|
||||
import type { DocumentSnapshot } from './snapshots/DocumentSnapshot';
|
||||
/**
|
||||
* Creates a module loader specifically for `.astro` and other frameworks files.
|
||||
*
|
||||
* The typescript language service tries to look up other files that are referenced in the currently open astro file.
|
||||
* For `.ts`/`.js` files this works, for `.astro` and frameworks files it does not by default.
|
||||
* Reason: The typescript language service does not know about those file endings,
|
||||
* so it assumes it's a normal typescript file and searches for files like `../Component.astro.ts`, which is wrong.
|
||||
* In order to fix this, we need to wrap typescript's module resolution and reroute all `.astro.ts` file lookups to .astro.
|
||||
*
|
||||
* @param getSnapshot A function which returns a (in case of astro file fully preprocessed) typescript/javascript snapshot
|
||||
* @param compilerOptions The typescript compiler options
|
||||
*/
|
||||
export declare function createAstroModuleLoader(getSnapshot: (fileName: string) => DocumentSnapshot, compilerOptions: ts.CompilerOptions, ts: typeof import('typescript/lib/tsserverlibrary'), tsResolveModuleName?: typeof ts.resolveModuleName): {
|
||||
fileExists: (path: string) => boolean;
|
||||
readFile: (path: string, encoding?: string | undefined) => string | undefined;
|
||||
readDirectory: (path: string, extensions?: readonly string[] | undefined, exclude?: readonly string[] | undefined, include?: readonly string[] | undefined, depth?: number | undefined) => string[];
|
||||
deleteFromModuleCache: (path: string) => void;
|
||||
deleteUnresolvedResolutionsFromCache: (path: string) => void;
|
||||
resolveModuleNames: (moduleNames: string[], containingFile: string, _reusedNames: string[] | undefined, _redirectedReference: ts.ResolvedProjectReference | undefined, _options: ts.CompilerOptions, containingSourceFile?: ts.SourceFile | undefined) => Array<ts.ResolvedModule | undefined>;
|
||||
};
|
||||
155
node_modules/@astrojs/language-server/dist/plugins/typescript/module-loader.js
generated
vendored
Normal file
155
node_modules/@astrojs/language-server/dist/plugins/typescript/module-loader.js
generated
vendored
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createAstroModuleLoader = void 0;
|
||||
const utils_1 = require("../../utils");
|
||||
const astro_sys_1 = require("./astro-sys");
|
||||
const utils_2 = require("./utils");
|
||||
/**
|
||||
* Caches resolved modules.
|
||||
*/
|
||||
class ModuleResolutionCache {
|
||||
constructor() {
|
||||
this.cache = new Map();
|
||||
}
|
||||
/**
|
||||
* Tries to get a cached module.
|
||||
*/
|
||||
get(moduleName, containingFile) {
|
||||
return this.cache.get(this.getKey(moduleName, containingFile));
|
||||
}
|
||||
/**
|
||||
* Checks if has cached module.
|
||||
*/
|
||||
has(moduleName, containingFile) {
|
||||
return this.cache.has(this.getKey(moduleName, containingFile));
|
||||
}
|
||||
/**
|
||||
* Caches resolved module (or undefined).
|
||||
*/
|
||||
set(moduleName, containingFile, resolvedModule) {
|
||||
this.cache.set(this.getKey(moduleName, containingFile), resolvedModule);
|
||||
}
|
||||
/**
|
||||
* Deletes module from cache. Call this if a file was deleted.
|
||||
* @param resolvedModuleName full path of the module
|
||||
*/
|
||||
delete(resolvedModuleName) {
|
||||
this.cache.forEach((val, key) => {
|
||||
if (val?.resolvedFileName === resolvedModuleName) {
|
||||
this.cache.delete(key);
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Deletes everything from cache that resolved to `undefined`
|
||||
* and which might match the path.
|
||||
*/
|
||||
deleteUnresolvedResolutionsFromCache(path) {
|
||||
const fileNameWithoutEnding = (0, utils_1.getLastPartOfPath)(path).split('.').shift() || '';
|
||||
this.cache.forEach((val, key) => {
|
||||
const moduleName = key.split(':::').pop() || '';
|
||||
if (!val && moduleName.includes(fileNameWithoutEnding)) {
|
||||
this.cache.delete(key);
|
||||
}
|
||||
});
|
||||
}
|
||||
getKey(moduleName, containingFile) {
|
||||
return containingFile + ':::' + (0, utils_2.ensureRealFilePath)(moduleName);
|
||||
}
|
||||
}
|
||||
class ImpliedNodeFormatResolver {
|
||||
constructor(ts) {
|
||||
this.ts = ts;
|
||||
this.alreadyResolved = new Map();
|
||||
}
|
||||
resolve(importPath, importIdxInFile, sourceFile, compilerOptions) {
|
||||
// For Astro & Framework imports, we have to fallback to the old resolution algorithm or it doesn't work
|
||||
if ((0, utils_2.isAstroFilePath)(importPath) || (0, utils_2.isFrameworkFilePath)(importPath)) {
|
||||
return undefined;
|
||||
}
|
||||
let mode = undefined;
|
||||
if (sourceFile) {
|
||||
if (!sourceFile.impliedNodeFormat &&
|
||||
((0, utils_2.isAstroFilePath)(sourceFile.fileName) || (0, utils_2.isFrameworkFilePath)(sourceFile.fileName))) {
|
||||
// impliedNodeFormat is not set for non-TS files, because the TS function which calculates this works with a
|
||||
// fixed set of extensions that does not include frameworks files
|
||||
if (!this.alreadyResolved.has(sourceFile.fileName)) {
|
||||
sourceFile.impliedNodeFormat = this.ts.getImpliedNodeFormatForFile((0, utils_2.toVirtualFilePath)(sourceFile.fileName), undefined, this.ts.sys, compilerOptions);
|
||||
this.alreadyResolved.set(sourceFile.fileName, sourceFile.impliedNodeFormat);
|
||||
}
|
||||
else {
|
||||
sourceFile.impliedNodeFormat = this.alreadyResolved.get(sourceFile.fileName);
|
||||
}
|
||||
}
|
||||
mode = this.ts.getModeForResolutionAtIndex(sourceFile, importIdxInFile);
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Creates a module loader specifically for `.astro` and other frameworks files.
|
||||
*
|
||||
* The typescript language service tries to look up other files that are referenced in the currently open astro file.
|
||||
* For `.ts`/`.js` files this works, for `.astro` and frameworks files it does not by default.
|
||||
* Reason: The typescript language service does not know about those file endings,
|
||||
* so it assumes it's a normal typescript file and searches for files like `../Component.astro.ts`, which is wrong.
|
||||
* In order to fix this, we need to wrap typescript's module resolution and reroute all `.astro.ts` file lookups to .astro.
|
||||
*
|
||||
* @param getSnapshot A function which returns a (in case of astro file fully preprocessed) typescript/javascript snapshot
|
||||
* @param compilerOptions The typescript compiler options
|
||||
*/
|
||||
function createAstroModuleLoader(getSnapshot, compilerOptions, ts,
|
||||
/* For tests */
|
||||
tsResolveModuleName) {
|
||||
const astroSys = (0, astro_sys_1.createAstroSys)(getSnapshot, ts);
|
||||
const tsResolver = tsResolveModuleName ? tsResolveModuleName : ts.resolveModuleName;
|
||||
const moduleCache = new ModuleResolutionCache();
|
||||
const impliedNodeFormatResolver = new ImpliedNodeFormatResolver(ts);
|
||||
return {
|
||||
fileExists: astroSys.fileExists,
|
||||
readFile: astroSys.readFile,
|
||||
readDirectory: astroSys.readDirectory,
|
||||
deleteFromModuleCache: (path) => {
|
||||
astroSys.deleteFromCache(path);
|
||||
moduleCache.delete(path);
|
||||
},
|
||||
deleteUnresolvedResolutionsFromCache: (path) => {
|
||||
astroSys.deleteFromCache(path);
|
||||
moduleCache.deleteUnresolvedResolutionsFromCache(path);
|
||||
},
|
||||
resolveModuleNames,
|
||||
};
|
||||
function resolveModuleNames(moduleNames, containingFile, _reusedNames, _redirectedReference, _options, containingSourceFile) {
|
||||
return moduleNames.map((moduleName, index) => {
|
||||
if (moduleCache.has(moduleName, containingFile)) {
|
||||
return moduleCache.get(moduleName, containingFile);
|
||||
}
|
||||
const resolvedModule = resolveModuleName(moduleName, containingFile, containingSourceFile, index);
|
||||
moduleCache.set(moduleName, containingFile, resolvedModule);
|
||||
return resolvedModule;
|
||||
});
|
||||
}
|
||||
function resolveModuleName(name, containingFile, containingSourceFile, index) {
|
||||
const mode = impliedNodeFormatResolver.resolve(name, index, containingSourceFile, compilerOptions);
|
||||
// Delegate to the TS resolver first.
|
||||
// If that does not bring up anything, try the Astro Module loader
|
||||
// which is able to deal with .astro and other frameworks files.
|
||||
const tsResolvedModule = tsResolver(name, containingFile, compilerOptions, ts.sys, undefined, undefined, mode).resolvedModule;
|
||||
if (tsResolvedModule && !(0, utils_2.isVirtualFilePath)(tsResolvedModule.resolvedFileName)) {
|
||||
return tsResolvedModule;
|
||||
}
|
||||
const astroResolvedModule = tsResolver(name, containingFile, compilerOptions, astroSys, undefined, undefined, mode).resolvedModule;
|
||||
if (!astroResolvedModule || !(0, utils_2.isVirtualFilePath)(astroResolvedModule.resolvedFileName)) {
|
||||
return astroResolvedModule;
|
||||
}
|
||||
const resolvedFileName = (0, utils_2.ensureRealFilePath)(astroResolvedModule.resolvedFileName);
|
||||
const snapshot = getSnapshot(resolvedFileName);
|
||||
const resolvedAstroModule = {
|
||||
extension: (0, utils_2.getExtensionFromScriptKind)(snapshot && snapshot.scriptKind, ts),
|
||||
resolvedFileName,
|
||||
isExternalLibraryImport: astroResolvedModule.isExternalLibraryImport,
|
||||
};
|
||||
return resolvedAstroModule;
|
||||
}
|
||||
}
|
||||
exports.createAstroModuleLoader = createAstroModuleLoader;
|
||||
7
node_modules/@astrojs/language-server/dist/plugins/typescript/previewer.d.ts
generated
vendored
Normal file
7
node_modules/@astrojs/language-server/dist/plugins/typescript/previewer.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* adopted from https://github.com/microsoft/vscode/blob/10722887b8629f90cc38ee7d90d54e8246dc895f/extensions/typescript-language-features/src/utils/previewer.ts
|
||||
*/
|
||||
import type ts from 'typescript';
|
||||
export declare function getTagDocumentation(tag: ts.JSDocTagInfo, ts: typeof import('typescript/lib/tsserverlibrary')): string | undefined;
|
||||
export declare function plain(parts: ts.SymbolDisplayPart[] | string, ts: typeof import('typescript/lib/tsserverlibrary')): string;
|
||||
export declare function getMarkdownDocumentation(documentation: ts.SymbolDisplayPart[] | undefined, tags: ts.JSDocTagInfo[] | undefined, ts: typeof import('typescript/lib/tsserverlibrary')): string;
|
||||
108
node_modules/@astrojs/language-server/dist/plugins/typescript/previewer.js
generated
vendored
Normal file
108
node_modules/@astrojs/language-server/dist/plugins/typescript/previewer.js
generated
vendored
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getMarkdownDocumentation = exports.plain = exports.getTagDocumentation = void 0;
|
||||
const utils_1 = require("../../utils");
|
||||
function replaceLinks(text) {
|
||||
return (text
|
||||
// Http(s) links
|
||||
.replace(/\{@(link|linkplain|linkcode) (https?:\/\/[^ |}]+?)(?:[| ]([^{}\n]+?))?\}/gi, (_, tag, link, label) => {
|
||||
switch (tag) {
|
||||
case 'linkcode':
|
||||
return `[\`${label ? label.trim() : link}\`](${link})`;
|
||||
default:
|
||||
return `[${label ? label.trim() : link}](${link})`;
|
||||
}
|
||||
}));
|
||||
}
|
||||
function processInlineTags(text) {
|
||||
return replaceLinks(text);
|
||||
}
|
||||
function getTagBodyText(tag, ts) {
|
||||
if (!tag.text) {
|
||||
return undefined;
|
||||
}
|
||||
// Convert to markdown code block if it is not already one
|
||||
function makeCodeblock(text) {
|
||||
if (text.match(/^\s*[~`]{3}/g)) {
|
||||
return text;
|
||||
}
|
||||
return '```\n' + text + '\n```';
|
||||
}
|
||||
function makeExampleTag(text) {
|
||||
// check for caption tags, fix for https://github.com/microsoft/vscode/issues/79704
|
||||
const captionTagMatches = text.match(/<caption>(.*?)<\/caption>\s*(\r\n|\n)/);
|
||||
if (captionTagMatches && captionTagMatches.index === 0) {
|
||||
return captionTagMatches[1] + '\n\n' + makeCodeblock(text.substr(captionTagMatches[0].length));
|
||||
}
|
||||
else {
|
||||
return makeCodeblock(text);
|
||||
}
|
||||
}
|
||||
function makeEmailTag(text) {
|
||||
// fix obsucated email address, https://github.com/microsoft/vscode/issues/80898
|
||||
const emailMatch = text.match(/(.+)\s<([-.\w]+@[-.\w]+)>/);
|
||||
if (emailMatch === null) {
|
||||
return text;
|
||||
}
|
||||
else {
|
||||
return `${emailMatch[1]} ${emailMatch[2]}`;
|
||||
}
|
||||
}
|
||||
switch (tag.name) {
|
||||
case 'example':
|
||||
return makeExampleTag(ts.displayPartsToString(tag.text));
|
||||
case 'author':
|
||||
return makeEmailTag(ts.displayPartsToString(tag.text));
|
||||
case 'default':
|
||||
return makeCodeblock(ts.displayPartsToString(tag.text));
|
||||
}
|
||||
return processInlineTags(ts.displayPartsToString(tag.text));
|
||||
}
|
||||
function getTagDocumentation(tag, ts) {
|
||||
function getWithType() {
|
||||
const body = (ts.displayPartsToString(tag.text) || '').split(/^(\S+)\s*-?\s*/);
|
||||
if (body?.length === 3) {
|
||||
const param = body[1];
|
||||
const doc = body[2];
|
||||
const label = `*@${tag.name}* \`${param}\``;
|
||||
if (!doc) {
|
||||
return label;
|
||||
}
|
||||
return label + (doc.match(/\r\n|\n/g) ? ' \n' + processInlineTags(doc) : ` — ${processInlineTags(doc)}`);
|
||||
}
|
||||
}
|
||||
switch (tag.name) {
|
||||
case 'augments':
|
||||
case 'extends':
|
||||
case 'param':
|
||||
case 'template':
|
||||
return getWithType();
|
||||
}
|
||||
// Generic tag
|
||||
const label = `*@${tag.name}*`;
|
||||
const text = getTagBodyText(tag, ts);
|
||||
if (!text) {
|
||||
return label;
|
||||
}
|
||||
return label + (text.match(/\r\n|\n/g) ? ' \n' + text : ` — ${text}`);
|
||||
}
|
||||
exports.getTagDocumentation = getTagDocumentation;
|
||||
function plain(parts, ts) {
|
||||
return processInlineTags(typeof parts === 'string' ? parts : ts.displayPartsToString(parts));
|
||||
}
|
||||
exports.plain = plain;
|
||||
function getMarkdownDocumentation(documentation, tags, ts) {
|
||||
let result = [];
|
||||
if (documentation) {
|
||||
result.push(plain(documentation, ts));
|
||||
}
|
||||
if (tags) {
|
||||
result = result.concat(tags.map((tag) => getTagDocumentation(tag, ts)));
|
||||
}
|
||||
return result.filter(utils_1.isNotNullOrUndefined).join('\n\n');
|
||||
}
|
||||
exports.getMarkdownDocumentation = getMarkdownDocumentation;
|
||||
95
node_modules/@astrojs/language-server/dist/plugins/typescript/snapshots/DocumentSnapshot.d.ts
generated
vendored
Normal file
95
node_modules/@astrojs/language-server/dist/plugins/typescript/snapshots/DocumentSnapshot.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
import { DiagnosticMessage } from '@astrojs/compiler/types';
|
||||
import { EncodedSourceMap, TraceMap } from '@jridgewell/trace-mapping';
|
||||
import type ts from 'typescript';
|
||||
import { Position, TextDocumentContentChangeEvent } from 'vscode-languageserver';
|
||||
import { AstroDocument, DocumentMapper, FragmentMapper, IdentityMapper, SourceMapDocumentMapper, TagInformation } from '../../../core/documents';
|
||||
export interface DocumentSnapshot extends ts.IScriptSnapshot, DocumentMapper {
|
||||
version: number;
|
||||
filePath: string;
|
||||
scriptKind: ts.ScriptKind;
|
||||
positionAt(offset: number): Position;
|
||||
offsetAt(position: Position): number;
|
||||
/**
|
||||
* Convenience function for getText(0, getLength())
|
||||
*/
|
||||
getFullText(): string;
|
||||
}
|
||||
/**
|
||||
* Snapshots used for Astro files
|
||||
*/
|
||||
export declare class AstroSnapshot implements DocumentSnapshot {
|
||||
readonly parent: AstroDocument;
|
||||
private readonly text;
|
||||
private readonly tsxMap;
|
||||
readonly scriptKind: ts.ScriptKind;
|
||||
readonly compilerDiagnostics: DiagnosticMessage[];
|
||||
private mapper?;
|
||||
private lineOffsets?;
|
||||
private url;
|
||||
scriptTagSnapshots: ScriptTagDocumentSnapshot[];
|
||||
version: number;
|
||||
constructor(parent: AstroDocument, text: string, tsxMap: EncodedSourceMap, scriptKind: ts.ScriptKind, compilerDiagnostics: DiagnosticMessage[]);
|
||||
get isInErrorState(): boolean;
|
||||
isInGenerated(pos: Position): boolean;
|
||||
getURL(): string;
|
||||
get filePath(): string;
|
||||
getText(start: number, end: number): string;
|
||||
getLength(): number;
|
||||
getFullText(): string;
|
||||
getChangeRange(): undefined;
|
||||
positionAt(offset: number): Position;
|
||||
offsetAt(position: Position): number;
|
||||
getOriginalPosition(pos: Position): Position;
|
||||
getGeneratedPosition(pos: Position): Position;
|
||||
private getLineOffsets;
|
||||
private getMapper;
|
||||
}
|
||||
/**
|
||||
* Snapshots used for script tags inside Astro files
|
||||
*/
|
||||
export declare class ScriptTagDocumentSnapshot extends FragmentMapper implements DocumentSnapshot {
|
||||
scriptTag: TagInformation;
|
||||
private readonly parent;
|
||||
filePath: string;
|
||||
readonly scriptKind: ts.ScriptKind;
|
||||
readonly version: number;
|
||||
private text;
|
||||
private lineOffsets?;
|
||||
constructor(scriptTag: TagInformation, parent: AstroDocument, filePath: string, scriptKind: ts.ScriptKind);
|
||||
positionAt(offset: number): Position;
|
||||
offsetAt(position: Position): number;
|
||||
getText(start: number, end: number): string;
|
||||
getLength(): number;
|
||||
getFullText(): string;
|
||||
getChangeRange(): undefined;
|
||||
private getLineOffsets;
|
||||
}
|
||||
/**
|
||||
* Snapshot used for anything that is not an Astro file
|
||||
* It's both used for .js(x)/.ts(x) files and .svelte/.vue files
|
||||
*/
|
||||
export declare class TypeScriptDocumentSnapshot extends IdentityMapper implements DocumentSnapshot {
|
||||
version: number;
|
||||
readonly filePath: string;
|
||||
private text;
|
||||
readonly supportPartialUpdate: boolean;
|
||||
scriptKind: ts.ScriptKind;
|
||||
private lineOffsets?;
|
||||
constructor(version: number, filePath: string, text: string, scriptKind: ts.ScriptKind, supportPartialUpdate: boolean);
|
||||
getText(start: number, end: number): string;
|
||||
getLength(): number;
|
||||
getFullText(): string;
|
||||
getChangeRange(): undefined;
|
||||
positionAt(offset: number): Position;
|
||||
offsetAt(position: Position): number;
|
||||
createFragment(): this;
|
||||
update(changes: TextDocumentContentChangeEvent[]): void;
|
||||
private getLineOffsets;
|
||||
}
|
||||
export declare class ConsumerDocumentMapper extends SourceMapDocumentMapper {
|
||||
private nrPrependesLines;
|
||||
constructor(traceMap: TraceMap, sourceUri: string, nrPrependesLines: number);
|
||||
getOriginalPosition(generatedPosition: Position): Position;
|
||||
getGeneratedPosition(originalPosition: Position): Position;
|
||||
isInGenerated(): boolean;
|
||||
}
|
||||
187
node_modules/@astrojs/language-server/dist/plugins/typescript/snapshots/DocumentSnapshot.js
generated
vendored
Normal file
187
node_modules/@astrojs/language-server/dist/plugins/typescript/snapshots/DocumentSnapshot.js
generated
vendored
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ConsumerDocumentMapper = exports.TypeScriptDocumentSnapshot = exports.ScriptTagDocumentSnapshot = exports.AstroSnapshot = void 0;
|
||||
const trace_mapping_1 = require("@jridgewell/trace-mapping");
|
||||
const vscode_languageserver_1 = require("vscode-languageserver");
|
||||
const documents_1 = require("../../../core/documents");
|
||||
const utils_1 = require("../../../utils");
|
||||
/**
|
||||
* Snapshots used for Astro files
|
||||
*/
|
||||
class AstroSnapshot {
|
||||
constructor(parent, text, tsxMap, scriptKind, compilerDiagnostics) {
|
||||
this.parent = parent;
|
||||
this.text = text;
|
||||
this.tsxMap = tsxMap;
|
||||
this.scriptKind = scriptKind;
|
||||
this.compilerDiagnostics = compilerDiagnostics;
|
||||
this.url = (0, utils_1.pathToUrl)(this.filePath);
|
||||
this.scriptTagSnapshots = [];
|
||||
this.version = this.parent.version;
|
||||
}
|
||||
get isInErrorState() {
|
||||
return this.compilerDiagnostics.filter((diag) => diag.severity === vscode_languageserver_1.DiagnosticSeverity.Error).length > 0;
|
||||
}
|
||||
isInGenerated(pos) {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
getURL() {
|
||||
return this.url;
|
||||
}
|
||||
get filePath() {
|
||||
return this.parent.getFilePath() || '';
|
||||
}
|
||||
getText(start, end) {
|
||||
return this.text.substring(start, end);
|
||||
}
|
||||
getLength() {
|
||||
return this.text.length;
|
||||
}
|
||||
getFullText() {
|
||||
return this.text;
|
||||
}
|
||||
getChangeRange() {
|
||||
return undefined;
|
||||
}
|
||||
positionAt(offset) {
|
||||
return (0, documents_1.positionAt)(offset, this.text, this.getLineOffsets());
|
||||
}
|
||||
offsetAt(position) {
|
||||
return (0, documents_1.offsetAt)(position, this.text, this.getLineOffsets());
|
||||
}
|
||||
getOriginalPosition(pos) {
|
||||
return this.getMapper().getOriginalPosition(pos);
|
||||
}
|
||||
getGeneratedPosition(pos) {
|
||||
return this.getMapper().getGeneratedPosition(pos);
|
||||
}
|
||||
getLineOffsets() {
|
||||
if (!this.lineOffsets) {
|
||||
this.lineOffsets = (0, documents_1.getLineOffsets)(this.text);
|
||||
}
|
||||
return this.lineOffsets;
|
||||
}
|
||||
getMapper() {
|
||||
if (!this.mapper) {
|
||||
this.mapper = new ConsumerDocumentMapper(new trace_mapping_1.TraceMap(this.tsxMap), this.url, 0);
|
||||
}
|
||||
return this.mapper;
|
||||
}
|
||||
}
|
||||
exports.AstroSnapshot = AstroSnapshot;
|
||||
/**
|
||||
* Snapshots used for script tags inside Astro files
|
||||
*/
|
||||
class ScriptTagDocumentSnapshot extends documents_1.FragmentMapper {
|
||||
constructor(scriptTag, parent, filePath, scriptKind) {
|
||||
super(parent.getText(), scriptTag, filePath);
|
||||
this.scriptTag = scriptTag;
|
||||
this.parent = parent;
|
||||
this.filePath = filePath;
|
||||
this.scriptKind = scriptKind;
|
||||
this.version = this.parent.version;
|
||||
this.text = this.parent.getText().slice(this.scriptTag.start, this.scriptTag.end) + '\nexport {}';
|
||||
}
|
||||
positionAt(offset) {
|
||||
return (0, documents_1.positionAt)(offset, this.text, this.getLineOffsets());
|
||||
}
|
||||
offsetAt(position) {
|
||||
return (0, documents_1.offsetAt)(position, this.text, this.getLineOffsets());
|
||||
}
|
||||
getText(start, end) {
|
||||
return this.text.substring(start, end);
|
||||
}
|
||||
getLength() {
|
||||
return this.text.length;
|
||||
}
|
||||
getFullText() {
|
||||
return this.text;
|
||||
}
|
||||
getChangeRange() {
|
||||
return undefined;
|
||||
}
|
||||
getLineOffsets() {
|
||||
if (!this.lineOffsets) {
|
||||
this.lineOffsets = (0, documents_1.getLineOffsets)(this.text);
|
||||
}
|
||||
return this.lineOffsets;
|
||||
}
|
||||
}
|
||||
exports.ScriptTagDocumentSnapshot = ScriptTagDocumentSnapshot;
|
||||
/**
|
||||
* Snapshot used for anything that is not an Astro file
|
||||
* It's both used for .js(x)/.ts(x) files and .svelte/.vue files
|
||||
*/
|
||||
class TypeScriptDocumentSnapshot extends documents_1.IdentityMapper {
|
||||
constructor(version, filePath, text, scriptKind, supportPartialUpdate) {
|
||||
super((0, utils_1.pathToUrl)(filePath));
|
||||
this.version = version;
|
||||
this.filePath = filePath;
|
||||
this.text = text;
|
||||
this.supportPartialUpdate = supportPartialUpdate;
|
||||
this.scriptKind = scriptKind;
|
||||
}
|
||||
getText(start, end) {
|
||||
return this.text.substring(start, end);
|
||||
}
|
||||
getLength() {
|
||||
return this.text.length;
|
||||
}
|
||||
getFullText() {
|
||||
return this.text;
|
||||
}
|
||||
getChangeRange() {
|
||||
return undefined;
|
||||
}
|
||||
positionAt(offset) {
|
||||
return (0, documents_1.positionAt)(offset, this.text, this.getLineOffsets());
|
||||
}
|
||||
offsetAt(position) {
|
||||
return (0, documents_1.offsetAt)(position, this.text, this.getLineOffsets());
|
||||
}
|
||||
createFragment() {
|
||||
return this;
|
||||
}
|
||||
update(changes) {
|
||||
for (const change of changes) {
|
||||
let start = 0;
|
||||
let end = 0;
|
||||
if ('range' in change) {
|
||||
start = this.offsetAt(change.range.start);
|
||||
end = this.offsetAt(change.range.end);
|
||||
}
|
||||
else {
|
||||
end = this.getLength();
|
||||
}
|
||||
this.text = this.text.slice(0, start) + change.text + this.text.slice(end);
|
||||
}
|
||||
this.version++;
|
||||
this.lineOffsets = undefined;
|
||||
}
|
||||
getLineOffsets() {
|
||||
if (!this.lineOffsets) {
|
||||
this.lineOffsets = (0, documents_1.getLineOffsets)(this.text);
|
||||
}
|
||||
return this.lineOffsets;
|
||||
}
|
||||
}
|
||||
exports.TypeScriptDocumentSnapshot = TypeScriptDocumentSnapshot;
|
||||
class ConsumerDocumentMapper extends documents_1.SourceMapDocumentMapper {
|
||||
constructor(traceMap, sourceUri, nrPrependesLines) {
|
||||
super(traceMap, sourceUri);
|
||||
this.nrPrependesLines = nrPrependesLines;
|
||||
}
|
||||
getOriginalPosition(generatedPosition) {
|
||||
return super.getOriginalPosition(vscode_languageserver_1.Position.create(generatedPosition.line - this.nrPrependesLines, generatedPosition.character));
|
||||
}
|
||||
getGeneratedPosition(originalPosition) {
|
||||
const result = super.getGeneratedPosition(originalPosition);
|
||||
result.line += this.nrPrependesLines;
|
||||
return result;
|
||||
}
|
||||
isInGenerated() {
|
||||
// always return true and map outliers case by case
|
||||
return true;
|
||||
}
|
||||
}
|
||||
exports.ConsumerDocumentMapper = ConsumerDocumentMapper;
|
||||
44
node_modules/@astrojs/language-server/dist/plugins/typescript/snapshots/SnapshotManager.d.ts
generated
vendored
Normal file
44
node_modules/@astrojs/language-server/dist/plugins/typescript/snapshots/SnapshotManager.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import type { TextDocumentContentChangeEvent } from 'vscode-languageserver';
|
||||
import { DocumentSnapshot, TypeScriptDocumentSnapshot } from './DocumentSnapshot';
|
||||
/**
|
||||
* Every snapshot corresponds to a unique file on disk.
|
||||
* A snapshot can be part of multiple projects, but for a given file path
|
||||
* there can be only one snapshot.
|
||||
*/
|
||||
export declare class GlobalSnapshotManager {
|
||||
private readonly ts;
|
||||
private emitter;
|
||||
private documents;
|
||||
constructor(ts: typeof import('typescript/lib/tsserverlibrary'));
|
||||
get(fileName: string): DocumentSnapshot | undefined;
|
||||
set(fileName: string, document: DocumentSnapshot): void;
|
||||
delete(fileName: string): void;
|
||||
updateNonAstroFile(fileName: string, changes?: TextDocumentContentChangeEvent[], newText?: string): TypeScriptDocumentSnapshot | undefined;
|
||||
onChange(listener: (fileName: string, newDocument: DocumentSnapshot | undefined) => void): void;
|
||||
}
|
||||
export interface TsFilesSpec {
|
||||
include?: readonly string[];
|
||||
exclude?: readonly string[];
|
||||
}
|
||||
/**
|
||||
* Should only be used by `language-service.ts`
|
||||
*/
|
||||
export declare class SnapshotManager {
|
||||
private globalSnapshotsManager;
|
||||
private projectFiles;
|
||||
private fileSpec;
|
||||
private workspaceRoot;
|
||||
private ts;
|
||||
private documents;
|
||||
private lastLogged;
|
||||
constructor(globalSnapshotsManager: GlobalSnapshotManager, projectFiles: string[], fileSpec: TsFilesSpec, workspaceRoot: string, ts: typeof import('typescript/lib/tsserverlibrary'));
|
||||
updateProjectFiles(): void;
|
||||
updateNonAstroFile(fileName: string, changes?: TextDocumentContentChangeEvent[], text?: string): void;
|
||||
has(fileName: string): boolean;
|
||||
set(fileName: string, snapshot: DocumentSnapshot): void;
|
||||
get(fileName: string): DocumentSnapshot | undefined;
|
||||
delete(fileName: string): void;
|
||||
getFileNames(): string[];
|
||||
getProjectFileNames(): string[];
|
||||
private logStatistics;
|
||||
}
|
||||
179
node_modules/@astrojs/language-server/dist/plugins/typescript/snapshots/SnapshotManager.js
generated
vendored
Normal file
179
node_modules/@astrojs/language-server/dist/plugins/typescript/snapshots/SnapshotManager.js
generated
vendored
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SnapshotManager = exports.GlobalSnapshotManager = void 0;
|
||||
const events_1 = require("events");
|
||||
const utils_1 = require("../../../utils");
|
||||
const DocumentSnapshot_1 = require("./DocumentSnapshot");
|
||||
const DocumentSnapshotUtils = __importStar(require("./utils"));
|
||||
/**
|
||||
* Every snapshot corresponds to a unique file on disk.
|
||||
* A snapshot can be part of multiple projects, but for a given file path
|
||||
* there can be only one snapshot.
|
||||
*/
|
||||
class GlobalSnapshotManager {
|
||||
constructor(ts) {
|
||||
this.ts = ts;
|
||||
this.emitter = new events_1.EventEmitter();
|
||||
this.documents = new Map();
|
||||
}
|
||||
get(fileName) {
|
||||
fileName = (0, utils_1.normalizePath)(fileName);
|
||||
return this.documents.get(fileName);
|
||||
}
|
||||
set(fileName, document) {
|
||||
fileName = (0, utils_1.normalizePath)(fileName);
|
||||
this.documents.set(fileName, document);
|
||||
this.emitter.emit('change', fileName, document);
|
||||
}
|
||||
delete(fileName) {
|
||||
fileName = (0, utils_1.normalizePath)(fileName);
|
||||
this.documents.delete(fileName);
|
||||
this.emitter.emit('change', fileName, undefined);
|
||||
}
|
||||
updateNonAstroFile(fileName, changes, newText) {
|
||||
fileName = (0, utils_1.normalizePath)(fileName);
|
||||
const previousSnapshot = this.get(fileName);
|
||||
const canBePartiallyUpdated = changes && previousSnapshot instanceof DocumentSnapshot_1.TypeScriptDocumentSnapshot && previousSnapshot.supportPartialUpdate;
|
||||
if (canBePartiallyUpdated) {
|
||||
previousSnapshot.update(changes);
|
||||
this.emitter.emit('change', fileName, previousSnapshot);
|
||||
return previousSnapshot;
|
||||
}
|
||||
else {
|
||||
const newSnapshot = DocumentSnapshotUtils.createFromNonAstroFilePath(fileName, this.ts, newText);
|
||||
if (previousSnapshot) {
|
||||
newSnapshot.version = previousSnapshot.version + 1;
|
||||
}
|
||||
else {
|
||||
// ensure it's greater than initial version
|
||||
// so that ts server picks up the change
|
||||
newSnapshot.version += 1;
|
||||
}
|
||||
this.set(fileName, newSnapshot);
|
||||
this.emitter.emit('change', fileName, newSnapshot);
|
||||
return newSnapshot;
|
||||
}
|
||||
}
|
||||
onChange(listener) {
|
||||
this.emitter.on('change', listener);
|
||||
}
|
||||
}
|
||||
exports.GlobalSnapshotManager = GlobalSnapshotManager;
|
||||
/**
|
||||
* Should only be used by `language-service.ts`
|
||||
*/
|
||||
class SnapshotManager {
|
||||
constructor(globalSnapshotsManager, projectFiles, fileSpec, workspaceRoot, ts) {
|
||||
this.globalSnapshotsManager = globalSnapshotsManager;
|
||||
this.projectFiles = projectFiles;
|
||||
this.fileSpec = fileSpec;
|
||||
this.workspaceRoot = workspaceRoot;
|
||||
this.ts = ts;
|
||||
this.documents = new Map();
|
||||
this.lastLogged = new Date(new Date().getTime() - 60001);
|
||||
this.globalSnapshotsManager.onChange((fileName, document) => {
|
||||
// Only delete/update snapshots, don't add new ones,
|
||||
// as they could be from another TS service and this
|
||||
// snapshot manager can't reach this file.
|
||||
// For these, instead wait on a `get` method invocation
|
||||
// and set them "manually" in the set/update methods.
|
||||
if (!document) {
|
||||
this.documents.delete(fileName);
|
||||
}
|
||||
else if (this.documents.has(fileName)) {
|
||||
this.documents.set(fileName, document);
|
||||
}
|
||||
});
|
||||
}
|
||||
updateProjectFiles() {
|
||||
const { include, exclude } = this.fileSpec;
|
||||
// Since we default to not include anything,
|
||||
// just don't waste time on this
|
||||
if (include?.length === 0) {
|
||||
return;
|
||||
}
|
||||
const projectFiles = this.ts.sys
|
||||
.readDirectory(this.workspaceRoot, [...Object.values(this.ts.Extension), '.astro', '.svelte', '.vue'], exclude, include)
|
||||
.map(utils_1.normalizePath);
|
||||
this.projectFiles = Array.from(new Set([...this.projectFiles, ...projectFiles]));
|
||||
}
|
||||
updateNonAstroFile(fileName, changes, text) {
|
||||
const snapshot = this.globalSnapshotsManager.updateNonAstroFile(fileName, changes, text);
|
||||
// This isn't duplicated logic to the listener, because this could
|
||||
// be a new snapshot which the listener wouldn't add.
|
||||
if (snapshot) {
|
||||
this.documents.set((0, utils_1.normalizePath)(fileName), snapshot);
|
||||
}
|
||||
}
|
||||
has(fileName) {
|
||||
fileName = (0, utils_1.normalizePath)(fileName);
|
||||
return this.projectFiles.includes(fileName) || this.getFileNames().includes(fileName);
|
||||
}
|
||||
set(fileName, snapshot) {
|
||||
this.globalSnapshotsManager.set(fileName, snapshot);
|
||||
// This isn't duplicated logic to the listener, because this could
|
||||
// be a new snapshot which the listener wouldn't add.
|
||||
this.documents.set((0, utils_1.normalizePath)(fileName), snapshot);
|
||||
}
|
||||
get(fileName) {
|
||||
fileName = (0, utils_1.normalizePath)(fileName);
|
||||
let snapshot = this.documents.get(fileName);
|
||||
if (!snapshot) {
|
||||
snapshot = this.globalSnapshotsManager.get(fileName);
|
||||
if (snapshot) {
|
||||
this.documents.set(fileName, snapshot);
|
||||
}
|
||||
}
|
||||
return snapshot;
|
||||
}
|
||||
delete(fileName) {
|
||||
fileName = (0, utils_1.normalizePath)(fileName);
|
||||
this.projectFiles = this.projectFiles.filter((s) => s !== fileName);
|
||||
this.globalSnapshotsManager.delete(fileName);
|
||||
}
|
||||
getFileNames() {
|
||||
return Array.from(this.documents.keys());
|
||||
}
|
||||
getProjectFileNames() {
|
||||
return [...this.projectFiles];
|
||||
}
|
||||
logStatistics() {
|
||||
const date = new Date();
|
||||
// Don't use setInterval because that will keep tests running forever
|
||||
if (date.getTime() - this.lastLogged.getTime() > 60000) {
|
||||
this.lastLogged = date;
|
||||
const projectFiles = this.getProjectFileNames();
|
||||
const allFiles = Array.from(new Set([...projectFiles, ...this.getFileNames()]));
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('SnapshotManager File Statistics:\n' +
|
||||
`Project files: ${projectFiles.length}\n` +
|
||||
`Astro files: ${allFiles.filter((name) => name.endsWith('.astro')).length}\n` +
|
||||
`From node_modules: ${allFiles.filter((name) => name.includes('node_modules')).length}\n` +
|
||||
`Total: ${allFiles.length}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.SnapshotManager = SnapshotManager;
|
||||
29
node_modules/@astrojs/language-server/dist/plugins/typescript/snapshots/utils.d.ts
generated
vendored
Normal file
29
node_modules/@astrojs/language-server/dist/plugins/typescript/snapshots/utils.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import type { AstroDocument } from '../../../core/documents';
|
||||
import { FrameworkExt } from '../utils';
|
||||
import { AstroSnapshot, TypeScriptDocumentSnapshot } from './DocumentSnapshot';
|
||||
export declare function createFromDocument(document: AstroDocument, ts: typeof import('typescript/lib/tsserverlibrary')): AstroSnapshot;
|
||||
/**
|
||||
* Returns an Astro or Framework or a ts/js snapshot from a file path, depending on the file contents.
|
||||
* @param filePath path to the file
|
||||
* @param createDocument function that is used to create a document in case it's an Astro file
|
||||
*/
|
||||
export declare function createFromFilePath(filePath: string, createDocument: (filePath: string, text: string) => AstroDocument, ts: typeof import('typescript/lib/tsserverlibrary')): AstroSnapshot | TypeScriptDocumentSnapshot;
|
||||
/**
|
||||
* Return a Framework or a TS snapshot from a file path, depending on the file contents
|
||||
* Unlike createFromFilePath, this does not support creating an Astro snapshot
|
||||
*/
|
||||
export declare function createFromNonAstroFilePath(filePath: string, ts: typeof import('typescript/lib/tsserverlibrary'), forceText?: string): TypeScriptDocumentSnapshot;
|
||||
/**
|
||||
* Returns a ts/js snapshot from a file path.
|
||||
* @param filePath path to the js/ts file
|
||||
* @param options options that apply in case it's a svelte file
|
||||
*/
|
||||
export declare function createFromTSFilePath(filePath: string, ts: typeof import('typescript/lib/tsserverlibrary'), forceText?: string): TypeScriptDocumentSnapshot;
|
||||
/**
|
||||
* Returns an Astro snapshot from a file path.
|
||||
* @param filePath path to the Astro file
|
||||
* @param createDocument function that is used to create a document
|
||||
*/
|
||||
export declare function createFromAstroFilePath(filePath: string, createDocument: (filePath: string, text: string) => AstroDocument, ts: typeof import('typescript/lib/tsserverlibrary')): AstroSnapshot;
|
||||
export declare function createFromFrameworkFilePath(filePath: string, framework: FrameworkExt, ts: typeof import('typescript/lib/tsserverlibrary'), forceText?: string): TypeScriptDocumentSnapshot;
|
||||
export declare function classNameFromFilename(filename: string): string;
|
||||
106
node_modules/@astrojs/language-server/dist/plugins/typescript/snapshots/utils.js
generated
vendored
Normal file
106
node_modules/@astrojs/language-server/dist/plugins/typescript/snapshots/utils.js
generated
vendored
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.classNameFromFilename = exports.createFromFrameworkFilePath = exports.createFromAstroFilePath = exports.createFromTSFilePath = exports.createFromNonAstroFilePath = exports.createFromFilePath = exports.createFromDocument = void 0;
|
||||
const vscode_uri_1 = require("vscode-uri");
|
||||
const importPackage_1 = require("../../../importPackage");
|
||||
const utils_1 = require("../../../utils");
|
||||
const astro2tsx_1 = require("../astro2tsx");
|
||||
const utils_2 = require("../utils");
|
||||
const DocumentSnapshot_1 = require("./DocumentSnapshot");
|
||||
// Utilities to create Snapshots from different contexts
|
||||
function createFromDocument(document, ts) {
|
||||
const { code, map, diagnostics } = (0, astro2tsx_1.astro2tsx)(document.getText(), document.getURL());
|
||||
const sourceMap = map;
|
||||
return new DocumentSnapshot_1.AstroSnapshot(document, code, sourceMap, ts.ScriptKind.TSX, diagnostics);
|
||||
}
|
||||
exports.createFromDocument = createFromDocument;
|
||||
/**
|
||||
* Returns an Astro or Framework or a ts/js snapshot from a file path, depending on the file contents.
|
||||
* @param filePath path to the file
|
||||
* @param createDocument function that is used to create a document in case it's an Astro file
|
||||
*/
|
||||
function createFromFilePath(filePath, createDocument, ts) {
|
||||
if ((0, utils_2.isAstroFilePath)(filePath)) {
|
||||
return createFromAstroFilePath(filePath, createDocument, ts);
|
||||
}
|
||||
else if ((0, utils_2.isFrameworkFilePath)(filePath)) {
|
||||
const framework = (0, utils_2.getFrameworkFromFilePath)(filePath);
|
||||
return createFromFrameworkFilePath(filePath, framework, ts);
|
||||
}
|
||||
else {
|
||||
return createFromTSFilePath(filePath, ts);
|
||||
}
|
||||
}
|
||||
exports.createFromFilePath = createFromFilePath;
|
||||
/**
|
||||
* Return a Framework or a TS snapshot from a file path, depending on the file contents
|
||||
* Unlike createFromFilePath, this does not support creating an Astro snapshot
|
||||
*/
|
||||
function createFromNonAstroFilePath(filePath, ts, forceText) {
|
||||
if ((0, utils_2.isFrameworkFilePath)(filePath)) {
|
||||
const framework = (0, utils_2.getFrameworkFromFilePath)(filePath);
|
||||
return createFromFrameworkFilePath(filePath, framework, ts, forceText);
|
||||
}
|
||||
else {
|
||||
return createFromTSFilePath(filePath, ts, forceText);
|
||||
}
|
||||
}
|
||||
exports.createFromNonAstroFilePath = createFromNonAstroFilePath;
|
||||
/**
|
||||
* Returns a ts/js snapshot from a file path.
|
||||
* @param filePath path to the js/ts file
|
||||
* @param options options that apply in case it's a svelte file
|
||||
*/
|
||||
function createFromTSFilePath(filePath, ts, forceText) {
|
||||
const originalText = forceText ?? ts.sys.readFile(filePath) ?? '';
|
||||
return new DocumentSnapshot_1.TypeScriptDocumentSnapshot(0, filePath, originalText, (0, utils_2.getScriptKindFromFileName)(filePath, ts), true);
|
||||
}
|
||||
exports.createFromTSFilePath = createFromTSFilePath;
|
||||
/**
|
||||
* Returns an Astro snapshot from a file path.
|
||||
* @param filePath path to the Astro file
|
||||
* @param createDocument function that is used to create a document
|
||||
*/
|
||||
function createFromAstroFilePath(filePath, createDocument, ts) {
|
||||
const originalText = ts.sys.readFile(filePath) ?? '';
|
||||
return createFromDocument(createDocument(filePath, originalText), ts);
|
||||
}
|
||||
exports.createFromAstroFilePath = createFromAstroFilePath;
|
||||
function createFromFrameworkFilePath(filePath, framework, ts, forceText) {
|
||||
const className = classNameFromFilename(filePath);
|
||||
const originalText = forceText ?? ts.sys.readFile(filePath) ?? '';
|
||||
let code = '';
|
||||
if (framework === 'svelte') {
|
||||
const svelteIntegration = (0, importPackage_1.importSvelteIntegration)(filePath);
|
||||
if (svelteIntegration) {
|
||||
code = svelteIntegration.toTSX(originalText, className);
|
||||
}
|
||||
}
|
||||
else if (framework === 'vue') {
|
||||
const vueIntegration = (0, importPackage_1.importVueIntegration)(filePath);
|
||||
if (vueIntegration) {
|
||||
code = vueIntegration.toTSX(originalText, className);
|
||||
}
|
||||
}
|
||||
return new DocumentSnapshot_1.TypeScriptDocumentSnapshot(0, filePath, code, ts.ScriptKind.TSX, false);
|
||||
}
|
||||
exports.createFromFrameworkFilePath = createFromFrameworkFilePath;
|
||||
function classNameFromFilename(filename) {
|
||||
const url = vscode_uri_1.URI.parse(filename);
|
||||
const withoutExtensions = vscode_uri_1.Utils.basename(url).slice(0, -vscode_uri_1.Utils.extname(url).length);
|
||||
const withoutInvalidCharacters = withoutExtensions
|
||||
.split('')
|
||||
// Although "-" is invalid, we leave it in, pascal-case-handling will throw it out later
|
||||
.filter((char) => /[A-Za-z$_\d-]/.test(char))
|
||||
.join('');
|
||||
const firstValidCharIdx = withoutInvalidCharacters
|
||||
.split('')
|
||||
// Although _ and $ are valid first characters for classes, they are invalid first characters
|
||||
// for tag names. For a better import autocompletion experience, we therefore throw them out.
|
||||
.findIndex((char) => /[A-Za-z]/.test(char));
|
||||
const withoutLeadingInvalidCharacters = withoutInvalidCharacters.substr(firstValidCharIdx);
|
||||
const inPascalCase = (0, utils_1.toPascalCase)(withoutLeadingInvalidCharacters);
|
||||
const finalName = firstValidCharIdx === -1 ? `A${inPascalCase}` : inPascalCase;
|
||||
return finalName;
|
||||
}
|
||||
exports.classNameFromFilename = classNameFromFilename;
|
||||
75
node_modules/@astrojs/language-server/dist/plugins/typescript/utils.d.ts
generated
vendored
Normal file
75
node_modules/@astrojs/language-server/dist/plugins/typescript/utils.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
import type ts from 'typescript';
|
||||
import type { Node } from 'vscode-html-languageservice';
|
||||
import { CompletionItemKind, Position, Range, SemanticTokensLegend, SymbolKind } from 'vscode-languageserver';
|
||||
import { AstroDocument, TagInformation } from '../../core/documents';
|
||||
import type { AstroSnapshot, DocumentSnapshot, ScriptTagDocumentSnapshot } from './snapshots/DocumentSnapshot';
|
||||
export declare const enum TokenType {
|
||||
class = 0,
|
||||
enum = 1,
|
||||
interface = 2,
|
||||
namespace = 3,
|
||||
typeParameter = 4,
|
||||
type = 5,
|
||||
parameter = 6,
|
||||
variable = 7,
|
||||
enumMember = 8,
|
||||
property = 9,
|
||||
function = 10,
|
||||
method = 11
|
||||
}
|
||||
export declare const enum TokenModifier {
|
||||
declaration = 0,
|
||||
static = 1,
|
||||
async = 2,
|
||||
readonly = 3,
|
||||
defaultLibrary = 4,
|
||||
local = 5
|
||||
}
|
||||
export declare function getSemanticTokenLegend(): SemanticTokensLegend;
|
||||
export declare function symbolKindFromString(kind: string): SymbolKind;
|
||||
export declare function scriptElementKindToCompletionItemKind(kind: ts.ScriptElementKind, ts: typeof import('typescript/lib/tsserverlibrary')): CompletionItemKind;
|
||||
export declare function getCommitCharactersForScriptElement(kind: ts.ScriptElementKind, ts: typeof import('typescript/lib/tsserverlibrary')): string[] | undefined;
|
||||
export declare function getExtensionFromScriptKind(kind: ts.ScriptKind | undefined, ts: typeof import('typescript/lib/tsserverlibrary')): ts.Extension;
|
||||
export declare function findTsConfigPath(fileName: string, rootUris: string[], ts: typeof import('typescript/lib/tsserverlibrary')): string;
|
||||
export declare function isSubPath(uri: string, possibleSubPath: string): boolean;
|
||||
export declare function getScriptKindFromFileName(fileName: string, ts: typeof import('typescript/lib/tsserverlibrary')): ts.ScriptKind;
|
||||
export declare function convertRange(document: {
|
||||
positionAt: (offset: number) => Position;
|
||||
}, range: {
|
||||
start?: number;
|
||||
length?: number;
|
||||
}): Range;
|
||||
export declare function convertToLocationRange(defDoc: DocumentSnapshot, textSpan: ts.TextSpan): Range;
|
||||
export declare function ensureFrontmatterInsert(resultRange: Range, document: AstroDocument): Range;
|
||||
export declare function checkEndOfFileCodeInsert(resultRange: Range, document: AstroDocument): Range;
|
||||
export declare function removeAstroComponentSuffix(name: string): string;
|
||||
export type FrameworkExt = 'astro' | 'vue' | 'jsx' | 'tsx' | 'svelte';
|
||||
type FrameworkVirtualExt = 'ts' | 'tsx';
|
||||
export declare function getFrameworkFromFilePath(filePath: string): FrameworkExt;
|
||||
export declare function isVirtualFrameworkFilePath(ext: FrameworkExt, virtualExt: FrameworkVirtualExt, filePath: string): boolean;
|
||||
export declare function isAstroFilePath(filePath: string): boolean;
|
||||
export declare function isFrameworkFilePath(filePath: string): boolean;
|
||||
export declare function isVirtualAstroFilePath(filePath: string): boolean;
|
||||
export declare function isVirtualVueFilePath(filePath: string): boolean;
|
||||
export declare function isVirtualSvelteFilePath(filePath: string): boolean;
|
||||
export declare function isVirtualFilePath(filePath: string): boolean;
|
||||
export declare function toVirtualAstroFilePath(filePath: string): string;
|
||||
export declare function toVirtualFilePath(filePath: string): string;
|
||||
export declare function toRealAstroFilePath(filePath: string): string;
|
||||
export declare function ensureRealAstroFilePath(filePath: string): string;
|
||||
export declare function ensureRealFilePath(filePath: string): string;
|
||||
export declare function isDocumentSymbolsPath(filePath: string): boolean;
|
||||
/**
|
||||
* Return if a script tag is TypeScript or JavaScript
|
||||
*/
|
||||
export declare function getScriptTagLanguage(scriptTag: TagInformation): 'js' | 'ts';
|
||||
export declare function getScriptTagSnapshot(snapshot: AstroSnapshot, document: AstroDocument, tagInfo: Node | {
|
||||
start: number;
|
||||
end: number;
|
||||
}, position?: Position): {
|
||||
snapshot: ScriptTagDocumentSnapshot;
|
||||
filePath: string;
|
||||
index: number;
|
||||
offset: number;
|
||||
};
|
||||
export {};
|
||||
366
node_modules/@astrojs/language-server/dist/plugins/typescript/utils.js
generated
vendored
Normal file
366
node_modules/@astrojs/language-server/dist/plugins/typescript/utils.js
generated
vendored
Normal file
|
|
@ -0,0 +1,366 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getScriptTagSnapshot = exports.getScriptTagLanguage = exports.isDocumentSymbolsPath = exports.ensureRealFilePath = exports.ensureRealAstroFilePath = exports.toRealAstroFilePath = exports.toVirtualFilePath = exports.toVirtualAstroFilePath = exports.isVirtualFilePath = exports.isVirtualSvelteFilePath = exports.isVirtualVueFilePath = exports.isVirtualAstroFilePath = exports.isFrameworkFilePath = exports.isAstroFilePath = exports.isVirtualFrameworkFilePath = exports.getFrameworkFromFilePath = exports.removeAstroComponentSuffix = exports.checkEndOfFileCodeInsert = exports.ensureFrontmatterInsert = exports.convertToLocationRange = exports.convertRange = exports.getScriptKindFromFileName = exports.isSubPath = exports.findTsConfigPath = exports.getExtensionFromScriptKind = exports.getCommitCharactersForScriptElement = exports.scriptElementKindToCompletionItemKind = exports.symbolKindFromString = exports.getSemanticTokenLegend = void 0;
|
||||
const path_1 = require("path");
|
||||
const vscode_languageserver_1 = require("vscode-languageserver");
|
||||
const documents_1 = require("../../core/documents");
|
||||
const utils_1 = require("../../utils");
|
||||
function getSemanticTokenLegend() {
|
||||
const tokenModifiers = [];
|
||||
[
|
||||
[0 /* TokenModifier.declaration */, vscode_languageserver_1.SemanticTokenModifiers.declaration],
|
||||
[1 /* TokenModifier.static */, vscode_languageserver_1.SemanticTokenModifiers.static],
|
||||
[2 /* TokenModifier.async */, vscode_languageserver_1.SemanticTokenModifiers.async],
|
||||
[3 /* TokenModifier.readonly */, vscode_languageserver_1.SemanticTokenModifiers.readonly],
|
||||
[4 /* TokenModifier.defaultLibrary */, vscode_languageserver_1.SemanticTokenModifiers.defaultLibrary],
|
||||
[5 /* TokenModifier.local */, 'local'],
|
||||
].forEach(([tsModifier, legend]) => (tokenModifiers[tsModifier] = legend));
|
||||
const tokenTypes = [];
|
||||
[
|
||||
[0 /* TokenType.class */, vscode_languageserver_1.SemanticTokenTypes.class],
|
||||
[1 /* TokenType.enum */, vscode_languageserver_1.SemanticTokenTypes.enum],
|
||||
[2 /* TokenType.interface */, vscode_languageserver_1.SemanticTokenTypes.interface],
|
||||
[3 /* TokenType.namespace */, vscode_languageserver_1.SemanticTokenTypes.namespace],
|
||||
[4 /* TokenType.typeParameter */, vscode_languageserver_1.SemanticTokenTypes.typeParameter],
|
||||
[5 /* TokenType.type */, vscode_languageserver_1.SemanticTokenTypes.type],
|
||||
[6 /* TokenType.parameter */, vscode_languageserver_1.SemanticTokenTypes.parameter],
|
||||
[7 /* TokenType.variable */, vscode_languageserver_1.SemanticTokenTypes.variable],
|
||||
[8 /* TokenType.enumMember */, vscode_languageserver_1.SemanticTokenTypes.enumMember],
|
||||
[9 /* TokenType.property */, vscode_languageserver_1.SemanticTokenTypes.property],
|
||||
[10 /* TokenType.function */, vscode_languageserver_1.SemanticTokenTypes.function],
|
||||
[11 /* TokenType.method */, vscode_languageserver_1.SemanticTokenTypes.method],
|
||||
].forEach(([tokenType, legend]) => (tokenTypes[tokenType] = legend));
|
||||
return {
|
||||
tokenModifiers,
|
||||
tokenTypes,
|
||||
};
|
||||
}
|
||||
exports.getSemanticTokenLegend = getSemanticTokenLegend;
|
||||
function symbolKindFromString(kind) {
|
||||
switch (kind) {
|
||||
case 'module':
|
||||
return vscode_languageserver_1.SymbolKind.Module;
|
||||
case 'class':
|
||||
return vscode_languageserver_1.SymbolKind.Class;
|
||||
case 'local class':
|
||||
return vscode_languageserver_1.SymbolKind.Class;
|
||||
case 'interface':
|
||||
return vscode_languageserver_1.SymbolKind.Interface;
|
||||
case 'enum':
|
||||
return vscode_languageserver_1.SymbolKind.Enum;
|
||||
case 'enum member':
|
||||
return vscode_languageserver_1.SymbolKind.Constant;
|
||||
case 'var':
|
||||
return vscode_languageserver_1.SymbolKind.Variable;
|
||||
case 'local var':
|
||||
return vscode_languageserver_1.SymbolKind.Variable;
|
||||
case 'function':
|
||||
return vscode_languageserver_1.SymbolKind.Function;
|
||||
case 'local function':
|
||||
return vscode_languageserver_1.SymbolKind.Function;
|
||||
case 'method':
|
||||
return vscode_languageserver_1.SymbolKind.Method;
|
||||
case 'getter':
|
||||
return vscode_languageserver_1.SymbolKind.Method;
|
||||
case 'setter':
|
||||
return vscode_languageserver_1.SymbolKind.Method;
|
||||
case 'property':
|
||||
return vscode_languageserver_1.SymbolKind.Property;
|
||||
case 'constructor':
|
||||
return vscode_languageserver_1.SymbolKind.Constructor;
|
||||
case 'parameter':
|
||||
return vscode_languageserver_1.SymbolKind.Variable;
|
||||
case 'type parameter':
|
||||
return vscode_languageserver_1.SymbolKind.Variable;
|
||||
case 'alias':
|
||||
return vscode_languageserver_1.SymbolKind.Variable;
|
||||
case 'let':
|
||||
return vscode_languageserver_1.SymbolKind.Variable;
|
||||
case 'const':
|
||||
return vscode_languageserver_1.SymbolKind.Constant;
|
||||
case 'JSX attribute':
|
||||
return vscode_languageserver_1.SymbolKind.Property;
|
||||
default:
|
||||
return vscode_languageserver_1.SymbolKind.Variable;
|
||||
}
|
||||
}
|
||||
exports.symbolKindFromString = symbolKindFromString;
|
||||
function scriptElementKindToCompletionItemKind(kind, ts) {
|
||||
switch (kind) {
|
||||
case ts.ScriptElementKind.primitiveType:
|
||||
case ts.ScriptElementKind.keyword:
|
||||
return vscode_languageserver_1.CompletionItemKind.Keyword;
|
||||
case ts.ScriptElementKind.constElement:
|
||||
return vscode_languageserver_1.CompletionItemKind.Constant;
|
||||
case ts.ScriptElementKind.letElement:
|
||||
case ts.ScriptElementKind.variableElement:
|
||||
case ts.ScriptElementKind.localVariableElement:
|
||||
case ts.ScriptElementKind.alias:
|
||||
return vscode_languageserver_1.CompletionItemKind.Variable;
|
||||
case ts.ScriptElementKind.memberVariableElement:
|
||||
case ts.ScriptElementKind.memberGetAccessorElement:
|
||||
case ts.ScriptElementKind.memberSetAccessorElement:
|
||||
return vscode_languageserver_1.CompletionItemKind.Field;
|
||||
case ts.ScriptElementKind.functionElement:
|
||||
return vscode_languageserver_1.CompletionItemKind.Function;
|
||||
case ts.ScriptElementKind.memberFunctionElement:
|
||||
case ts.ScriptElementKind.constructSignatureElement:
|
||||
case ts.ScriptElementKind.callSignatureElement:
|
||||
case ts.ScriptElementKind.indexSignatureElement:
|
||||
return vscode_languageserver_1.CompletionItemKind.Method;
|
||||
case ts.ScriptElementKind.enumElement:
|
||||
return vscode_languageserver_1.CompletionItemKind.Enum;
|
||||
case ts.ScriptElementKind.moduleElement:
|
||||
case ts.ScriptElementKind.externalModuleName:
|
||||
return vscode_languageserver_1.CompletionItemKind.Module;
|
||||
case ts.ScriptElementKind.classElement:
|
||||
case ts.ScriptElementKind.typeElement:
|
||||
return vscode_languageserver_1.CompletionItemKind.Class;
|
||||
case ts.ScriptElementKind.interfaceElement:
|
||||
return vscode_languageserver_1.CompletionItemKind.Interface;
|
||||
case ts.ScriptElementKind.warning:
|
||||
case ts.ScriptElementKind.scriptElement:
|
||||
return vscode_languageserver_1.CompletionItemKind.File;
|
||||
case ts.ScriptElementKind.directory:
|
||||
return vscode_languageserver_1.CompletionItemKind.Folder;
|
||||
case ts.ScriptElementKind.string:
|
||||
return vscode_languageserver_1.CompletionItemKind.Constant;
|
||||
}
|
||||
return vscode_languageserver_1.CompletionItemKind.Property;
|
||||
}
|
||||
exports.scriptElementKindToCompletionItemKind = scriptElementKindToCompletionItemKind;
|
||||
function getCommitCharactersForScriptElement(kind, ts) {
|
||||
const commitCharacters = [];
|
||||
switch (kind) {
|
||||
case ts.ScriptElementKind.memberGetAccessorElement:
|
||||
case ts.ScriptElementKind.memberSetAccessorElement:
|
||||
case ts.ScriptElementKind.constructSignatureElement:
|
||||
case ts.ScriptElementKind.callSignatureElement:
|
||||
case ts.ScriptElementKind.indexSignatureElement:
|
||||
case ts.ScriptElementKind.enumElement:
|
||||
case ts.ScriptElementKind.interfaceElement:
|
||||
commitCharacters.push('.');
|
||||
break;
|
||||
case ts.ScriptElementKind.moduleElement:
|
||||
case ts.ScriptElementKind.alias:
|
||||
case ts.ScriptElementKind.constElement:
|
||||
case ts.ScriptElementKind.letElement:
|
||||
case ts.ScriptElementKind.variableElement:
|
||||
case ts.ScriptElementKind.localVariableElement:
|
||||
case ts.ScriptElementKind.memberVariableElement:
|
||||
case ts.ScriptElementKind.classElement:
|
||||
case ts.ScriptElementKind.functionElement:
|
||||
case ts.ScriptElementKind.memberFunctionElement:
|
||||
commitCharacters.push('.', ',');
|
||||
commitCharacters.push('(');
|
||||
break;
|
||||
}
|
||||
return commitCharacters.length === 0 ? undefined : commitCharacters;
|
||||
}
|
||||
exports.getCommitCharactersForScriptElement = getCommitCharactersForScriptElement;
|
||||
function getExtensionFromScriptKind(kind, ts) {
|
||||
switch (kind) {
|
||||
case ts.ScriptKind.JSX:
|
||||
return ts.Extension.Jsx;
|
||||
case ts.ScriptKind.TS:
|
||||
return ts.Extension.Ts;
|
||||
case ts.ScriptKind.TSX:
|
||||
return ts.Extension.Tsx;
|
||||
case ts.ScriptKind.JSON:
|
||||
return ts.Extension.Json;
|
||||
case ts.ScriptKind.JS:
|
||||
default:
|
||||
return ts.Extension.Js;
|
||||
}
|
||||
}
|
||||
exports.getExtensionFromScriptKind = getExtensionFromScriptKind;
|
||||
function findTsConfigPath(fileName, rootUris, ts) {
|
||||
const searchDir = (0, path_1.dirname)(fileName);
|
||||
const path = ts.findConfigFile(searchDir, ts.sys.fileExists, 'tsconfig.json') ||
|
||||
ts.findConfigFile(searchDir, ts.sys.fileExists, 'jsconfig.json') ||
|
||||
'';
|
||||
// Don't return config files that exceed the current workspace context.
|
||||
return !!path && rootUris.some((rootUri) => isSubPath(rootUri, path)) ? path : '';
|
||||
}
|
||||
exports.findTsConfigPath = findTsConfigPath;
|
||||
function isSubPath(uri, possibleSubPath) {
|
||||
return (0, utils_1.pathToUrl)(possibleSubPath).startsWith(uri);
|
||||
}
|
||||
exports.isSubPath = isSubPath;
|
||||
function getScriptKindFromFileName(fileName, ts) {
|
||||
const ext = fileName.substring(fileName.lastIndexOf('.'));
|
||||
switch (ext.toLowerCase()) {
|
||||
case ts.Extension.Js:
|
||||
return ts.ScriptKind.JS;
|
||||
case ts.Extension.Jsx:
|
||||
return ts.ScriptKind.JSX;
|
||||
case ts.Extension.Ts:
|
||||
return ts.ScriptKind.TS;
|
||||
case ts.Extension.Tsx:
|
||||
return ts.ScriptKind.TSX;
|
||||
case ts.Extension.Json:
|
||||
return ts.ScriptKind.JSON;
|
||||
default:
|
||||
return ts.ScriptKind.Unknown;
|
||||
}
|
||||
}
|
||||
exports.getScriptKindFromFileName = getScriptKindFromFileName;
|
||||
function convertRange(document, range) {
|
||||
return vscode_languageserver_1.Range.create(document.positionAt(range.start || 0), document.positionAt((range.start || 0) + (range.length || 0)));
|
||||
}
|
||||
exports.convertRange = convertRange;
|
||||
function convertToLocationRange(defDoc, textSpan) {
|
||||
const range = (0, documents_1.mapRangeToOriginal)(defDoc, convertRange(defDoc, textSpan));
|
||||
// Some definition like the svelte component class definition don't exist in the original, so we map to 0,1
|
||||
if (range.start.line < 0) {
|
||||
range.start.line = 0;
|
||||
range.start.character = 1;
|
||||
}
|
||||
if (range.end.line < 0) {
|
||||
range.end = range.start;
|
||||
}
|
||||
return range;
|
||||
}
|
||||
exports.convertToLocationRange = convertToLocationRange;
|
||||
// Some code actions will insert code at the start of the file instead of inside our frontmatter
|
||||
// We'll redirect those to the proper starting place
|
||||
function ensureFrontmatterInsert(resultRange, document) {
|
||||
if (document.astroMeta.frontmatter.state === 'closed') {
|
||||
const position = document.positionAt(document.astroMeta.frontmatter.startOffset);
|
||||
position.line += 1;
|
||||
position.character = resultRange.start.character;
|
||||
return vscode_languageserver_1.Range.create(position, position);
|
||||
}
|
||||
return resultRange;
|
||||
}
|
||||
exports.ensureFrontmatterInsert = ensureFrontmatterInsert;
|
||||
// Some code actions ill insert code at the end of the generated TSX file, so we'll manually
|
||||
// redirect it to the end of the frontmatter instead
|
||||
function checkEndOfFileCodeInsert(resultRange, document) {
|
||||
if (resultRange.start.line > document.lineCount) {
|
||||
if (document.astroMeta.frontmatter.state === 'closed') {
|
||||
const position = document.positionAt(document.astroMeta.frontmatter.endOffset);
|
||||
return vscode_languageserver_1.Range.create(position, position);
|
||||
}
|
||||
}
|
||||
return resultRange;
|
||||
}
|
||||
exports.checkEndOfFileCodeInsert = checkEndOfFileCodeInsert;
|
||||
function removeAstroComponentSuffix(name) {
|
||||
return name.replace(/(\w+)__AstroComponent_/, '$1');
|
||||
}
|
||||
exports.removeAstroComponentSuffix = removeAstroComponentSuffix;
|
||||
const VirtualExtension = {
|
||||
ts: 'ts',
|
||||
tsx: 'tsx',
|
||||
};
|
||||
function getFrameworkFromFilePath(filePath) {
|
||||
filePath = ensureRealFilePath(filePath);
|
||||
return (0, path_1.extname)(filePath).substring(1);
|
||||
}
|
||||
exports.getFrameworkFromFilePath = getFrameworkFromFilePath;
|
||||
function isVirtualFrameworkFilePath(ext, virtualExt, filePath) {
|
||||
return filePath.endsWith('.' + ext + '.' + virtualExt);
|
||||
}
|
||||
exports.isVirtualFrameworkFilePath = isVirtualFrameworkFilePath;
|
||||
function isAstroFilePath(filePath) {
|
||||
return filePath.endsWith('.astro');
|
||||
}
|
||||
exports.isAstroFilePath = isAstroFilePath;
|
||||
function isFrameworkFilePath(filePath) {
|
||||
return filePath.endsWith('.svelte') || filePath.endsWith('.vue');
|
||||
}
|
||||
exports.isFrameworkFilePath = isFrameworkFilePath;
|
||||
function isVirtualAstroFilePath(filePath) {
|
||||
return isVirtualFrameworkFilePath('astro', VirtualExtension.tsx, filePath);
|
||||
}
|
||||
exports.isVirtualAstroFilePath = isVirtualAstroFilePath;
|
||||
function isVirtualVueFilePath(filePath) {
|
||||
return isVirtualFrameworkFilePath('vue', VirtualExtension.tsx, filePath);
|
||||
}
|
||||
exports.isVirtualVueFilePath = isVirtualVueFilePath;
|
||||
function isVirtualSvelteFilePath(filePath) {
|
||||
return isVirtualFrameworkFilePath('svelte', VirtualExtension.tsx, filePath);
|
||||
}
|
||||
exports.isVirtualSvelteFilePath = isVirtualSvelteFilePath;
|
||||
function isVirtualFilePath(filePath) {
|
||||
return isVirtualAstroFilePath(filePath) || isVirtualVueFilePath(filePath) || isVirtualSvelteFilePath(filePath);
|
||||
}
|
||||
exports.isVirtualFilePath = isVirtualFilePath;
|
||||
function toVirtualAstroFilePath(filePath) {
|
||||
if (isVirtualAstroFilePath(filePath)) {
|
||||
return filePath;
|
||||
}
|
||||
else if (isAstroFilePath(filePath)) {
|
||||
return `${filePath}.tsx`;
|
||||
}
|
||||
else {
|
||||
return filePath;
|
||||
}
|
||||
}
|
||||
exports.toVirtualAstroFilePath = toVirtualAstroFilePath;
|
||||
function toVirtualFilePath(filePath) {
|
||||
if (isVirtualFilePath(filePath)) {
|
||||
return filePath;
|
||||
}
|
||||
else if (isFrameworkFilePath(filePath) || isAstroFilePath(filePath)) {
|
||||
return `${filePath}.tsx`;
|
||||
}
|
||||
else {
|
||||
return filePath;
|
||||
}
|
||||
}
|
||||
exports.toVirtualFilePath = toVirtualFilePath;
|
||||
function toRealAstroFilePath(filePath) {
|
||||
return filePath.slice(0, -'.tsx'.length);
|
||||
}
|
||||
exports.toRealAstroFilePath = toRealAstroFilePath;
|
||||
function ensureRealAstroFilePath(filePath) {
|
||||
return isVirtualAstroFilePath(filePath) ? toRealAstroFilePath(filePath) : filePath;
|
||||
}
|
||||
exports.ensureRealAstroFilePath = ensureRealAstroFilePath;
|
||||
function ensureRealFilePath(filePath) {
|
||||
// For Document Symbols, we need to return a different snapshot, so we append a query param to the file path
|
||||
// However, we need this removed when we need to deal with real (as in, real on the filesystem) paths
|
||||
filePath = filePath.replace('?documentSymbols', '');
|
||||
if (isVirtualFilePath(filePath)) {
|
||||
let extLen = filePath.endsWith('.tsx') ? 4 : 3;
|
||||
return filePath.slice(0, filePath.length - extLen);
|
||||
}
|
||||
else {
|
||||
return filePath;
|
||||
}
|
||||
}
|
||||
exports.ensureRealFilePath = ensureRealFilePath;
|
||||
function isDocumentSymbolsPath(filePath) {
|
||||
return filePath.endsWith('?documentSymbols');
|
||||
}
|
||||
exports.isDocumentSymbolsPath = isDocumentSymbolsPath;
|
||||
/**
|
||||
* Return if a script tag is TypeScript or JavaScript
|
||||
*/
|
||||
function getScriptTagLanguage(scriptTag) {
|
||||
// Using any kind of attributes on the script tag will disable hoisting, so we can just check if there's any
|
||||
if (Object.entries(scriptTag.attributes).length === 0) {
|
||||
return 'ts';
|
||||
}
|
||||
return 'js';
|
||||
}
|
||||
exports.getScriptTagLanguage = getScriptTagLanguage;
|
||||
function getScriptTagSnapshot(snapshot, document, tagInfo, position) {
|
||||
const index = document.scriptTags.findIndex((value) => value.container.start == tagInfo.start);
|
||||
const scriptTagLanguage = getScriptTagLanguage(document.scriptTags[index]);
|
||||
const scriptFilePath = snapshot.filePath + `.__script${index}.${scriptTagLanguage}`;
|
||||
const scriptTagSnapshot = snapshot.scriptTagSnapshots[index];
|
||||
let offset = 0;
|
||||
if (position) {
|
||||
offset = scriptTagSnapshot.offsetAt(scriptTagSnapshot.getGeneratedPosition(position));
|
||||
}
|
||||
return {
|
||||
snapshot: scriptTagSnapshot,
|
||||
filePath: scriptFilePath,
|
||||
index,
|
||||
offset,
|
||||
};
|
||||
}
|
||||
exports.getScriptTagSnapshot = getScriptTagSnapshot;
|
||||
Loading…
Add table
Add a link
Reference in a new issue