Giter Club home page Giter Club logo

volar.js's Issues

[Language Server] Performance pitfalls of recursively searching for tsconfig.json

In the following line, the language server attempts to search for all tsconfigs from the workspace root directory. If the user attempts to start vscode from the system root directory and opens a vue file, this could lead to performance issues for the language server searching through the entire file system for tsconfigs.

const rootTsConfigs = new Set(sys?.readDirectory(uriToFileName(context.rootUri.toString()), rootTsConfigNames, undefined, ['**/*']).map(fileName => fileName.replace(/\\/g, '/') as path.PosixPath));

A better approach would be to attempt to search up for the tsconfig for each request.

Allow the TypeScript plugin to be configured via editor settings

Based on the VSCode documentation on contributes.typescriptServerPlugins, it’s possible to send configuration via an extension.

We could use this to provide a uniform interface to configure Volar based TypeScript plugins through either tsconfig.json or VSCode settings.

The following VSCode extension:

import { activateTsPlugin } from '@volar/vscode'

export async function activate(context) {
  await activateTsPlugin(
    '@mdx-js/typescript-plugin',
    context,
    'mdx',
    'config'
  )
}

configures the TypeScript plugin using the following VSCode settings:

{
  "mdx.config": {
    "plugins": []
  }
}

The TypeScript plugin would look something like this:

module.exports = createAsyncTSServerPlugin(
  ['.mdx'],
  2,
  // This tells Volar at which `tsconfig.json` key to look.
  'mdx',
  async (ts, info, options) => {
    // The options are available here somehow.
  }
)

This would be equivalen to having the following tsconfig.json:

{
  "compilerOptions": {/* … */},
  "mdx": {}
}

Related:

Wrong initial formatting with simultaneous <script> and <script setup>

I often use <script> together with <script setup> in SFC to cache some data across components.
Unfortunately it seems Volar wrongly formats this combination initially.
When I format manually, close and open the file, everything works fine afterwards, but that's annonying:

volar-wrong-formatting

Tried the pre-release version - the same problem:

Vue Language Features (Volar)
v1.8.23

Visual Studio Code
Version: 1.84.1
Commit: 2b35e1e6d88f1ce073683991d1eff5284a32690f
Date: 2023-11-06T12:35:59.022Z (23 hrs ago)
Browser: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Code/1.84.1 Chrome/114.0.5735.289 Electron/25.9.2 Safari/537.36

EACCESS crashes the server

I was instructed to file this upstream from vuejs/language-tools#3511

My project directory contains a directory which is not readable (owned by a different user). The existence of this directory crashes the server.

Steps to reproduce

  • Install VS Cod(e|ium).
  • Install the Vue.volar plugin.
  • Open a Vue project
  • sudo mkdir problem

Expected behavior

The plugin ignores this error, perhaps emitting a warning, and continues to start. Alternatively, the plugin is configurable in some way to ignore certain files or directories within a project directory.

Error Logs

node:fs:1442
  handleErrorFromBinding(ctx);
  ^

Error: EACCES: permission denied, scandir '/home/scott/src/kalkutago/db.mount'
    at Object.readdirSync (node:fs:1442:3)
    at t.readdirSync (node:electron/js2c/asar_bundle:2:10837)
    at Object.readDirectory (/nix/store/nrwr1bw6hdg4k34can4y4qig73x9fi98-vscode-extension-Vue-volar-1.7.11/share/vscode/extensions/Vue.volar/dist/server.js:77:33947)
    at Object.readDirectory (/nix/store/nrwr1bw6hdg4k34can4y4qig73x9fi98-vscode-extension-Vue-volar-1.7.11/share/vscode/extensions/Vue.volar/dist/server.js:77:30107)
    at b (/nix/store/nrwr1bw6hdg4k34can4y4qig73x9fi98-vscode-extension-Vue-volar-1.7.11/share/vscode/extensions/Vue.volar/dist/server.js:77:3184)
    at /nix/store/nrwr1bw6hdg4k34can4y4qig73x9fi98-vscode-extension-Vue-volar-1.7.11/share/vscode/extensions/Vue.volar/dist/server.js:77:1942
    at w (/nix/store/nrwr1bw6hdg4k34can4y4qig73x9fi98-vscode-extension-Vue-volar-1.7.11/share/vscode/extensions/Vue.volar/dist/server.js:76:38771)
    at w (/nix/store/nrwr1bw6hdg4k34can4y4qig73x9fi98-vscode-extension-Vue-volar-1.7.11/share/vscode/extensions/Vue.volar/dist/server.js:76:39220)
    at Aoe (/nix/store/nrwr1bw6hdg4k34can4y4qig73x9fi98-vscode-extension-Vue-volar-1.7.11/share/vscode/extensions/Vue.volar/dist/server.js:76:38625)
    at Proxy.w (/nix/store/nrwr1bw6hdg4k34can4y4qig73x9fi98-vscode-extension-Vue-volar-1.7.11/share/vscode/extensions/Vue.volar/dist/server.js:77:1885) {
  errno: -13,
  syscall: 'scandir',
  code: 'EACCES',
  path: '/home/scott/src/kalkutago/db.mount'
}

