svelte-language-server
Version:
A language server for Svelte
116 lines • 4.83 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.JsOrTsComponentInfoProvider = void 0;
const typescript_1 = __importDefault(require("typescript"));
const utils_1 = require("../../utils");
const utils_2 = require("./features/utils");
class JsOrTsComponentInfoProvider {
constructor(typeChecker, classType, useSvelte5PlusPropsParameter = false) {
this.typeChecker = typeChecker;
this.classType = classType;
this.useSvelte5PlusPropsParameter = useSvelte5PlusPropsParameter;
}
getEvents() {
const eventType = this.getType(this.useSvelte5PlusPropsParameter ? '$$events' : '$$events_def');
if (!eventType) {
return [];
}
return this.mapPropertiesOfType(eventType);
}
getSlotLets(slot = 'default') {
const slotType = this.getType(this.useSvelte5PlusPropsParameter ? '$$slots' : '$$slot_def');
if (!slotType) {
return [];
}
const slotLets = slotType.getProperties().find((prop) => prop.name === slot);
if (!slotLets?.valueDeclaration) {
return [];
}
const slotLetsType = this.typeChecker.getTypeOfSymbolAtLocation(slotLets, slotLets.valueDeclaration);
return this.mapPropertiesOfType(slotLetsType);
}
getProps() {
if (!this.useSvelte5PlusPropsParameter) {
const props = this.getType('$$prop_def');
if (!props) {
return [];
}
return this.mapPropertiesOfType(props);
}
return this.mapPropertiesOfType(this.classType).filter((prop) => !prop.name.startsWith('$$'));
}
getType(classProperty) {
const symbol = this.classType.getProperty(classProperty);
if (!symbol?.valueDeclaration) {
return null;
}
return this.typeChecker.getTypeOfSymbolAtLocation(symbol, symbol.valueDeclaration);
}
mapPropertiesOfType(type) {
return type
.getProperties()
.map((prop) => {
// type would still be correct when there're multiple declarations
const declaration = prop.valueDeclaration ??
prop.declarations?.[0] ??
// very complex types are hidden on this thing for some reason
prop?.links?.mappedType?.declaration;
if (!declaration) {
return;
}
return {
name: prop.name,
type: this.typeChecker.typeToString(this.typeChecker.getTypeOfSymbolAtLocation(prop, declaration)),
doc: typescript_1.default.displayPartsToString(prop.getDocumentationComment(this.typeChecker))
};
})
.filter(utils_1.isNotNullOrUndefined);
}
/**
* The result of this shouldn't be cached as it could lead to memory leaks. The type checker
* could become old and then multiple versions of it could exist.
*/
static create(lang, def, isSvelte5Plus) {
const program = lang.getProgram();
const sourceFile = program?.getSourceFile(def.fileName);
if (!program || !sourceFile) {
return null;
}
const defIdentifier = (0, utils_2.findContainingNode)(sourceFile, def.textSpan, typescript_1.default.isIdentifier);
if (!defIdentifier) {
return null;
}
const typeChecker = program.getTypeChecker();
const componentSymbol = typeChecker.getSymbolAtLocation(defIdentifier);
if (!componentSymbol) {
return null;
}
const type = typeChecker.getTypeOfSymbolAtLocation(componentSymbol, defIdentifier);
if (type.isClass()) {
return new JsOrTsComponentInfoProvider(typeChecker, type);
}
const constructorSignatures = type.getConstructSignatures();
if (constructorSignatures.length === 1) {
return new JsOrTsComponentInfoProvider(typeChecker, constructorSignatures[0].getReturnType());
}
if (!isSvelte5Plus) {
return null;
}
const signatures = type.getCallSignatures();
if (signatures.length !== 1) {
return null;
}
const propsParameter = signatures[0].parameters[1];
if (!propsParameter) {
return null;
}
const propsParameterType = typeChecker.getTypeOfSymbol(propsParameter);
return new JsOrTsComponentInfoProvider(typeChecker, propsParameterType,
/** useSvelte5PlusPropsParameter */ true);
}
}
exports.JsOrTsComponentInfoProvider = JsOrTsComponentInfoProvider;
//# sourceMappingURL=ComponentInfoProvider.js.map