@vue/typescript-plugin
Advanced tools
| import { type Language, type SourceScript, type VueVirtualCode } from '@vue/language-core'; | ||
| import type * as ts from 'typescript'; | ||
| export interface ComponentPropInfo { | ||
| name: string; | ||
| description?: string; | ||
| optional?: boolean; | ||
| boolean?: boolean; | ||
| } | ||
| export declare function getComponentProps(ts: typeof import('typescript'), tsLanguageService: ts.LanguageService, session: ts.server.Session, language: Language, sourceScript: SourceScript<string>, virtualCode: VueVirtualCode, position: number): ComponentPropInfo[]; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.getComponentProps = getComponentProps; | ||
| const transform_1 = require("@volar/typescript/lib/node/transform"); | ||
| const language_core_1 = require("@vue/language-core"); | ||
| function getComponentProps(ts, tsLanguageService, session, language, sourceScript, virtualCode, position) { | ||
| const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(virtualCode); | ||
| if (!serviceScript) { | ||
| return []; | ||
| } | ||
| const { ir } = virtualCode; | ||
| if (!ir.template?.ast) { | ||
| return []; | ||
| } | ||
| let node; | ||
| for (const child of (0, language_core_1.forEachElementNode)(ir.template.ast)) { | ||
| if (position >= child.loc.start.offset) { | ||
| node = child; | ||
| } | ||
| } | ||
| if (node?.tagType !== 1) { | ||
| return []; | ||
| } | ||
| let position2; | ||
| if (node.props.some(prop => position >= prop.loc.start.offset && position <= prop.loc.end.offset)) { | ||
| position2 = (0, transform_1.toGeneratedOffset)(language, serviceScript, sourceScript, ir.template.startTagEnd + position - ( | ||
| // <Comp :foo-| /> -> { "foo"|: ... } | ||
| ir.template.content[position - 1] === '-' ? 1 : 0), (data) => !!data.__propsCompletion); | ||
| } | ||
| position2 ??= (0, transform_1.toGeneratedOffset)(language, serviceScript, sourceScript, ir.template.startTagEnd + node.loc.start.offset, (data) => !!data.__propsCompletion); | ||
| if (!position2) { | ||
| return []; | ||
| } | ||
| const preferences = session['getPreferences'](); | ||
| const completion = tsLanguageService.getCompletionsAtPosition(virtualCode.fileName, position2, preferences); | ||
| // skip fallback global completions | ||
| if (!completion?.isMemberCompletion) { | ||
| return []; | ||
| } | ||
| return completion?.entries.map(entry => { | ||
| const modifiers = entry.kindModifiers?.split(','); | ||
| const details = tsLanguageService.getCompletionEntryDetails(virtualCode.fileName, position2, entry.name, session['getFormatOptions'](), entry.source, preferences, entry.data); | ||
| const info = { | ||
| name: entry.name.startsWith('"') && entry.name.endsWith('"') | ||
| ? entry.name.slice(1, -1) | ||
| : entry.name, | ||
| description: ts.displayPartsToString(details?.documentation) + (details?.tags | ||
| ? '\n\n' + details.tags.map(tag => `*@${tag.name}* — ${ts.displayPartsToString(tag.text)}`).join('\n') | ||
| : ''), | ||
| }; | ||
| if (modifiers?.includes('optional')) { | ||
| info.optional = true; | ||
| } | ||
| if (details?.displayParts.some((part, i) => i >= 7 && part.text === 'boolean')) { | ||
| info.boolean = true; | ||
| } | ||
| return info; | ||
| }); | ||
| } | ||
| //# sourceMappingURL=getComponentProps.js.map |
+21
-12
@@ -35,3 +35,3 @@ "use strict"; | ||
| })(); | ||
| const transform_js_1 = require("@volar/typescript/lib/node/transform.js"); | ||
| const transform_1 = require("@volar/typescript/lib/node/transform"); | ||
| const createLanguageServicePlugin_1 = require("@volar/typescript/lib/quickstart/createLanguageServicePlugin"); | ||
@@ -44,2 +44,3 @@ const core = __importStar(require("@vue/language-core")); | ||
| const getComponentNames_1 = require("./lib/requests/getComponentNames"); | ||
| const getComponentProps_1 = require("./lib/requests/getComponentProps"); | ||
| const getComponentSlots_1 = require("./lib/requests/getComponentSlots"); | ||
@@ -191,3 +192,3 @@ const getElementAttrs_1 = require("./lib/requests/getElementAttrs"); | ||
| for (const codeAction of details.codeActions ?? []) { | ||
| codeAction.changes = (0, transform_js_1.transformFileTextChanges)(language, codeAction.changes, false, core.isCompletionEnabled); | ||
| codeAction.changes = (0, transform_1.transformFileTextChanges)(language, codeAction.changes, false, core.isCompletionEnabled); | ||
| } | ||
@@ -198,7 +199,2 @@ (0, common_1.resolveCompletionEntryDetails)(language, details, data); | ||
| }); | ||
| session.addProtocolHandler('_vue:isRefAtPosition', request => { | ||
| const [fileName, position] = request.arguments; | ||
| const { program, language, sourceScript, virtualCode } = getProjectAndVirtualCode(fileName); | ||
| return createResponse((0, isRefAtPosition_1.isRefAtPosition)(ts, language, program, sourceScript, virtualCode, position, sourceScript.generated ? sourceScript.snapshot.getLength() : 0)); | ||
| }); | ||
| session.addProtocolHandler('_vue:getComponentDirectives', request => { | ||
@@ -209,2 +205,7 @@ const [fileName] = request.arguments; | ||
| }); | ||
| session.addProtocolHandler('_vue:getComponentMeta', request => { | ||
| const [fileName, tag] = request.arguments; | ||
| const { program, virtualCode, language } = getProjectAndVirtualCode(fileName); | ||
| return createResponse((0, getComponentMeta_1.getComponentMeta)(ts, program, language, fileName => language.scripts.get(fileName), program.getSourceFile(virtualCode.fileName), virtualCode, tag)); | ||
| }); | ||
| session.addProtocolHandler('_vue:getComponentNames', request => { | ||
@@ -215,7 +216,10 @@ const [fileName] = request.arguments; | ||
| }); | ||
| session.addProtocolHandler('_vue:getComponentMeta', request => { | ||
| const [fileName, tag] = request.arguments; | ||
| const { program, virtualCode, language } = getProjectAndVirtualCode(fileName); | ||
| const sourceFile = program.getSourceFile(virtualCode.fileName); | ||
| return createResponse((0, getComponentMeta_1.getComponentMeta)(ts, program, language, fileName => language.scripts.get(fileName), sourceFile, virtualCode, tag)); | ||
| session.addProtocolHandler('_vue:getComponentProps', request => { | ||
| const [fileName, position] = request.arguments; | ||
| const { project, language, sourceScript, virtualCode } = getProjectAndVirtualCode(fileName); | ||
| const tsLanguageService = projectToOriginalLanguageService.get(project); | ||
| if (!tsLanguageService) { | ||
| return createResponse(undefined); | ||
| } | ||
| return createResponse((0, getComponentProps_1.getComponentProps)(ts, tsLanguageService, session, language, sourceScript, virtualCode, position)); | ||
| }); | ||
@@ -237,2 +241,7 @@ session.addProtocolHandler('_vue:getComponentSlots', request => { | ||
| }); | ||
| session.addProtocolHandler('_vue:isRefAtPosition', request => { | ||
| const [fileName, position] = request.arguments; | ||
| const { program, language, sourceScript, virtualCode } = getProjectAndVirtualCode(fileName); | ||
| return createResponse((0, isRefAtPosition_1.isRefAtPosition)(ts, language, program, sourceScript, virtualCode, position)); | ||
| }); | ||
| session.addProtocolHandler('_vue:resolveModuleName', request => { | ||
@@ -239,0 +248,0 @@ const [fileName, ...args] = request.arguments; |
+45
-55
@@ -11,2 +11,3 @@ "use strict"; | ||
| const shared_1 = require("@vue/shared"); | ||
| const utils_2 = require("./requests/utils"); | ||
| const windowsPathReg = /\\/g; | ||
@@ -55,3 +56,3 @@ function preprocessLanguageService(languageService, getLanguage) { | ||
| } | ||
| const codegen = language_core_1.tsCodegen.get(sourceScript.generated.root.sfc); | ||
| const codegen = language_core_1.tsCodegen.get(sourceScript.generated.root.ir); | ||
| const leadingOffset = sourceScript.snapshot.getLength(); | ||
@@ -81,3 +82,3 @@ for (const sourceRange of (0, transform_1.toSourceRanges)(sourceScript, language, serviceScript, result.textSpan.start, result.textSpan.start + result.textSpan.length, true, () => true)) { | ||
| } | ||
| const [serviceScript, _targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName); | ||
| const [serviceScript, , sourceScript] = (0, utils_1.getServiceScript)(language, fileName); | ||
| if (!serviceScript || !(sourceScript?.generated?.root instanceof language_core_1.VueVirtualCode)) { | ||
@@ -124,3 +125,3 @@ return result; | ||
| } | ||
| const codegen = language_core_1.tsCodegen.get(sourceScript.generated.root.sfc); | ||
| const codegen = language_core_1.tsCodegen.get(sourceScript.generated.root.ir); | ||
| const leadingOffset = sourceScript.snapshot.getLength(); | ||
@@ -154,3 +155,3 @@ for (const diagnostic of result) { | ||
| } | ||
| const [serviceScript, _targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName); | ||
| const [serviceScript, , sourceScript] = (0, utils_1.getServiceScript)(language, fileName); | ||
| if (!serviceScript || !(sourceScript?.generated?.root instanceof language_core_1.VueVirtualCode)) { | ||
@@ -182,3 +183,3 @@ return result; | ||
| } | ||
| const [serviceScript, _targetScript, sourceScript] = (0, utils_1.getServiceScript)(language, fileName); | ||
| const [serviceScript, , sourceScript] = (0, utils_1.getServiceScript)(language, fileName); | ||
| if (!serviceScript || !(sourceScript?.generated?.root instanceof language_core_1.VueVirtualCode)) { | ||
@@ -306,3 +307,3 @@ return result; | ||
| } | ||
| const styles = root.sfc.styles; | ||
| const styles = root.ir.styles; | ||
| if (!styles.length) { | ||
@@ -356,2 +357,5 @@ return result; | ||
| const result = getDefinitionAndBoundSpan(fileName, position, ...rests); | ||
| if (!result?.definitions?.length) { | ||
| return result; | ||
| } | ||
| const program = languageService.getProgram(); | ||
@@ -363,17 +367,13 @@ const sourceScript = language.scripts.get(asScriptId(fileName)); | ||
| } | ||
| if (!result?.definitions?.length) { | ||
| return; | ||
| } | ||
| if (!root.sfc.template | ||
| || position < root.sfc.template.startTagEnd | ||
| || position > root.sfc.template.endTagStart) { | ||
| if (!root.ir.template | ||
| || position < root.ir.template.startTagEnd | ||
| || position > root.ir.template.endTagStart) { | ||
| return result; | ||
| } | ||
| const definitions = new Set(result.definitions); | ||
| const skippedDefinitions = []; | ||
| // #5275 | ||
| if (result.definitions.length >= 2) { | ||
| for (const definition of result.definitions) { | ||
| if (root.sfc.content[definition.textSpan.start - 1] === '@' | ||
| || root.sfc.content.slice(definition.textSpan.start - 5, definition.textSpan.start) === 'v-on:') { | ||
| if (root.ir.content[definition.textSpan.start - 1] === '@' | ||
| || root.ir.content.slice(definition.textSpan.start - 5, definition.textSpan.start) === 'v-on:') { | ||
| definitions.delete(definition); | ||
@@ -391,7 +391,15 @@ } | ||
| } | ||
| visit(sourceFile, definition, sourceFile); | ||
| const node = visit(sourceFile, definition); | ||
| if (!node) { | ||
| continue; | ||
| } | ||
| const position = node.getStart(sourceFile); | ||
| const res = getDefinitionAndBoundSpan(definition.fileName, position); | ||
| if (res?.definitions?.length) { | ||
| definitions.delete(definition); | ||
| for (const definition of res.definitions) { | ||
| definitions.add(definition); | ||
| } | ||
| } | ||
| } | ||
| for (const definition of skippedDefinitions) { | ||
| definitions.delete(definition); | ||
| } | ||
| return { | ||
@@ -401,38 +409,20 @@ definitions: [...definitions], | ||
| }; | ||
| function visit(node, definition, sourceFile) { | ||
| if (ts.isPropertySignature(node) && node.type) { | ||
| proxy(node.name, node.type, definition, sourceFile); | ||
| } | ||
| else if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.type && !node.initializer) { | ||
| proxy(node.name, node.type, definition, sourceFile); | ||
| } | ||
| else { | ||
| ts.forEachChild(node, child => visit(child, definition, sourceFile)); | ||
| } | ||
| } | ||
| function proxy(name, type, definition, sourceFile) { | ||
| const { textSpan, fileName } = definition; | ||
| const start = name.getStart(sourceFile); | ||
| const end = name.getEnd(); | ||
| if (start !== textSpan.start || end - start !== textSpan.length) { | ||
| return; | ||
| } | ||
| if (ts.isIndexedAccessTypeNode(type)) { | ||
| const pos = type.indexType.getStart(sourceFile); | ||
| const res = getDefinitionAndBoundSpan(fileName, pos, ...rests); | ||
| if (res?.definitions?.length) { | ||
| for (const definition of res.definitions) { | ||
| definitions.add(definition); | ||
| function visit(sourceFile, definition) { | ||
| for (const node of (0, utils_2.forEachTouchingNode)(ts, sourceFile, definition.textSpan.start)) { | ||
| if (ts.isPropertySignature(node) && node.type | ||
| || ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.type) { | ||
| if (definition.textSpan.start + definition.textSpan.length > node.name.end | ||
| || definition.textSpan.start < node.name.getStart(sourceFile)) { | ||
| continue; | ||
| } | ||
| skippedDefinitions.push(definition); | ||
| } | ||
| } | ||
| else if (ts.isImportTypeNode(type)) { | ||
| const pos = type.argument.getStart(sourceFile); | ||
| const res = getDefinitionAndBoundSpan(fileName, pos, ...rests); | ||
| if (res?.definitions?.length) { | ||
| for (const definition of res.definitions) { | ||
| definitions.add(definition); | ||
| let type = node.type; | ||
| while (ts.isTypeReferenceNode(type) && type.typeArguments?.length) { | ||
| type = type.typeArguments[0]; | ||
| } | ||
| skippedDefinitions.push(definition); | ||
| if (ts.isIndexedAccessTypeNode(type)) { | ||
| return type.indexType; | ||
| } | ||
| else if (ts.isImportTypeNode(type)) { | ||
| return type.qualifier ?? type.argument; | ||
| } | ||
| } | ||
@@ -453,4 +443,4 @@ } | ||
| const blocks = [ | ||
| root.sfc.template, | ||
| ...root.sfc.styles, | ||
| root.ir.template, | ||
| ...root.ir.styles, | ||
| ]; | ||
@@ -457,0 +447,0 @@ const ranges = blocks.filter(Boolean).map(block => [ |
@@ -6,8 +6,11 @@ "use strict"; | ||
| function collectExtractProps(ts, language, program, sourceScript, virtualCode, templateCodeRange, leadingOffset = 0) { | ||
| const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(virtualCode); | ||
| if (!serviceScript) { | ||
| return []; | ||
| } | ||
| const result = new Map(); | ||
| const sourceFile = program.getSourceFile(virtualCode.fileName); | ||
| const checker = program.getTypeChecker(); | ||
| const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(virtualCode); | ||
| const maps = serviceScript ? [...language.maps.forEach(serviceScript.code)].map(([, map]) => map) : []; | ||
| const { sfc } = virtualCode; | ||
| const map = language.maps.get(serviceScript.code, sourceScript); | ||
| const { ir } = virtualCode; | ||
| sourceFile.forEachChild(function visit(node) { | ||
@@ -19,26 +22,18 @@ if (ts.isPropertyAccessExpression(node) | ||
| const { name } = node; | ||
| for (const map of maps) { | ||
| let mapped = false; | ||
| for (const source of map.toSourceLocation(name.getEnd() - leadingOffset)) { | ||
| if (source[0] >= sfc.template.startTagEnd + templateCodeRange[0] | ||
| && source[0] <= sfc.template.startTagEnd + templateCodeRange[1] | ||
| && (0, language_core_1.isSemanticTokensEnabled)(source[1].data)) { | ||
| mapped = true; | ||
| if (!result.has(name.text)) { | ||
| const type = checker.getTypeAtLocation(node); | ||
| const typeString = checker.typeToString(type, node, ts.TypeFormatFlags.NoTruncation); | ||
| result.set(name.text, { | ||
| name: name.text, | ||
| type: typeString.includes('__VLS_') ? 'any' : typeString, | ||
| model: false, | ||
| }); | ||
| } | ||
| const isModel = ts.isPostfixUnaryExpression(node.parent) || ts.isBinaryExpression(node.parent); | ||
| if (isModel) { | ||
| result.get(name.text).model = true; | ||
| } | ||
| break; | ||
| for (const [offset] of map.toSourceLocation(name.getEnd() - leadingOffset, language_core_1.isSemanticTokensEnabled)) { | ||
| if (offset >= ir.template.startTagEnd + templateCodeRange[0] | ||
| && offset <= ir.template.startTagEnd + templateCodeRange[1]) { | ||
| if (!result.has(name.text)) { | ||
| const type = checker.getTypeAtLocation(node); | ||
| const typeString = checker.typeToString(type, node, ts.TypeFormatFlags.NoTruncation); | ||
| result.set(name.text, { | ||
| name: name.text, | ||
| type: typeString.includes('__VLS_') ? 'any' : typeString, | ||
| model: false, | ||
| }); | ||
| } | ||
| } | ||
| if (mapped) { | ||
| const isModel = ts.isPostfixUnaryExpression(node.parent) || ts.isBinaryExpression(node.parent); | ||
| if (isModel) { | ||
| result.get(name.text).model = true; | ||
| } | ||
| break; | ||
@@ -45,0 +40,0 @@ } |
| import { type VueVirtualCode } from '@vue/language-core'; | ||
| import type * as ts from 'typescript'; | ||
| export declare function getComponentNames(ts: typeof import('typescript'), program: ts.Program, { fileName, sfc }: VueVirtualCode): string[]; | ||
| export declare function getComponentNames(ts: typeof import('typescript'), program: ts.Program, virtualCode: VueVirtualCode): string[]; |
@@ -6,4 +6,4 @@ "use strict"; | ||
| const utils_1 = require("./utils"); | ||
| function getComponentNames(ts, program, { fileName, sfc }) { | ||
| const sourceFile = program.getSourceFile(fileName); | ||
| function getComponentNames(ts, program, virtualCode) { | ||
| const sourceFile = program.getSourceFile(virtualCode.fileName); | ||
| if (!sourceFile) { | ||
@@ -19,6 +19,6 @@ return []; | ||
| ?? []; | ||
| componentNames.push((0, utils_1.getSelfComponentName)(fileName)); | ||
| componentNames.push(...language_core_1.tsCodegen.get(sfc)?.getImportedComponents() ?? []); | ||
| componentNames.push((0, utils_1.getSelfComponentName)(virtualCode.fileName)); | ||
| componentNames.push(...language_core_1.tsCodegen.get(virtualCode.ir)?.getImportedComponents() ?? []); | ||
| return [...new Set(componentNames)]; | ||
| } | ||
| //# sourceMappingURL=getComponentNames.js.map |
@@ -7,3 +7,3 @@ "use strict"; | ||
| function getComponentSlots(ts, program, virtualCode) { | ||
| const codegen = language_core_1.tsCodegen.get(virtualCode.sfc); | ||
| const codegen = language_core_1.tsCodegen.get(virtualCode.ir); | ||
| if (!codegen) { | ||
@@ -10,0 +10,0 @@ return []; |
| import type * as ts from 'typescript'; | ||
| export declare function getElementAttrs(ts: typeof import('typescript'), program: ts.Program, fileName: string, tag: string): { | ||
| name: string; | ||
| type: string; | ||
| }[]; | ||
| import type { ComponentPropInfo } from './getComponentProps'; | ||
| export declare function getElementAttrs(ts: typeof import('typescript'), program: ts.Program, fileName: string, tag: string): ComponentPropInfo[]; |
@@ -20,7 +20,12 @@ "use strict"; | ||
| } | ||
| return checker.getTypeOfSymbol(elementType).getProperties().map(c => ({ | ||
| name: c.name, | ||
| type: checker.typeToString(checker.getTypeOfSymbolAtLocation(c, sourceFile), elements.node, ts.TypeFormatFlags.NoTruncation), | ||
| })); | ||
| return checker.getTypeOfSymbol(elementType).getProperties().map(prop => { | ||
| const info = { | ||
| name: prop.name, | ||
| }; | ||
| if ((0, utils_1.hasBooleanType)(ts, checker.getTypeOfSymbol(prop))) { | ||
| info.boolean = true; | ||
| } | ||
| return info; | ||
| }); | ||
| } | ||
| //# sourceMappingURL=getElementAttrs.js.map |
| import type * as ts from 'typescript'; | ||
| import type { VueCompletionData } from '../common.js'; | ||
| import type { VueCompletionData } from '../common'; | ||
| type Response<T> = T | null | undefined | Promise<T | null | undefined>; | ||
@@ -9,4 +9,5 @@ export interface Requests { | ||
| getComponentDirectives(fileName: string): Response<ReturnType<typeof import('./getComponentDirectives.js')['getComponentDirectives']>>; | ||
| getComponentMeta(fileName: string, tag: string): Response<ReturnType<typeof import('./getComponentMeta.js')['getComponentMeta']>>; | ||
| getComponentNames(fileName: string): Response<ReturnType<typeof import('./getComponentNames.js')['getComponentNames']>>; | ||
| getComponentMeta(fileName: string, tag: string): Response<ReturnType<typeof import('./getComponentMeta.js')['getComponentMeta']>>; | ||
| getComponentProps(fileName: string, position: number): Response<ReturnType<typeof import('./getComponentProps.js')['getComponentProps']>>; | ||
| getComponentSlots(fileName: string): Response<ReturnType<typeof import('./getComponentSlots.js')['getComponentSlots']>>; | ||
@@ -13,0 +14,0 @@ getElementAttrs(fileName: string, tag: string): Response<ReturnType<typeof import('./getElementAttrs.js')['getElementAttrs']>>; |
| import { type Language, type SourceScript, type VueVirtualCode } from '@vue/language-core'; | ||
| import type * as ts from 'typescript'; | ||
| export declare function isRefAtPosition(ts: typeof import('typescript'), language: Language, program: ts.Program, sourceScript: SourceScript, virtualCode: VueVirtualCode, position: number, leadingOffset?: number): boolean; | ||
| export declare function isRefAtPosition(ts: typeof import('typescript'), language: Language, program: ts.Program, sourceScript: SourceScript<string>, virtualCode: VueVirtualCode, position: number): boolean; |
@@ -5,4 +5,6 @@ "use strict"; | ||
| exports.isRefAtPosition = isRefAtPosition; | ||
| const transform_1 = require("@volar/typescript/lib/node/transform"); | ||
| const language_core_1 = require("@vue/language-core"); | ||
| function isRefAtPosition(ts, language, program, sourceScript, virtualCode, position, leadingOffset = 0) { | ||
| const utils_1 = require("./utils"); | ||
| function isRefAtPosition(ts, language, program, sourceScript, virtualCode, position) { | ||
| const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(virtualCode); | ||
@@ -12,16 +14,4 @@ if (!serviceScript) { | ||
| } | ||
| let mapped = false; | ||
| for (const [_sourceScript, map] of language.maps.forEach(serviceScript.code)) { | ||
| for (const [position2, mapping] of map.toGeneratedLocation(position)) { | ||
| if ((0, language_core_1.isCompletionEnabled)(mapping.data)) { | ||
| position = position2; | ||
| mapped = true; | ||
| break; | ||
| } | ||
| } | ||
| if (mapped) { | ||
| break; | ||
| } | ||
| } | ||
| if (!mapped) { | ||
| const position2 = (0, transform_1.toGeneratedOffset)(language, serviceScript, sourceScript, position, language_core_1.isCompletionEnabled); | ||
| if (!position2) { | ||
| return false; | ||
@@ -33,3 +23,9 @@ } | ||
| } | ||
| const node = findPositionIdentifier(sourceFile, sourceFile, position + leadingOffset); | ||
| let node; | ||
| for (const child of (0, utils_1.forEachTouchingNode)(ts, sourceFile, position2)) { | ||
| if (ts.isIdentifier(child)) { | ||
| node = child; | ||
| break; | ||
| } | ||
| } | ||
| if (!node) { | ||
@@ -45,17 +41,3 @@ return false; | ||
| && decl.name.expression.text === 'RefSymbol')); | ||
| function findPositionIdentifier(sourceFile, node, offset) { | ||
| let result; | ||
| node.forEachChild(child => { | ||
| if (!result) { | ||
| if (child.end === offset && ts.isIdentifier(child)) { | ||
| result = child; | ||
| } | ||
| else if (child.end >= offset && child.getStart(sourceFile) < offset) { | ||
| result = findPositionIdentifier(sourceFile, child, offset); | ||
| } | ||
| } | ||
| }); | ||
| return result; | ||
| } | ||
| } | ||
| //# sourceMappingURL=isRefAtPosition.js.map |
| import { type VueVirtualCode } from '@vue/language-core'; | ||
| import type * as ts from 'typescript'; | ||
| export declare function getComponentType(ts: typeof import('typescript'), checker: ts.TypeChecker, sourceFile: ts.SourceFile, { fileName, sfc }: VueVirtualCode, tag: string): { | ||
| export declare function getComponentType(ts: typeof import('typescript'), checker: ts.TypeChecker, sourceFile: ts.SourceFile, { fileName, ir }: VueVirtualCode, tag: string): { | ||
| node: ts.Node; | ||
@@ -12,1 +12,3 @@ type: ts.Type; | ||
| } | undefined; | ||
| export declare function hasBooleanType(ts: typeof import('typescript'), type: ts.Type): boolean; | ||
| export declare function forEachTouchingNode(ts: typeof import('typescript'), sourceFile: ts.SourceFile, position: number): Generator<ts.Node, void, any>; |
@@ -39,6 +39,8 @@ "use strict"; | ||
| exports.getVariableType = getVariableType; | ||
| exports.hasBooleanType = hasBooleanType; | ||
| exports.forEachTouchingNode = forEachTouchingNode; | ||
| const language_core_1 = require("@vue/language-core"); | ||
| const shared_1 = require("@vue/shared"); | ||
| const path = __importStar(require("path-browserify")); | ||
| function getComponentType(ts, checker, sourceFile, { fileName, sfc }, tag) { | ||
| function getComponentType(ts, checker, sourceFile, { fileName, ir }, tag) { | ||
| const testNames = new Set([ | ||
@@ -49,3 +51,3 @@ tag, | ||
| ]); | ||
| const codegen = language_core_1.tsCodegen.get(sfc); | ||
| const codegen = language_core_1.tsCodegen.get(ir); | ||
| for (const importedName of codegen?.getImportedComponents() ?? []) { | ||
@@ -141,2 +143,37 @@ if (testNames.has(importedName)) { | ||
| } | ||
| function hasBooleanType(ts, type) { | ||
| if (type.flags & ts.TypeFlags.BooleanLike) { | ||
| return true; | ||
| } | ||
| if (type.isUnionOrIntersection()) { | ||
| return type.types.some(type => hasBooleanType(ts, type)); | ||
| } | ||
| return false; | ||
| } | ||
| function* forEachTouchingNode(ts, sourceFile, position) { | ||
| yield* binaryVisit(ts, sourceFile, sourceFile, position); | ||
| } | ||
| function* binaryVisit(ts, sourceFile, node, position) { | ||
| const nodes = []; | ||
| ts.forEachChild(node, child => { | ||
| nodes.push(child); | ||
| }); | ||
| let left = 0; | ||
| let right = nodes.length - 1; | ||
| while (left <= right) { | ||
| const mid = Math.floor((left + right) / 2); | ||
| const node = nodes[mid]; | ||
| if (position > node.end) { | ||
| left = mid + 1; | ||
| } | ||
| else if (position < node.getStart(sourceFile)) { | ||
| right = mid - 1; | ||
| } | ||
| else { | ||
| yield node; | ||
| yield* binaryVisit(ts, sourceFile, node, position); | ||
| return; | ||
| } | ||
| } | ||
| } | ||
| //# sourceMappingURL=utils.js.map |
+6
-5
| { | ||
| "name": "@vue/typescript-plugin", | ||
| "version": "3.2.9", | ||
| "version": "3.3.0", | ||
| "license": "MIT", | ||
@@ -19,12 +19,13 @@ "files": [ | ||
| "@volar/typescript": "2.4.28", | ||
| "@vue/language-core": "3.2.9", | ||
| "@vue/language-core": "3.3.0", | ||
| "@vue/shared": "^3.5.0", | ||
| "path-browserify": "^1.0.1", | ||
| "vue-component-meta": "3.2.9" | ||
| "vue-component-meta": "3.3.0" | ||
| }, | ||
| "devDependencies": { | ||
| "@types/node": "^24.1.0", | ||
| "@types/path-browserify": "^1.0.3" | ||
| "@types/path-browserify": "^1.0.3", | ||
| "@vue/compiler-dom": "^3.5.0" | ||
| }, | ||
| "gitHead": "9c1fd47ffe25e86394232dfc76453a5f76cb4fe0" | ||
| "gitHead": "1088dce8ae6b937f7525fae4982e3b3ea99d3c64" | ||
| } |
+2
-1
@@ -54,4 +54,5 @@ # @vue/typescript-plugin | ||
| | `_vue:getComponentDirectives` | Get component directives | | ||
| | `_vue:getComponentMeta` | Get component metadata | | ||
| | `_vue:getComponentNames` | Get component name list | | ||
| | `_vue:getComponentMeta` | Get component metadata | | ||
| | `_vue:getComponentProps` | Get component props | | ||
| | `_vue:getComponentSlots` | Get component slots | | ||
@@ -58,0 +59,0 @@ | `_vue:getElementAttrs` | Get element attributes | |
73120
5.91%33
6.45%1397
6.64%83
1.22%3
50%+ Added
+ Added
- Removed
- Removed
Updated
Updated