"Save as..." in VSCode often triggers "Virtual script not found" error

Obviously there's no way to repro this in a repo, because this is an extension bug in VSCode, but on more than one occasion, if I'm working with a Vue SFC (in TypeScript), and I "Save as..." another file in the same folder, the script tag will say: Virtual script not found, may missing <script lang="ts"> / "allowJs": true / jsconfig.json

allowJs is enabled and was working just fine in tsconfig.json. Creating a jsconfig.json of course has no effect, because it's TypeScript (but I tried anyway). It happens only when duplicating a file. Restarting Volar is the only current fix.

Directory named "constructor" could crash

If a project have a directory named "constructor" it could crash with error like
TypeError: Cannot read properties of undefined (reading '<something>')

I found it happening because of a bug in the file packages/typescript/src/sys.ts , function getDirFromDir

	function getDirFromDir(dir: Dir, name: string) {
		let target = dir.dirs[name]; // <-------------- BUGGY LINE
		if (!target) {
			target = {
				dirs: {},
				files: {},
			};
			dir.dirs[name] = target;
		}
		return target;
	}

The function getDirFromDir gets called in a loop iterating through some directory path.
If there are a directory named "constructor" in the middle of the path then it will crash.

Getting name "constructor" of an empty object (which dir.dirs could be) returns the actual object constructor instead of a Dir object or undefined.
Then the object constructor gets returned as if it was a Dir found.
On the next call of getDirFromDir function there will be the object constructor used as the dir: Dir argument.
So if there is next call then the function throws a null-refference error because there is no dirs in the object constructor.

I kind of reproduced the bug and it seems like changing the buggy line would fix the issue:

let target = name in dir.dirs ? dir.dirs[name] : undefined;

Support remove all unused imports in Vue.js SFC?

Now, if the project supports ESlint, we can delete all unused imports using the VSCode ESlint quick fix. However, I believe it would take less time if we could accomplish this using a command.

Quick fix

image

Command

image

`volar.config.js` does not load on Windows

volar.config.js has no effect on Windows because the language server fails to resolve the file path.

This happens because of the path property on the URI class from vscode-uri. On windows it returns /c:/path instead of c:/path.

The fix is to use fsPath instead of path when calling loadConfig

[bug]vs-code snippet scoped in vue-html

"tabs": {
		"scope": "vue-html",
		"prefix": [
			"template:tabs",
		],
		"body": [
			"a line",
			"another line",
		],
		"description": "tabs"
	}

This won't work in the template section in a SFC file.

It's been a bug since vetur.

Deprecate `@volar/shared`

We've pretty much disassembled the shared module's functions down to the actual used packages, and we'll be able to remove it.

@volar/monaco: add @types/xxx automaticlly

When using @volar/monaco, for third-party libraries that don't have types in package.json(such as react), can @types/xxx be automatically added to obtain type prompts.

For example, when I import 'react' and it doesn't hava types field in package.json, I hope @volar/monaco can add @types/react automaticly.

image

Volar intellisense takeover mode does not resolve external workspaces/packages (monorepo)

Volar is not handling resolving external workspaces/packages within monorepo.

Reproduction: https://github.com/blake-newman/vue-tsc-import-resolution

takeover mode: off

When takeover mode is off it is able to auto import the modules/dependencies from external workspaces/packages

  • Enable the built-in TypeScript Extension
    • Run Extensions: Show Built-in Extensions from VSCode's command palette
    • Find TypeScript and JavaScript Language Features, right click and select Enable (Workspace)
  • Reload the VSCode window by running Developer: Reload Window from the command palette.
  • Within ./packages/main/src/index.ts try to use isFalse function from b package.
    • The exported function is found in intelisense and choosing that will auto import the dependency.

Screenshot 2023-03-16 at 09 01 37

takeover mode: on

When takeover mode is on it is unable to auto import modules/dependencies from external workspaces/packages

  • Enable the built-in TypeScript Extension
    • Run Extensions: Show Built-in Extensions from VSCode's command palette
    • Find TypeScript and JavaScript Language Features, right click and select Disable (Workspace)
  • Reload the VSCode window by running Developer: Reload Window from the command palette.
  • Within ./packages/main/src/index.ts try to use isFalse function from b package.
    • The exported function is not found in intelisense

Screenshot 2023-03-16 at 08 58 19

Add virtual file tester

The main purpose of a language plugin, is to provide (embdded) virtual files. These virtual files contain a snapshot and mappings. The Volar Labs VSCode extension provides a great way to inspect them. However, the mappings become pretty hard to interpret when writing tests (example).

It would be nice if Volar provides a way to represent virtual files in a way that’s friendly to the reader.

Idea: Add a function to represent a Volar virtual file as a markdown file containing annotated code blocks.

import { printVirtualFile } from '@volar/test-utils'

