svelte-language-server
Version:
A language server for Svelte
116 lines • 5.67 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SemanticTokensProviderImpl = void 0;
const typescript_1 = __importDefault(require("typescript"));
const vscode_languageserver_1 = require("vscode-languageserver");
const documents_1 = require("../../../lib/documents");
const utils_1 = require("../utils");
const utils_2 = require("./utils");
const svelte2tsx_1 = require("svelte2tsx");
const CONTENT_LENGTH_LIMIT = 50000;
class SemanticTokensProviderImpl {
constructor(lsAndTsDocResolver) {
this.lsAndTsDocResolver = lsAndTsDocResolver;
}
async getSemanticTokens(textDocument, range, cancellationToken) {
const { lang, tsDoc } = await this.lsAndTsDocResolver.getLSAndTSDoc(textDocument);
// for better performance, don't do full-file semantic tokens when the file is too big
if ((!range && tsDoc.getLength() > CONTENT_LENGTH_LIMIT) ||
cancellationToken?.isCancellationRequested) {
return null;
}
// No script tags -> nothing to analyse semantic tokens for
if (!textDocument.scriptInfo && !textDocument.moduleScriptInfo) {
return null;
}
const textSpan = range
? (0, utils_1.convertToTextSpan)(range, tsDoc)
: {
start: 0,
length: tsDoc.parserError
? tsDoc.getLength()
: // This is appended by svelte2tsx, there's nothing mappable afterwards
tsDoc.getFullText().lastIndexOf('return { props:') || tsDoc.getLength()
};
const { spans } = lang.getEncodedSemanticClassifications(tsDoc.filePath, textSpan, typescript_1.default.SemanticClassificationFormat.TwentyTwenty);
const data = [];
let index = 0;
while (index < spans.length) {
// [start, length, encodedClassification, start2, length2, encodedClassification2]
const generatedOffset = spans[index++];
const generatedLength = spans[index++];
const encodedClassification = spans[index++];
const classificationType = this.getTokenTypeFromClassification(encodedClassification);
if (classificationType < 0) {
continue;
}
const original = this.map(textDocument, tsDoc, generatedOffset, generatedLength, encodedClassification, classificationType);
// remove identifiers whose start and end mapped to the same location,
// like the svelte2tsx inserted render function,
// or reversed like Component.$on
if (!original || original[2] <= 0) {
continue;
}
data.push(original);
}
const sorted = data.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));
return builder.build();
}
map(document, snapshot, generatedOffset, generatedLength, encodedClassification, classificationType) {
const text = snapshot.getFullText();
if ((0, utils_2.isInGeneratedCode)(text, generatedOffset, generatedOffset + generatedLength) ||
(encodedClassification === 2817 /* top level function */ &&
text.substring(generatedOffset, generatedOffset + generatedLength) ===
svelte2tsx_1.internalHelpers.renderName)) {
return;
}
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);
// Ensure components in the template get no semantic highlighting
if ((classificationType === 0 /* TokenType.class */ ||
classificationType === 5 /* TokenType.type */ ||
classificationType === 6 /* TokenType.parameter */ ||
classificationType === 7 /* TokenType.variable */ ||
classificationType === 10 /* TokenType.function */) &&
snapshot.svelteNodeAt(startOffset)?.type === 'InlineComponent' &&
(document.getText().charCodeAt(startOffset - 1) === /* < */ 60 ||
document.getText().charCodeAt(startOffset - 1) === /* / */ 47)) {
return;
}
return [
startPosition.line,
startPosition.character,
endOffset - startOffset,
classificationType,
this.getTokenModifierFromClassification(encodedClassification)
];
}
/**
* TSClassification = (TokenType + 1) << TokenEncodingConsts.typeOffset + TokenModifier
*/
getTokenTypeFromClassification(tsClassification) {
return (tsClassification >> 8 /* TokenEncodingConsts.typeOffset */) - 1;
}
getTokenModifierFromClassification(tsClassification) {
return tsClassification & 255 /* TokenEncodingConsts.modifierMask */;
}
}
exports.SemanticTokensProviderImpl = SemanticTokensProviderImpl;
//# sourceMappingURL=SemanticTokensProvider.js.map