Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 60 additions & 17 deletions extensions/vscode/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import * as interpolationDecorators from './lib/interpolationDecorators';
import * as reactivityVisualization from './lib/reactivityVisualization';
import * as welcome from './lib/welcome';

let client: lsp.BaseLanguageClient | undefined;
let needRestart = false;
const serverPath = resolveServerPath();
const neededRestart = !patchTypeScriptExtension();

for (
const incompatibleExtensionId of [
Expand All @@ -44,6 +44,8 @@ for (
}

export = defineExtension(() => {
let client: lsp.BaseLanguageClient | undefined;

const context = extensionContext.value!;
const volarLabs = createLabsInfo();
const activeTextEditor = useActiveTextEditor();
Expand All @@ -59,7 +61,7 @@ export = defineExtension(() => {

nextTick(() => stop());

if (needRestart) {
if (neededRestart) {
vscode.window.showInformationMessage(
'Please restart the extension host to activate Vue support.',
'Restart Extension Host',
Expand All @@ -75,9 +77,12 @@ export = defineExtension(() => {
return;
}

watch(() => config.server.includeLanguages, async () => {
watch(() => [
config.server.path,
config.server.includeLanguages,
], async () => {
const reload = await vscode.window.showInformationMessage(
'Please restart extension host to apply the new language settings.',
'Please restart extension host to apply the new server settings.',
'Restart Extension Host',
);
if (reload) {
Expand All @@ -95,7 +100,14 @@ export = defineExtension(() => {
);
}

volarLabs.addLanguageClient(client = launch(context));
if (config.server.path && !serverPath) {
vscode.window.showErrorMessage('Cannot find @vue/language-server.');
return;
}

client = launch(serverPath ?? vscode.Uri.joinPath(context.extensionUri, 'dist', 'language-server.js').fsPath);

volarLabs.addLanguageClient(client);

const selectors = config.server.includeLanguages;

Expand Down Expand Up @@ -123,19 +135,18 @@ export = defineExtension(() => {
return volarLabs.extensionExports;
});

function launch(context: vscode.ExtensionContext) {
const serverModule = vscode.Uri.joinPath(context.extensionUri, 'dist', 'language-server.js');
function launch(serverPath: string) {
const client = new lsp.LanguageClient(
'vue',
'Vue',
{
run: {
module: serverModule.fsPath,
module: serverPath,
transport: lsp.TransportKind.ipc,
options: {},
},
debug: {
module: serverModule.fsPath,
module: serverPath,
transport: lsp.TransportKind.ipc,
options: { execArgv: ['--nolazy', '--inspect=' + 6009] },
},
Expand Down Expand Up @@ -179,21 +190,52 @@ function launch(context: vscode.ExtensionContext) {
return client;
}

const tsExtension = vscode.extensions.getExtension('vscode.typescript-language-features')!;
if (tsExtension.isActive) {
needRestart = true;
function resolveServerPath() {
const tsPluginPackPath = path.join(__dirname, '..', 'node_modules', 'vue-typescript-plugin-pack', 'index.js');

if (!config.server.path) {
fs.writeFileSync(tsPluginPackPath, `module.exports = require("../../dist/typescript-plugin.js");`);
return;
}

if (path.isAbsolute(config.server.path)) {
const entryFile = require.resolve('./index.js', { paths: [config.server.path] });
const tsPluginPath = require.resolve('@vue/typescript-plugin', { paths: [path.dirname(entryFile)] });
fs.writeFileSync(tsPluginPackPath, `module.exports = require("${tsPluginPath}");`);
return entryFile;
}

for (const { uri } of vscode.workspace.workspaceFolders ?? []) {
if (uri.scheme !== 'file') {
continue;
}
try {
const serverPath = path.join(uri.fsPath, config.server.path);
const entryFile = require.resolve('./index.js', { paths: [serverPath] });
const tsPluginPath = require.resolve('@vue/typescript-plugin', { paths: [path.dirname(entryFile)] });
fs.writeFileSync(tsPluginPackPath, `module.exports = require("${tsPluginPath}");`);
return entryFile;
}
catch {}
}
}
else {

function patchTypeScriptExtension() {
const tsExtension = vscode.extensions.getExtension('vscode.typescript-language-features')!;
if (tsExtension.isActive) {
return false;
}

const fs = require('node:fs');
const readFileSync = fs.readFileSync;
const extensionJsPath = require.resolve('./dist/extension.js', { paths: [tsExtension.extensionPath] });
const { publisher, name } = require('./package.json');
const vueExtension = vscode.extensions.getExtension(`${publisher}.${name}`)!;
const vuePluginName = 'vue-typescript-plugin-pack';
const tsPluginName = 'vue-typescript-plugin-pack';

vueExtension.packageJSON.contributes.typescriptServerPlugins = [
{
name: vuePluginName,
name: tsPluginName,
enableForWorkspaceTypeScriptVersions: true,
configNamespace: 'typescript',
languages: config.server.includeLanguages,
Expand All @@ -218,7 +260,7 @@ else {
// sort plugins for johnsoncodehk.tsslint, zardoy.ts-essential-plugins
text = text.replace(
'"--globalPlugins",i.plugins',
s => s + `.sort((a,b)=>(b.name==="${vuePluginName}"?-1:0)-(a.name==="${vuePluginName}"?-1:0))`,
s => s + `.sort((a,b)=>(b.name==="${tsPluginName}"?-1:0)-(a.name==="${tsPluginName}"?-1:0))`,
);

return text;
Expand All @@ -232,4 +274,5 @@ else {
const patchedModule = require(extensionJsPath);
Object.assign(loadedModule.exports, patchedModule);
}
return true;
}
25 changes: 21 additions & 4 deletions extensions/vscode/lib/generated-meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// Meta info
export const publisher = 'Vue';
export const name = 'volar';
export const version = '3.0.6';
export const version = '3.0.7';
export const displayName = 'Vue (Official)';
export const description = 'Language Support for Vue';
export const extensionId = `${publisher}.${name}`;
Expand Down Expand Up @@ -40,6 +40,7 @@ export type ConfigKey =
| 'vue.editor.focusMode'
| 'vue.editor.reactivityVisualization'
| 'vue.editor.templateInterpolationDecorators'
| 'vue.server.path'
| 'vue.server.includeLanguages'
| 'vue.codeActions.askNewComponentName'
| 'vue.suggest.componentNameCasing'
Expand All @@ -62,6 +63,7 @@ export interface ConfigKeyTypeMap {
'vue.editor.focusMode': boolean;
'vue.editor.reactivityVisualization': boolean;
'vue.editor.templateInterpolationDecorators': boolean;
'vue.server.path': string | undefined;
'vue.server.includeLanguages': string[];
'vue.codeActions.askNewComponentName': boolean;
'vue.suggest.componentNameCasing': 'preferKebabCase' | 'preferPascalCase' | 'alwaysKebabCase' | 'alwaysPascalCase';
Expand Down Expand Up @@ -92,6 +94,7 @@ export interface ConfigShorthandMap {
editorFocusMode: 'vue.editor.focusMode';
editorReactivityVisualization: 'vue.editor.reactivityVisualization';
editorTemplateInterpolationDecorators: 'vue.editor.templateInterpolationDecorators';
serverPath: 'vue.server.path';
serverIncludeLanguages: 'vue.server.includeLanguages';
codeActionsAskNewComponentName: 'vue.codeActions.askNewComponentName';
suggestComponentNameCasing: 'vue.suggest.componentNameCasing';
Expand All @@ -115,6 +118,7 @@ export interface ConfigShorthandTypeMap {
editorFocusMode: boolean;
editorReactivityVisualization: boolean;
editorTemplateInterpolationDecorators: boolean;
serverPath: string | undefined;
serverIncludeLanguages: string[];
codeActionsAskNewComponentName: boolean;
suggestComponentNameCasing: 'preferKebabCase' | 'preferPascalCase' | 'alwaysKebabCase' | 'alwaysPascalCase';
Expand Down Expand Up @@ -160,12 +164,12 @@ export const configs = {
} as ConfigItem<'vue.trace.server'>,
/**
* @key `vue.editor.focusMode`
* @default `true`
* @default `false`
* @type `boolean`
*/
editorFocusMode: {
key: 'vue.editor.focusMode',
default: true,
default: false,
} as ConfigItem<'vue.editor.focusMode'>,
/**
* @key `vue.editor.reactivityVisualization`
Expand All @@ -185,6 +189,15 @@ export const configs = {
key: 'vue.editor.templateInterpolationDecorators',
default: true,
} as ConfigItem<'vue.editor.templateInterpolationDecorators'>,
/**
* @key `vue.server.path`
* @default `undefined`
* @type `string`
*/
serverPath: {
key: 'vue.server.path',
default: undefined,
} as ConfigItem<'vue.server.path'>,
/**
* @key `vue.server.includeLanguages`
* @default `["vue"]`
Expand Down Expand Up @@ -336,6 +349,7 @@ export interface ScopedConfigKeyTypeMap {
'editor.focusMode': boolean;
'editor.reactivityVisualization': boolean;
'editor.templateInterpolationDecorators': boolean;
'server.path': string | undefined;
'server.includeLanguages': string[];
'codeActions.askNewComponentName': boolean;
'suggest.componentNameCasing': 'preferKebabCase' | 'preferPascalCase' | 'alwaysKebabCase' | 'alwaysPascalCase';
Expand Down Expand Up @@ -365,9 +379,10 @@ export const scopedConfigs = {
scope: 'vue',
defaults: {
'trace.server': 'off',
'editor.focusMode': true,
'editor.focusMode': false,
'editor.reactivityVisualization': true,
'editor.templateInterpolationDecorators': true,
'server.path': undefined,
'server.includeLanguages': ['vue'],
'codeActions.askNewComponentName': true,
'suggest.componentNameCasing': 'preferPascalCase',
Expand Down Expand Up @@ -398,6 +413,7 @@ export interface NestedConfigs {
'templateInterpolationDecorators': boolean;
};
'server': {
'path': string | undefined;
'includeLanguages': string[];
};
'codeActions': {
Expand Down Expand Up @@ -451,6 +467,7 @@ export interface NestedScopedConfigs {
'templateInterpolationDecorators': boolean;
};
'server': {
'path': string | undefined;
'includeLanguages': string[];
};
'codeActions': {
Expand Down
4 changes: 4 additions & 0 deletions extensions/vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,10 @@
"default": true,
"markdownDescription": "%configuration.editor.templateInterpolationDecorators%"
},
"vue.server.path": {
"type": "string",
"markdownDescription": "%configuration.server.path%"
},
"vue.server.includeLanguages": {
"type": "array",
"items": {
Expand Down
1 change: 1 addition & 0 deletions extensions/vscode/package.nls.ja.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"configuration.trace.server": "VS Code と Vue 言語サーバー間の通信をトレースします。",
"configuration.server.path": "`@vue/language-server` モジュールへのパス。設定しない場合、拡張機能にバンドルされたサーバーが読み込まれます。",
"configuration.server.includeLanguages": "拡張機能を有効にする言語を指定します。",
"configuration.codeActions.askNewComponentName": "コンポーネントを抽出する時に新しいコンポーネント名を尋ねます。",
"configuration.suggest.componentNameCasing": "コンポーネント名の命名規則。",
Expand Down
1 change: 1 addition & 0 deletions extensions/vscode/package.nls.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"configuration.trace.server": "Traces the communication between VS Code and the language server.",
"configuration.server.path": "Path to the `@vue/language-server` module. If not set, the server will be loaded from the extension's bundled.",
"configuration.server.includeLanguages": "Configure the languages for which the extension should be activated.",
"configuration.codeActions.askNewComponentName": "Ask for new component name when extract component.",
"configuration.suggest.componentNameCasing": "Preferred component name case.",
Expand Down
1 change: 1 addition & 0 deletions extensions/vscode/package.nls.ru.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"configuration.trace.server": "Отслеживать коммуникацию между VS Code и языковым сервером Vue.",
"configuration.server.path": "Путь к модулю `@vue/language-server`. Если не установлен, сервер будет загружен из пакета расширения.",
"configuration.server.includeLanguages": "Языки, для которых будет включено расширение.",
"configuration.codeActions.askNewComponentName": "Запрашивать новое имя компонента при извлечении компонента.",
"configuration.suggest.componentNameCasing": "Предпочитаемый формат имени компонента.",
Expand Down
1 change: 1 addition & 0 deletions extensions/vscode/package.nls.zh-CN.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"configuration.trace.server": "跟踪 VS Code 和 Vue 语言服务器之间的通信。",
"configuration.server.path": "`@vue/language-server` 模块的路径。如果未设置,服务器将从扩展的捆绑包中加载。",
"configuration.server.includeLanguages": "配置扩展需要激活的语言类型。",
"configuration.codeActions.askNewComponentName": "提取组件时询问新组件名称。",
"configuration.suggest.componentNameCasing": "首选组件命名格式。",
Expand Down
1 change: 1 addition & 0 deletions extensions/vscode/package.nls.zh-TW.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"configuration.trace.server": "追蹤 VS Code 和 Vue 語言伺服器之間的通訊。",
"configuration.server.path": "`@vue/language-server` 模組的路徑。如果未設定,伺服器將從擴充功能的捆綁包中載入。",
"configuration.server.includeLanguages": "配置擴充功能應該啟動的語言類型。",
"configuration.codeActions.askNewComponentName": "提取元件時詢問新元件名稱。",
"configuration.suggest.componentNameCasing": "首選元件名稱格式。",
Expand Down
Loading