printSnapshot(printVirtualFile, {
  comments: {
    markdown: ['<!--', '-->'],
    mdx: ['{/*', '*/}'],
    typescriptreact: '//',
  }
})
```mdx fileName="file.mdx"
{/* Exact match */}
    import { Component } from './component.js'

    Hello <Component name={props.name} />
```

```javascriptreact fileName="file.mdx.jsx"
   import { Component } from './component.js'
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

   /**
    * @deprecated
    *   Do not use.
    *
    * @param {{readonly [K in keyof MDXContentProps]: MDXContentProps[K]}} props
    *   The [props](https://mdxjs.com/docs/using-mdx/#props) that have been passed to the MDX component.
    */
   function _createMdxContent(props) {
     return <><Component name={props.name} /></>
//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   }
   
   /**
    * Render the MDX contents.
    *
    * @param {{readonly [K in keyof MDXContentProps]: MDXContentProps[K]}} props
    *   The [props](https://mdxjs.com/docs/using-mdx/#props) that have been passed to the MDX component.
    */
   export default function MDXContent(props) {
     return <_createMdxContent {...props} />
   }
   
   // @ts-ignore
   /** @typedef {0 extends 1 & Props ? {} : Props} MDXContentProps */
```

```markdown fileName="file.mdx.md"

<!-- ^ --->
     Hello <!---->
<!-- ^^^^^^       ^ -->
```

The comment could be configured per language ID. Code is indented by the length of the opening comment. The commend uses ^ to indicate a character that matches the position in the parent virtual file, and shows the original character in case of a mismatch.

This file could be written to disk using any snapshotting library, or inlined in a multiline string.

Bug: jsDelivr isValidPackageName check is wrong

Hello,

Function isValidPackageName rejects packages whose name contain a dot while some valid packages contain dots.
Example : pixi.js https://www.jsdelivr.com/package/npm/pixi.js

