@vue/typescript-plugin
Advanced tools
Comparing version 2.0.19 to 2.0.20
@@ -1,3 +0,2 @@ | ||
import type * as ts from 'typescript'; | ||
declare const _default: ts.server.PluginModuleFactory; | ||
export = _default; | ||
declare const plugin: import("typescript").server.PluginModuleFactory; | ||
export = plugin; |
124
index.js
"use strict"; | ||
const decorateLanguageService_1 = require("@volar/typescript/lib/node/decorateLanguageService"); | ||
const decorateLanguageServiceHost_1 = require("@volar/typescript/lib/node/decorateLanguageServiceHost"); | ||
const createLanguageServicePlugin_1 = require("@volar/typescript/lib/quickstart/createLanguageServicePlugin"); | ||
const vue = require("@vue/language-core"); | ||
const language_core_1 = require("@vue/language-core"); | ||
const common_1 = require("./lib/common"); | ||
const server_1 = require("./lib/server"); | ||
const windowsPathReg = /\\/g; | ||
const externalFiles = new WeakMap(); | ||
const projectExternalFileExtensions = new WeakMap(); | ||
const decoratedLanguageServices = new WeakSet(); | ||
const decoratedLanguageServiceHosts = new WeakSet(); | ||
function createLanguageServicePlugin() { | ||
return modules => { | ||
const { typescript: ts } = modules; | ||
const pluginModule = { | ||
create(info) { | ||
if (!decoratedLanguageServices.has(info.languageService) | ||
&& !decoratedLanguageServiceHosts.has(info.languageServiceHost)) { | ||
decoratedLanguageServices.add(info.languageService); | ||
decoratedLanguageServiceHosts.add(info.languageServiceHost); | ||
const vueOptions = getVueCompilerOptions(); | ||
const languagePlugin = vue.createVueLanguagePlugin(ts, id => id, info.languageServiceHost.useCaseSensitiveFileNames?.() ?? false, () => info.languageServiceHost.getProjectVersion?.() ?? '', () => externalFiles.get(info.project) ?? [], info.languageServiceHost.getCompilationSettings(), vueOptions); | ||
const extensions = languagePlugin.typescript?.extraFileExtensions.map(ext => '.' + ext.extension) ?? []; | ||
const getScriptSnapshot = info.languageServiceHost.getScriptSnapshot.bind(info.languageServiceHost); | ||
const getScriptVersion = info.languageServiceHost.getScriptVersion.bind(info.languageServiceHost); | ||
const syncedScriptVersions = new vue.FileMap(ts.sys.useCaseSensitiveFileNames); | ||
const language = (0, language_core_1.createLanguage)([languagePlugin], ts.sys.useCaseSensitiveFileNames, fileName => { | ||
const version = getScriptVersion(fileName); | ||
if (syncedScriptVersions.get(fileName) === version) { | ||
return; | ||
} | ||
syncedScriptVersions.set(fileName, version); | ||
const snapshot = getScriptSnapshot(fileName); | ||
if (snapshot) { | ||
language.scripts.set(fileName, snapshot); | ||
} | ||
else { | ||
language.scripts.delete(fileName); | ||
} | ||
}); | ||
projectExternalFileExtensions.set(info.project, extensions); | ||
server_1.projects.set(info.project, { info, language, vueOptions }); | ||
(0, decorateLanguageService_1.decorateLanguageService)(language, info.languageService); | ||
(0, common_1.decorateLanguageServiceForVue)(language, info.languageService, vueOptions, ts, true, fileName => fileName); | ||
(0, decorateLanguageServiceHost_1.decorateLanguageServiceHost)(ts, language, info.languageServiceHost); | ||
(0, server_1.startNamedPipeServer)(ts, info.project.projectKind, info.project.getCurrentDirectory()); | ||
// #3963 | ||
const timer = setInterval(() => { | ||
if (info.project['program']) { | ||
clearInterval(timer); | ||
info.project['program'].__vue__ = { language }; | ||
} | ||
}, 50); | ||
const plugin = (0, createLanguageServicePlugin_1.createLanguageServicePlugin)((ts, info) => { | ||
const vueOptions = getVueCompilerOptions(); | ||
const languagePlugin = vue.createVueLanguagePlugin(ts, id => id, () => info.languageServiceHost.getProjectVersion?.() ?? '', info.project.projectKind === ts.server.ProjectKind.Inferred | ||
? () => true | ||
: fileName => { | ||
const fileMap = new vue.FileMap(info.languageServiceHost.useCaseSensitiveFileNames?.() ?? false); | ||
for (const vueFileName of createLanguageServicePlugin_1.externalFiles.get(info.project) ?? []) { | ||
fileMap.set(vueFileName, undefined); | ||
} | ||
return fileMap.has(fileName); | ||
}, info.languageServiceHost.getCompilationSettings(), vueOptions); | ||
return { | ||
languagePlugins: [languagePlugin], | ||
setup: language => { | ||
server_1.projects.set(info.project, { info, language, vueOptions }); | ||
(0, common_1.decorateLanguageServiceForVue)(language, info.languageService, vueOptions, ts, true, fileName => fileName); | ||
(0, server_1.startNamedPipeServer)(ts, info.project.projectKind, info.project.getCurrentDirectory()); | ||
// #3963 | ||
const timer = setInterval(() => { | ||
if (info.project['program']) { | ||
clearInterval(timer); | ||
info.project['program'].__vue__ = { language }; | ||
} | ||
return info.languageService; | ||
function getVueCompilerOptions() { | ||
if (info.project.projectKind === ts.server.ProjectKind.Configured) { | ||
const tsconfig = info.project.getProjectName(); | ||
return vue.createParsedCommandLine(ts, ts.sys, tsconfig.replace(windowsPathReg, '/')).vueOptions; | ||
} | ||
else { | ||
return vue.createParsedCommandLineByJson(ts, ts.sys, info.languageServiceHost.getCurrentDirectory(), {}).vueOptions; | ||
} | ||
} | ||
}, | ||
getExternalFiles(project, updateLevel = 0) { | ||
if (updateLevel >= (1) | ||
|| !externalFiles.has(project)) { | ||
const oldFiles = externalFiles.get(project); | ||
const newFiles = new Set((0, decorateLanguageServiceHost_1.searchExternalFiles)(ts, project, projectExternalFileExtensions.get(project))); | ||
externalFiles.set(project, newFiles); | ||
if (oldFiles && !twoSetsEqual(oldFiles, newFiles)) { | ||
for (const oldFile of oldFiles) { | ||
if (!newFiles.has(oldFile)) { | ||
server_1.projects.get(project)?.language.scripts.delete(oldFile); | ||
} | ||
} | ||
project.refreshDiagnostics(); | ||
} | ||
} | ||
return [...externalFiles.get(project)]; | ||
}, | ||
}; | ||
return pluginModule; | ||
}, 50); | ||
} | ||
}; | ||
} | ||
function twoSetsEqual(a, b) { | ||
if (a.size !== b.size) { | ||
return false; | ||
} | ||
for (const file of a) { | ||
if (!b.has(file)) { | ||
return false; | ||
function getVueCompilerOptions() { | ||
if (info.project.projectKind === ts.server.ProjectKind.Configured) { | ||
const tsconfig = info.project.getProjectName(); | ||
return vue.createParsedCommandLine(ts, ts.sys, tsconfig.replace(windowsPathReg, '/')).vueOptions; | ||
} | ||
else { | ||
return vue.createParsedCommandLineByJson(ts, ts.sys, info.languageServiceHost.getCurrentDirectory(), {}).vueOptions; | ||
} | ||
} | ||
return true; | ||
} | ||
module.exports = createLanguageServicePlugin(); | ||
}); | ||
module.exports = plugin; | ||
//# sourceMappingURL=index.js.map |
import * as vue from '@vue/language-core'; | ||
import type * as ts from 'typescript'; | ||
export declare function decorateLanguageServiceForVue(language: vue.Language, languageService: ts.LanguageService, vueOptions: vue.VueCompilerOptions, ts: typeof import('typescript'), isTsPlugin: boolean, getScriptId: (fileName: string) => string): void; | ||
export declare function getComponentSpans(this: { | ||
typescript: typeof import('typescript'); | ||
languageService: ts.LanguageService; | ||
}, vueCode: vue.VueVirtualCode, template: NonNullable<vue.VueVirtualCode['sfc']['template']>, spanTemplateRange: ts.TextSpan): ts.TextSpan[]; | ||
import type { RequestContext } from './requests/types'; | ||
export declare function decorateLanguageServiceForVue<T>(language: vue.Language<T>, languageService: ts.LanguageService, vueOptions: vue.VueCompilerOptions, ts: typeof import('typescript'), isTsPlugin: boolean, getScriptId: (fileName: string) => T): void; | ||
export declare function getComponentSpans(this: Pick<RequestContext, 'typescript' | 'languageService'>, vueCode: vue.VueVirtualCode, template: NonNullable<vue.VueVirtualCode['sfc']['template']>, spanTemplateRange: ts.TextSpan): ts.TextSpan[]; |
@@ -137,7 +137,8 @@ "use strict"; | ||
if (template) { | ||
for (const componentSpan of getComponentSpans.call({ typescript: ts, languageService, vueOptions }, file.generated.root, template, { | ||
for (const componentSpan of getComponentSpans.call({ typescript: ts, languageService }, file.generated.root, template, { | ||
start: span.start - template.startTagEnd, | ||
length: span.length, | ||
})) { | ||
result.spans.push(componentSpan.start + template.startTagEnd, componentSpan.length, 256); | ||
result.spans.push(componentSpan.start + template.startTagEnd, componentSpan.length, 256 // class | ||
); | ||
} | ||
@@ -144,0 +145,0 @@ } |
@@ -19,3 +19,3 @@ "use strict"; | ||
const script = volarFile.generated?.languagePlugin.typescript?.getServiceScript(volarFile.generated.root); | ||
const maps = script ? [...language.maps.forEach(script.code).values()] : []; | ||
const maps = script ? [...language.maps.forEach(script.code)].map(([_1, _2, map]) => map) : []; | ||
const sfc = volarFile.generated.root.sfc; | ||
@@ -28,21 +28,26 @@ sourceFile.forEachChild(function visit(node) { | ||
const { name } = node; | ||
for (const [_, map] of maps) { | ||
const source = map.getSourceOffset(name.getEnd() - (isTsPlugin ? volarFile.snapshot.getLength() : 0)); | ||
if (source | ||
&& source[0] >= sfc.template.startTagEnd + templateCodeRange[0] | ||
&& source[0] <= sfc.template.startTagEnd + templateCodeRange[1] | ||
&& (0, language_core_1.isSemanticTokensEnabled)(source[1].data)) { | ||
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, | ||
}); | ||
for (const map of maps) { | ||
let mapped = false; | ||
for (const source of map.getSourceOffsets(name.getEnd() - (isTsPlugin ? volarFile.snapshot.getLength() : 0))) { | ||
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; | ||
} | ||
const isModel = ts.isPostfixUnaryExpression(node.parent) || ts.isBinaryExpression(node.parent); | ||
if (isModel) { | ||
result.get(name.text).model = true; | ||
} | ||
} | ||
if (mapped) { | ||
break; | ||
@@ -49,0 +54,0 @@ } |
@@ -5,26 +5,6 @@ import * as vue from '@vue/language-core'; | ||
export declare function getComponentProps(this: RequestContext, fileName: string, tag: string, requiredOnly?: boolean): string[] | undefined; | ||
export declare function getComponentEvents(this: { | ||
typescript: typeof import('typescript'); | ||
languageService: ts.LanguageService; | ||
language: vue.Language; | ||
getFileId: (fileName: string) => string; | ||
}, fileName: string, tag: string): string[] | undefined; | ||
export declare function getTemplateContextProps(this: { | ||
typescript: typeof import('typescript'); | ||
languageService: ts.LanguageService; | ||
language: vue.Language; | ||
getFileId: (fileName: string) => string; | ||
}, fileName: string): string[] | undefined; | ||
export declare function getComponentNames(this: { | ||
typescript: typeof import('typescript'); | ||
languageService: ts.LanguageService; | ||
language: vue.Language; | ||
getFileId: (fileName: string) => string; | ||
}, fileName: string): string[] | undefined; | ||
export declare function getComponentEvents(this: RequestContext, fileName: string, tag: string): string[] | undefined; | ||
export declare function getTemplateContextProps(this: RequestContext, fileName: string): string[] | undefined; | ||
export declare function getComponentNames(this: RequestContext, fileName: string): string[] | undefined; | ||
export declare function _getComponentNames(ts: typeof import('typescript'), tsLs: ts.LanguageService, vueCode: vue.VueVirtualCode): string[]; | ||
export declare function getElementAttrs(this: { | ||
typescript: typeof import('typescript'); | ||
languageService: ts.LanguageService; | ||
language: vue.Language; | ||
getFileId: (fileName: string) => string; | ||
}, fileName: string, tagName: string): string[] | undefined; | ||
export declare function getElementAttrs(this: RequestContext, fileName: string, tagName: string): string[] | undefined; |
@@ -15,3 +15,3 @@ "use strict"; | ||
let mapped = false; | ||
for (const [_1, [_2, map]] of language.maps.forEach(virtualScript.code)) { | ||
for (const [_1, _2, map] of language.maps.forEach(virtualScript.code)) { | ||
for (const [position2, mapping] of map.getGeneratedOffsets(position)) { | ||
@@ -18,0 +18,0 @@ if ((0, language_core_1.isCompletionEnabled)(mapping.data)) { |
import type { Language } from '@vue/language-core'; | ||
import type * as ts from 'typescript'; | ||
export interface RequestContext { | ||
export interface RequestContext<T = any> { | ||
typescript: typeof import('typescript'); | ||
languageService: ts.LanguageService; | ||
languageServiceHost: ts.LanguageServiceHost; | ||
language: Language; | ||
language: Language<T>; | ||
isTsPlugin: boolean; | ||
getFileId: (fileName: string) => string; | ||
getFileId: (fileName: string) => T; | ||
} |
@@ -10,4 +10,4 @@ import type { Language, VueCompilerOptions } from '@vue/language-core'; | ||
info: ts.server.PluginCreateInfo; | ||
language: Language; | ||
language: Language<string>; | ||
vueOptions: VueCompilerOptions; | ||
}>; |
@@ -5,2 +5,3 @@ /// <reference types="node" /> | ||
import type { Request } from './server'; | ||
export { TypeScriptProjectHost } from '@volar/typescript'; | ||
export interface NamedPipeServer { | ||
@@ -7,0 +8,0 @@ path: string; |
@@ -8,2 +8,3 @@ "use strict"; | ||
const fs = require("fs"); | ||
var typescript_1 = require("@volar/typescript"); | ||
const { version } = require('../package.json'); | ||
@@ -10,0 +11,0 @@ const pipeTableFile = path.join(os.tmpdir(), `vue-tsp-table-${version}.json`); |
{ | ||
"name": "@vue/typescript-plugin", | ||
"version": "2.0.19", | ||
"version": "2.0.20", | ||
"license": "MIT", | ||
@@ -15,4 +15,4 @@ "files": [ | ||
"dependencies": { | ||
"@volar/typescript": "~2.2.4", | ||
"@vue/language-core": "2.0.19", | ||
"@volar/typescript": "~2.3.0-alpha.14", | ||
"@vue/language-core": "2.0.20", | ||
"@vue/shared": "^3.4.0" | ||
@@ -23,3 +23,3 @@ }, | ||
}, | ||
"gitHead": "a9fae154ad1efc4359866cfd10251d53e4b0faed" | ||
"gitHead": "e1a5d2f136bf60a772c9655f9f5474c7f71a2ff9" | ||
} |
48985
1042
+ Added@volar/language-core@2.3.4(transitive)
+ Added@volar/source-map@2.3.4(transitive)
+ Added@volar/typescript@2.3.4(transitive)
+ Added@vue/language-core@2.0.20(transitive)
+ Addedvscode-uri@3.0.8(transitive)
- Removed@volar/language-core@2.2.5(transitive)
- Removed@volar/source-map@2.2.5(transitive)
- Removed@volar/typescript@2.2.5(transitive)
- Removed@vue/language-core@2.0.19(transitive)
- Removedmuggle-string@0.4.1(transitive)
Updated@vue/language-core@2.0.20