if (pkgName.indexOf('.') >= 0 || pkgName.endsWith('/node_modules')) {

I don't know exactly the goal of this check, but if it aims to rejects local modules (import x from "./X") then this would be better:

if (pkgName.indexOf('.') == 0 || pkgName.endsWith('/node_modules')) { 

Thank you,

[v2] request handlers and context access in `ServerPlugin`

I enjoy using Volar - great work!

I found myself in need to:

  • implement custom requests to handle the extension commands and more
  • get access to the TS program to analyze the AST

With the help of @remcohaszing I managed to do both of those based on:

  • how the Vue's extension is using onRequest, here
  • how the volar-service-typescript-twoslash-queries is getting access to the TS language service, here

With those references and some source code spelunking I managed to do something along those lines:

export const createServerPlugin =
  (connection: Connection): ServerPlugin =>
  ({ modules }) => {
    return {
      typescript: {
        extraFileExtensions: [],
      },

      watchFileExtensions: [
        'cjs',
        'cts',
        'js',
        'jsx',
        'json',
        'mjs',
        'mts',
        'ts',
        'tsx',
      ],

      async resolveConfig(config, env, projectContext) {
        if (!modules.typescript) {
          throw new Error('TypeScript module is missing');
        }

        (config.services ||= {}).typescript = createTypeScriptService(
          modules.typescript,
        );

        return config;
      },
      onInitialized(projects) {
        connection.onRequest(helloRequest, async ({ textDocument, name }) => {
          if (!textDocument) {
            connection.console.log(`Hello, ${name}!`);
            return true;
          }
          const languageService = await getTypeScriptLanguageService(
            textDocument.uri,
          );

          connection.console.log(
            `Hello in "${languageService
              .getProgram()
              ?.getCurrentDirectory()}", ${name}!`,
          );
          return true;
        });

        async function getTypeScriptLanguageService(uri: string) {
          return (await projects.getProject(uri))
            .getLanguageService()
            .context.inject<Provide, 'typescript/languageService'>(
              'typescript/languageService',
            );
        }
      },
    };
  };

I think there is some opportunity in the API to make this use case easier

The Vue Semantic Server server crashed 5 times in the last 3 minutes. The server will not be restarted.

Bug

Error: Debug Failure. False expression: y:/mapped_network_drive/path/to/project/node_modules/vue/dist/vue.d.ts linked to nonexistent file //server/linux/path/to/project/node_modules/vue/dist/vue.d.ts

Project Info:

Additional Infomation

[@volar-plugins/typescript] sourceFile not found file:///y%3A/path/to/project/app.vue.js
c:\Users\username\AppData\Local\Programs\Microsoft VS Code\resources\app\extensions\node_modules\typescript\lib\typescript.js:39898

Create available commands for IDEs other than VSCode

Currently we have factory code for building commands in the following code, but it only works for VSCode (seems to work for coc too). We should judge the IDE of the language client to return the command format actually supported by the current IDE.

commands: {
rename: {
create(uri, position) {
const source = toSourceLocation(uri, position, data => typeof data.rename === 'object' ? !!data.rename.normalize : !!data.rename);
if (!source) {
return;
}
return vscode.Command.create(
'',
'editor.action.rename',
source.uri,
source.position,
);
},
is(command) {
return command.command === 'editor.action.rename';
},
},
showReferences: {
create(uri, position, locations) {
const source = toSourceLocation(uri, position);
if (!source) {
return;
}
const sourceReferences: vscode.Location[] = [];
for (const reference of locations) {
if (context.documents.isVirtualFileUri(reference.uri)) {
for (const [_, map] of context.documents.getMapsByVirtualFileUri(reference.uri)) {
const range = map.toSourceRange(reference.range);
if (range) {
sourceReferences.push({ uri: map.sourceFileDocument.uri, range });
}
}
}
else {
sourceReferences.push(reference);
}
}
return vscode.Command.create(
locations.length === 1 ? '1 reference' : `${locations.length} references`,
'editor.action.showReferences',
source.uri,
source.position,
sourceReferences,
);
},
is(command) {
return command.command === 'editor.action.showReferences';
},
},
setSelection: {
create(position: vscode.Position) {
return vscode.Command.create(
'',
'setSelection',
{
selection: {
selectionStartLineNumber: position.line + 1,
positionLineNumber: position.line + 1,
selectionStartColumn: position.character + 1,
positionColumn: position.character + 1,
},
},
);
},
is(command) {
return command.command === 'setSelection';
}
},

Allow service plugins to define request / notification handlers.

Based on mdx-js/mdx-analyzer#384, a bit of boilerplate is needed to define custom LSP request and notification handlers.

I think it would be neat if service plugins can specify request and notification handlers. This means language servers no longer have to deal with any of this.

The following service plugin:

export function createMdxServicePlugin() {
  return {
    name: 'mdx',

    create(context) {
      return {
        notification: {
          sayHi(params) {
            // Handle notification
          }
        },

        request: {
          toggleStrong(params) {
            // Handle request
          }
        }
      }
    }
  }
}

Would be equivalent to the following language server code:

connection.onRequest('mdx/toggleStrong', params => {
  // Handle request
})

connection.onNotification('mdx/sayHi', params => {
  // Handle request
})

The service plugin name is used to scope the requests and notifications, and is therefor required.

This could also make usage from contexts other than a language server more straight-forward, e.g. for testing purposes or usage from Monaco editor.

Integration with CodeMirror

We have now completed the Monaco integration and when I checked @vue/repl I noticed it also uses another web code editor called CodeMirror, I was just considering whether it also needs LSP support.

The closest solution at the moment is codemirror-languageserver maintained by @hjr265.

But perhaps a compatibility package between Monaco worker and CodeMirror editor would be a better approach?

For now, I will keep this issue open but I may not do the work because I am not even sure if CodeMirror is still being used or maintained by the community.

Feature: Enable language server features in tagged template literals

Sometimes I have code in a string:

const js = `
  const msg = 'this doesnt have any language server features';
  console.log(msg);
`

There is a vscode extension that allows syntax highlighting for such template literals by prefixing it was a comment or use a tagged template:

// with comment
const js = /* javascript */ `
  const msg = 'this code is highlighted';
  console.log(msg)
`
// via tagged template
const js = javascript`
  const msg = 'this code is highlighted';
  console.log(msg)
`

Syntax highlighting alone is pretty cool. However, I run into bugs all the time because I have spelling errors or other easy to catch mistakes if those templates would also have language server support.

So I wanted to extend the ts language server to add this feature but I am not sure if extending a language server is even possible yet.

In a dream world you probably would use it like this:

const outerMsg = 'hello from outside'
const ts = javascript`
  // inherits the scope of the sorrounding code
  console.log(outerMsg); // outerMsg is "string"
`

const ts = javascript<Window>`
  // scope is Window
  window.console.log('much wow!')
`

Obviously you would still need to define the javascript function in this case. So maybe its not the best solution but its a start.

2.0 Backlogs

How to load type definitions automatically in a monaco worker?

Hi,
I am using @volar/monaco/worker to create a language service for monaco-editor.

With the default monaco-editor TypeScript worker I can use addExtraLib to add an extra type definition so I can define some globals types that do not require to be imported (check the next screenshot using a React code)

Type definition Editor
image image

During the creation of the language service, I wanted to use my own dtsHost here:

createLanguageService({
    config: resolveConfig(
        {
            services: {
                typescript: createTsService({
                    dtsHost:  myOwnDtsHost, // <-here
                },
             }
        }
    }
}

But I noticed that the types are fetched once the package is required in the code, it is not fetched by default. Debugging, I also noticed that typescript, vue, csstype and other modules are loaded automatically. Is there a way to achieve the same with my custom library and custom type definitions?

Regards and thanks in advance.

Having issues with Vue Doc Examples

<script setup lang="ts">
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>

<template>
  <input :model-value="modelValue" @input="$emit('update:modelValue', $event.target?.value)">
</template>

for a component as simple as this, I am getting type errors from Volar (im in takeover mode and forced TS version to 4.9.5) saying that "Property value does not exist on type 'EventType'"

also using nuxt 3.3.2 if that matters

tried looking around and finding other solutions as well, any help is greatly appreciated

Add source.sortImports support for .vue files in Volar

Preamble

I think this issue needs to be in language-tools, but that repo has limited issue reporting to existing contributors, so I can't post this there. If it does need to be moved, I would appreciate a contributor adding it over there. Thank you in advance!

Request

I use VS Code for Vue development with the Volar plugins. In my VS Code config I used to use source.organizeImports in editor.codeActionsOnSave but it deletes unused imports which can break an application. I read that VS Code v1.57 added the source.sortImports action for javascript and typescript files. However, this action has no effect on .vue files.

Please add source.sortImports support for .vue files so I can automatically organize my inputs in a non-destructive manner.

Thank you!

volar fails to start due to a syntax error

Hello,

Using NeoVim I have installed the volar LSP via Mason.
Now, when I edit a .vue file, the volar LSP client immediately crashes with exit code 1 and signal 0.

This is the complete output in lsp.log (I will split it in multiple lines for readability):

[START][2023-04-16 09:06:32] LSP logging initiated
[ERROR][2023-04-16 09:06:32] .../vim/lsp/rpc.lua:734	"rpc"	"vue-language-server"	"stderr"
"/home/vincent/.local/share/nvim/mason/packages/vue-language-server/node_modules/@volar/
  vue-language-server/node_modules/@vscode/l10n/dist/main.js:846
throw new Error(e.responseText ?? (0, import_request_light.getErrorStatusDescription)(e.status) ?? e.toString());

SyntaxError: Unexpected token '?'
at wrapSafe (internal/modules/cjs/loader.js:915:16)
at Module._compile (internal/modules/cjs/loader.js:963:27)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
at Module.load (internal/modules/cjs/loader.js:863:32)
at Function.Module._load (internal/modules/cjs/loader.js:708:14)
at Module.require (internal/modules/cjs/loader.js:887:19)
at require (internal/modules/cjs/helpers.js:74:18)
at /home/vincent/.local/share/nvim/mason/packages/vue-language-server/node_modules/@volar/
  vue-language-server/node_modules/vscode-html-languageservice/lib/umd/parser/htmlScanner.js:17:18
at /home/vincent/.local/share/nvim/mason/packages/vue-language-server/node_modules/@volar/
  vue-language-server/node_modules/vscode-html-languageservice/lib/umd/parser/htmlScanner.js:7:17
at Object.<anonymous> (/home/vincent/.local/share/nvim/mason/packages/vue-language-server/
  node_modules/@volar/vue-language-server/node_modules/vscode-html-languageservice/lib/umd/parser/
  htmlScanner.js:13:3)"

Infinite recursion / stack overflow in getProgram Proxy

See screenshot. getProgram is getting called infinitely recursively. This is happening when using vite-plugin-checker 0.5.6 with vue-tsc 1.1.7 and typescript 4.9.5, although I don't think its anything that vite-plugin-checker is doing wrong.

If it helps, the stack frame before the one selected in my screenshot, resolveNamesWithLocalCache, is trying to call program.getResolvedProjectReferenceToRedirect('C:/my/project/__inferred type names__.ts') on every single stack frame that that function is repeated.

image

Custom SFC blocks

Hello there ! Thanks for making Volar, it is really awesome.

I want to implement server blocks for Nuxt nuxt/nuxt#20802
The SFC is going to look like this.

Under the hood, this entire block content would be removed, and processed separately by Nuxt. It wouldn't be present in the component itself, it's essentially isolated from blocks.

Adding lang="ts" make the color syntax work, but I want all the Typescript features to work, such as following the correct tsconfig and also typechecking.
I've considered using a <script server> tag too, but it seems to be easier with a custom name.
What needs to happen with Volar to make something like this work ? I would appreciate if you could point me in the right direction.
Thanks !

Plugin API v1

Before:

export interface LanguageServicePluginInstance {
rules?: {
onAny?(context: RuleContext): NotNullableResult<RuleContext>;
onFormat?(context: RuleContext): NotNullableResult<RuleContext>;
onSyntax?(context: RuleContext): NotNullableResult<RuleContext>;
onSemantic?(context: RuleContext): NotNullableResult<RuleContext>;
};
validation?: {
onSemantic?(document: TextDocument): NullableResult<vscode.Diagnostic[]>;
onSyntactic?(document: TextDocument): NullableResult<vscode.Diagnostic[]>;
onSuggestion?(document: TextDocument): NullableResult<vscode.Diagnostic[]>;
onDeclaration?(document: TextDocument): NullableResult<vscode.Diagnostic[]>;
};
doHover?(document: TextDocument, position: vscode.Position): NullableResult<vscode.Hover>,
findImplementations?(document: TextDocument, position: vscode.Position): NullableResult<vscode.LocationLink[]>;
findReferences?(document: TextDocument, position: vscode.Position): NullableResult<vscode.Location[]>;
findFileReferences?(document: TextDocument): NullableResult<vscode.Location[]>;
findDocumentHighlights?(document: TextDocument, position: vscode.Position): NullableResult<vscode.DocumentHighlight[]>;
findDocumentLinks?(document: TextDocument): NullableResult<vscode.DocumentLink[]>;
findDocumentSymbols?(document: TextDocument): NullableResult<vscode.DocumentSymbol[]>;
findDocumentSemanticTokens?(document: TextDocument, range: vscode.Range, legend: vscode.SemanticTokensLegend): NullableResult<SemanticToken[]>;
findWorkspaceSymbols?(query: string): NullableResult<vscode.WorkspaceSymbol[]>;
findDocumentColors?(document: TextDocument): NullableResult<vscode.ColorInformation[]>;
getColorPresentations?(document: TextDocument, color: vscode.Color, range: vscode.Range): NullableResult<vscode.ColorPresentation[]>;
doFileRename?(oldUri: string, newUri: string): NullableResult<vscode.WorkspaceEdit>;
getFoldingRanges?(document: TextDocument): NullableResult<vscode.FoldingRange[]>;
getSelectionRanges?(document: TextDocument, positions: vscode.Position[]): NullableResult<vscode.SelectionRange[]>;
getSignatureHelp?(document: TextDocument, position: vscode.Position, context?: vscode.SignatureHelpContext): NullableResult<vscode.SignatureHelp>;
format?(document: TextDocument, range: vscode.Range, options: vscode.FormattingOptions): NullableResult<vscode.TextEdit[]>;
formatOnType?(document: TextDocument, position: vscode.Position, key: string, options: vscode.FormattingOptions): NullableResult<vscode.TextEdit[]>;
getIndentSensitiveLines?(document: TextDocument): NullableResult<number[]>;
definition?: {
on?(document: TextDocument, position: vscode.Position): NullableResult<vscode.LocationLink[]>;
onType?(document: TextDocument, position: vscode.Position): NullableResult<vscode.LocationLink[]>;
};
complete?: {
triggerCharacters?: string[],
isAdditional?: boolean,
on?(document: TextDocument, position: vscode.Position, context?: vscode.CompletionContext): NullableResult<vscode.CompletionList>,
resolve?(item: vscode.CompletionItem): NotNullableResult<vscode.CompletionItem>,
};
rename?: {
prepare?(document: TextDocument, position: vscode.Position): NullableResult<vscode.Range | vscode.ResponseError<void>>;
on?(document: TextDocument, position: vscode.Position, newName: string): NullableResult<vscode.WorkspaceEdit>;
};
codeAction?: {
on?(document: TextDocument, range: vscode.Range, context: vscode.CodeActionContext): NullableResult<vscode.CodeAction[]>;
resolve?(codeAction: vscode.CodeAction): NotNullableResult<vscode.CodeAction>;
};
codeLens?: {
on?(document: TextDocument): NullableResult<vscode.CodeLens[]>;
resolve?(codeLens: vscode.CodeLens): NotNullableResult<vscode.CodeLens>;
};
referencesCodeLens?: {
on?(document: TextDocument): NullableResult<vscode.Location[]>;
resolve?(document: TextDocument, location: vscode.Location, references: vscode.Location[]): NotNullableResult<vscode.Location[]>;
};
callHierarchy?: {
prepare(document: TextDocument, position: vscode.Position): NullableResult<vscode.CallHierarchyItem[]>;
onIncomingCalls(item: vscode.CallHierarchyItem): NotNullableResult<vscode.CallHierarchyIncomingCall[]>;
onOutgoingCalls(item: vscode.CallHierarchyItem): NotNullableResult<vscode.CallHierarchyOutgoingCall[]>;
};
inlayHints?: {
on?(document: TextDocument, range: vscode.Range): NullableResult<vscode.InlayHint[]>,
// TODO: resolve
};
// html
findLinkedEditingRanges?(document: TextDocument, position: vscode.Position): NullableResult<vscode.LinkedEditingRanges>;
doAutoInsert?(document: TextDocument, position: vscode.Position, context: {
lastChange: {
range: vscode.Range;
rangeOffset: number;
rangeLength: number;
text: string;
};
}): NullableResult<string | vscode.TextEdit>;
/**
* TODO: only support to doCompleteResolve for now
*/
resolveEmbeddedRange?(range: vscode.Range): vscode.Range | undefined;
}

v1:

export interface LanguageServicePluginInstance {
isAdditionalCompletion?: boolean; // volar specific
triggerCharacters?: string[];
signatureHelpTriggerCharacters?: string[];
signatureHelpRetriggerCharacters?: string[];
autoFormatTriggerCharacters?: string[];
prepareRename?(document: TextDocument, position: vscode.Position, token: vscode.CancellationToken): NullableResult<vscode.Range | vscode.ResponseError<void>>;
provideHover?(document: TextDocument, position: vscode.Position, token: vscode.CancellationToken): NullableResult<vscode.Hover>,
provideDocumentSymbols?(document: TextDocument, token: vscode.CancellationToken): NullableResult<vscode.DocumentSymbol[]>;
provideDocumentHighlights?(document: TextDocument, position: vscode.Position, token: vscode.CancellationToken): NullableResult<vscode.DocumentHighlight[]>;
provideLinkedEditingRanges?(document: TextDocument, position: vscode.Position, token: vscode.CancellationToken): NullableResult<vscode.LinkedEditingRanges>;
provideDefinition?(document: TextDocument, position: vscode.Position, token: vscode.CancellationToken): NullableResult<vscode.LocationLink[]>;
provideTypeDefinition?(document: TextDocument, position: vscode.Position, token: vscode.CancellationToken): NullableResult<vscode.LocationLink[]>;
provideImplementation?(document: TextDocument, position: vscode.Position, token: vscode.CancellationToken): NullableResult<vscode.LocationLink[]>;
provideCodeLenses?(document: TextDocument, token: vscode.CancellationToken): NullableResult<vscode.CodeLens[]>;
provideCodeActions?(document: TextDocument, range: vscode.Range, context: vscode.CodeActionContext, token: vscode.CancellationToken): NullableResult<vscode.CodeAction[]>;
provideDocumentFormattingEdits?(document: TextDocument, range: vscode.Range, options: vscode.FormattingOptions, token: vscode.CancellationToken): NullableResult<vscode.TextEdit[]>;
provideOnTypeFormattingEdits?(document: TextDocument, position: vscode.Position, key: string, options: vscode.FormattingOptions, token: vscode.CancellationToken): NullableResult<vscode.TextEdit[]>;
provideLinks?(document: TextDocument, token: vscode.CancellationToken): NullableResult<vscode.DocumentLink[]>;
provideCompletionItems?(document: TextDocument, position: vscode.Position, context: vscode.CompletionContext, token: vscode.CancellationToken): NullableResult<vscode.CompletionList>,
provideDocumentColors?(document: TextDocument, token: vscode.CancellationToken): NullableResult<vscode.ColorInformation[]>;
provideColorPresentations?(document: TextDocument, color: vscode.Color, range: vscode.Range, token: vscode.CancellationToken): NullableResult<vscode.ColorPresentation[]>;
provideFoldingRanges?(document: TextDocument, token: vscode.CancellationToken): NullableResult<vscode.FoldingRange[]>;
provideSignatureHelp?(document: TextDocument, position: vscode.Position, context: vscode.SignatureHelpContext, token: vscode.CancellationToken): NullableResult<vscode.SignatureHelp>;
provideRenameEdits?(document: TextDocument, position: vscode.Position, newName: string, token: vscode.CancellationToken): NullableResult<vscode.WorkspaceEdit>;
provideReferences?(document: TextDocument, position: vscode.Position, token: vscode.CancellationToken): NullableResult<vscode.Location[]>;
provideSelectionRanges?(document: TextDocument, positions: vscode.Position[], token: vscode.CancellationToken): NullableResult<vscode.SelectionRange[]>;
provideInlayHints?(document: TextDocument, range: vscode.Range, token: vscode.CancellationToken): NullableResult<vscode.InlayHint[]>,
provideCallHierarchyItems(document: TextDocument, position: vscode.Position, token: vscode.CancellationToken): NullableResult<vscode.CallHierarchyItem[]>;
provideCallHierarchyIncomingCalls(item: vscode.CallHierarchyItem, token: vscode.CancellationToken): Result<vscode.CallHierarchyIncomingCall[]>;
provideCallHierarchyOutgoingCalls(item: vscode.CallHierarchyItem, token: vscode.CancellationToken): Result<vscode.CallHierarchyOutgoingCall[]>;
provideDocumentSemanticTokens?(document: TextDocument, range: vscode.Range, legend: vscode.SemanticTokensLegend, token: vscode.CancellationToken): NullableResult<SemanticToken[]>;
provideWorkspaceSymbols?(query: string, token: vscode.CancellationToken): NullableResult<vscode.WorkspaceSymbol[]>;
provideSyntacticDiagnostics?(document: TextDocument, token: vscode.CancellationToken): NullableResult<vscode.Diagnostic[]>;
provideSemanticDiagnostics?(document: TextDocument, token: vscode.CancellationToken): NullableResult<vscode.Diagnostic[]>;
provideFileReferences?(document: TextDocument, token: vscode.CancellationToken): NullableResult<vscode.Location[]>; // volar specific
provideReferencesCodeLenses?(document: TextDocument, token: vscode.CancellationToken): NullableResult<vscode.Location[]>; // volar specific
provideAutoInsertionEdit?(document: TextDocument, position: vscode.Position, context: AutoInsertionContext, token: vscode.CancellationToken): NullableResult<string | vscode.TextEdit>; // volar specific
provideFileRenameEdits?(oldUri: string, newUri: string, token: vscode.CancellationToken): NullableResult<vscode.WorkspaceEdit>; // volar specific
provideFormattingIndentSensitiveLines?(document: TextDocument, token: vscode.CancellationToken): NullableResult<number[]>; // volar specific
resolveCodeLens?(codeLens: vscode.CodeLens, token: vscode.CancellationToken): Result<vscode.CodeLens>;
resolveCodeAction?(codeAction: vscode.CodeAction, token: vscode.CancellationToken): Result<vscode.CodeAction>;
resolveCompletionItem?(item: vscode.CompletionItem, token: vscode.CancellationToken): Result<vscode.CompletionItem>,
resolveReferencesCodeLens?(document: TextDocument, location: vscode.Location, references: vscode.Location[], token: vscode.CancellationToken): Result<vscode.Location[]>; // volar specific
resolveRuleContext?(context: RuleContext, ruleType: 'format' | 'syntax' | 'semantic'): Result<RuleContext>; // volar specific
resolveEmbeddedRange?(range: vscode.Range): vscode.Range | undefined; // volar specific, only support in resolveCompletionItem for now
// resolveLink
// resolveInlayHint
}

[Feature Request] exposing the `FileRegistry` in 2.0

Hi, I'm working on a vscode extension ts-type-explorer that provides a view to know a type in the js or ts file and I added support for Vue files to this extension. See zcf0508/ts-type-explorer@c306370#diff-0d574bd7891645b07141f9f400e0830e391153bc3d2e7618245fcd8e86bd42fb .

I see that volar.js 2.0 is released recently, and I try to make my code compatible with it. See zcf0508/ts-type-explorer@e62e1cc#diff-0d574bd7891645b07141f9f400e0830e391153bc3d2e7618245fcd8e86bd42fb .

I used the program.__vue.langaugeContext to get the virtualFile and then calculate the new offset in the first commit.

But when I update the volar.js to 2.0, the program no longer exposes the languageContext and virtualFile. So I consider returning the FileRegistry when using proxyCreateProgram to create the program.Like thie.

// https://github.com/volarjs/volar.js/blob/v2.0.0/packages/typescript/lib/node/proxyCreateProgram.ts#L131

const program = Reflect.apply(target, thisArg, [options]);
decorateProgram(files, program);

+ program.files = files

return program;

@johnsoncodehk

If you have a plan to expose the FileRegistry or the other relevant object in other ways, I will wait for you to finish before continuing with further modifications. Alternatively, I can submit a pr according to the above plan.

Use `@volar/kit` to linting this repo

Rules:

  • Service needs to annotate the return type
  • Use import type for typescript/lib/tsserverlibrary
  • import typescript/lib/tsserverlibrary instead of typescript

volar-service-json 与 monaco.languages.json.jsonDefaults.setDiagnosticsOptions 没有联动关系

在使用Monaco 编辑器时发生的问题

JSON Worker

import * as worker from "monaco-editor-core/esm/vs/editor/editor.worker";
import type * as monaco from "monaco-editor-core";
import { resolveConfig } from "@vue/language-service";
import { createLanguageService } from "@volar/monaco/worker";
import createJsonService from "volar-service-json";

self.onmessage = () => {
  worker.initialize((ctx: monaco.worker.IWorkerContext) => {
    return createLanguageService({
      workerContext: ctx,
      config: resolveConfig(
        {
          services: {
            json: createJsonService({
              validate: true,
              allowComments: true,
              schemas: []
            })
          },
        },
      ),
    });
  });
};

index.vue

	import * as monaco from 'monaco-editor';
	// ...
    monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
      validate: true,
      enableSchemaRequest: true,
      allowComments: true,
      schemas: [
        {
          uri: componentName!,
          schema: JSONSchema
        }
      ]
    })

这两者似乎无法关联起来

Volar fails to start in eclipse theia

Volar fails to start in eclipse theia because cant find typescript module:

Message: Request initialize failed with message: Can't find typescript.js or tsserverlibrary.js in

after some investigation, i found that volar is trying to load the typescript module from extensions/node_modules, that seems to be the place where vscode contains this module.

if (vscode.env.appRoot) {
const libPath = path.join(
vscode.env.appRoot.replace(/\\/g, '/'),
'extensions/node_modules/typescript/lib',
);
return {
path: libPath,
version: await getTsVersion(libPath),
isWeb: false,
};
}

there's a workaround, installing the ms-vscode.vscode-typescript-next extensions, that uses extensionPath to find the node_modules folder (i think that extensionPath is empty so it use the node_modules from de theia folder)

const nightly = vscode.extensions.getExtension('ms-vscode.vscode-typescript-next');
if (nightly) {
const libPath = path.join(
nightly.extensionPath.replace(/\\/g, '/'),
'node_modules/typescript/lib',
);
return {
path: libPath,
version: await getTsVersion(libPath),
isWeb: false,
};
}

here's the related issue in theia repo: eclipse-theia/theia#12443

is there any chance to add a fix to this problem (ie, validating that the extensions/node_modules exists)?

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.