Skip to content

Commit

Permalink
Upgrade to Volar 1.x (#134)
Browse files Browse the repository at this point in the history
* Add support for Volar 1.x

* Handle custom vue.findReferences notification

* update vueCompilerOptions schema

* prevent starting when no workspace folder

* remove updateImportsOnFileMove

* 1.0.5

* fix link

* 1.0.7

* 1.0.9

* add emmet options

* add noProjectReferences

* move to init options
  • Loading branch information
rchl committed Oct 28, 2022
1 parent 00047b1 commit 32f0c42
Show file tree
Hide file tree
Showing 9 changed files with 1,162 additions and 709 deletions.
67 changes: 48 additions & 19 deletions LSP-volar.sublime-settings
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
{
"command": ["${node_bin}", "${server_path}", "--stdio"],
"initializationOptions": {
// Specify the `typescript.serverPath` to tsserverlibrary.js.
// List any additional file extensions that should be processed as Vue files.
"additionalExtensions": [],
// Defines which auto-complete popup trigger characters that Volar defines are allowed.
// By default all Volar trigger characters are disabled as ST does a better job.
"ignoreTriggerCharacters": [],
// Specify the `typescript.tsdk` to tsserverlibrary.js.
// If not specified LSP-volar will use the typescript from the workspace if it exist,
// else the typescript bundled with LSP-volar will be used.
"typescript": {
// "serverPath": "/path/to/tsserverlibrary.js"
}
// "typescript.tsdk": "/path/to/tsserverlibrary.js"
// Set --max-old-space-size option on server process. If you have problem on frequently
// "Request textDocument/** failed." error, try setting higher memory(MB) on it.
"maxOldSpaceSize": null,
// Ignore project references settings of tsconfig in language server for resolve issue
// https://github.com/johnsoncodehk/volar/issues/1344.
"noProjectReferences": false,
},
"settings": {
// Auto-complete Ref value with `.value`.
Expand All @@ -19,16 +27,16 @@
"volar.codeLens.references": true,
// [ref sugar ☐] code lens.
"volar.codeLens.scriptSetupTools": false,
// Enabled auto-import for component with tag completion.
"volar.completion.autoImportComponent": true,
// Do not trigger the auto-complete popup on these characters.
"volar.completion.ignoreTriggerCharacters": "",
// Normalize import name for auto import. ("myCompVue" -> "MyComp")
"volar.completion.normalizeComponentAutoImportName": true,
// Preferred attr name case.
// possible values: auto-kebab, auto-camel, kebab, camel
// possible values: "auto-kebab", "auto-camel", "kebab", "camel"
"volar.completion.preferredAttrNameCase": "auto-kebab",
// Preferred tag name case.
// possible values: auto, both, kebab, pascal
"volar.completion.preferredTagNameCase": "auto",
// possible values: "auto-kebab", "auto-pascal", "kebab", "pascal"
"volar.completion.preferredTagNameCase": "auto-pascal",
// Delay time for diagnostics.
"volar.diagnostics.delay": 200,
// Whether to have initial indent.
"volar.format.initialIndent": {
"css": false,
Expand All @@ -41,30 +49,51 @@
"typescript": false,
"typescriptreact": false,
},
// Set --max-old-space-size option on server process. If you have problem on frequently
// "Request textDocument/** failed." error, try setting higher memory(MB) on it.
"volar.vueserver.maxOldSpaceSize": null,
// Defines how the host (editor) should sync document changes to the language server.
"volar.vueserver.textDocumentSync": "incremental",

// javascript inlay hint
"javascript.inlayHints.enumMemberValues.enabled": false,
"javascript.inlayHints.functionLikeReturnTypes.enabled": false,
"javascript.inlayHints.parameterNames.enabled": "none",
"javascript.inlayHints.parameterNames.suppressWhenArgumentMatchesName": false,
"javascript.inlayHints.parameterNames.suppressWhenArgumentMatchesName": true,
"javascript.inlayHints.parameterTypes.enabled": false,
"javascript.inlayHints.propertyDeclarationTypes.enabled": false,
"javascript.inlayHints.variableTypes.enabled": false,
"javascript.inlayHints.variableTypes.suppressWhenTypeMatchesName.enabled": true,

// typescript inlay hint
"typescript.inlayHints.enumMemberValues.enabled": false,
"typescript.inlayHints.functionLikeReturnTypes.enabled": false,
"typescript.inlayHints.parameterNames.enabled": "none",
"typescript.inlayHints.parameterNames.suppressWhenArgumentMatchesName": false,
"typescript.inlayHints.parameterNames.suppressWhenArgumentMatchesName": true,
"typescript.inlayHints.parameterTypes.enabled": false,
"typescript.inlayHints.propertyDeclarationTypes.enabled": false,
"typescript.inlayHints.variableTypes.enabled": false,
"typescript.inlayHints.variableTypes.suppressWhenTypeMatchesName.enabled": true,

// Emmet plugin settings (autocompletion within template blocks).

// An array of languages where Emmet abbreviations should not be expanded.
"emmet.excludeLanguages": ["markdown"],
// Preferences used to modify behavior of some actions and resolvers of Emmet.
"emmet.preferences": {},
// Shows possible Emmet abbreviations as suggestions. Not applicable in stylesheets or when
// emmet.showExpandedAbbreviation is set to `"never"`.
"emmet.showAbbreviationSuggestions": true,
// Shows expanded Emmet abbreviations as suggestions.
// The option `"inMarkupAndStylesheetFilesOnly"` applies to html, haml, jade, slim, xml,
// xsl, css, scss, sass, less and stylus.
// The option `"always"` applies to all parts of the file regardless of markup/css.
// possible values: "never", "always", "inMarkupAndStylesheetFilesOnly"
"emmet.showExpandedAbbreviation": "always",
// If `true`, then Emmet suggestions will show up as snippets allowing you to order them as
// per `#editor.snippetSuggestions#` setting.
"emmet.showSuggestionsAsSnippets": false,
// Define profile for specified syntax or use your own profile with specific rules.
"emmet.syntaxProfiles": {},
// Variables to be used in Emmet snippets.
"emmet.variables": {},
},
"command": ["${node_bin}", "${server_path}", "--stdio"],
// ST4
"selector": "text.html.vue",
// ST3
Expand Down
136 changes: 41 additions & 95 deletions plugin.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
from .types import VueFindReferencesParams
from LSP.plugin import ClientConfig
from LSP.plugin import WorkspaceFolder
from LSP.plugin.core.protocol import TextDocumentSyncKind
from LSP.plugin.core.typing import List, Optional
from lsp_utils import NpmClientHandler
from LSP.plugin.locationpicker import LocationPicker
from lsp_utils import NpmClientHandler, notification_handler
import os
import sublime
import subprocess
import sys


def plugin_loaded():
Expand All @@ -29,99 +28,46 @@ def is_allowed_to_start(
initiating_view: Optional[sublime.View] = None,
workspace_folders: Optional[List[WorkspaceFolder]] = None,
configuration: Optional[ClientConfig] = None
):
) -> Optional[str]:
if not workspace_folders or not configuration:
return
configuration.init_options.set('textDocumentSync', get_text_document_sync(configuration))
configuration.init_options.set('languageFeatures', get_language_features(configuration))
configuration.init_options.set('documentFeatures', {
"selectionRange": True,
"foldingRange": True,
"linkedEditingRange": False,
"documentSymbol": True,
"documentColor": True,
"documentFormatting": {
"defaultPrintWidth": 90
}
})
if configuration.init_options.get('typescript.serverPath'):
return # don't find the `typescript.serverPath` if it was set explicitly in LSP-volar.sublime-settings
typescript_path = cls.find_typescript_path(workspace_folders[0].path)
configuration.init_options.set('typescript.serverPath', typescript_path)
return 'Can not run without a workspace folder'
if configuration.init_options.get('typescript.tsdk'):
return # don't find the `typescript.tsdk` if it was set explicitly in LSP-volar.sublime-settings
typescript_lib_path = cls.find_typescript_lib_path(workspace_folders[0].path)
if not typescript_lib_path:
return 'Could not resolve location of TypeScript package'
configuration.init_options.set('typescript.tsdk', typescript_lib_path)

@classmethod
def find_typescript_path(cls, current_folder: str) -> str:
def find_typescript_lib_path(cls, workspace_folder: str) -> Optional[str]:
module_paths = [
'node_modules/typescript/lib/tsserverlibrary.js',
'.vscode/pnpify/typescript/lib/tsserverlibrary.js',
'.yarn/sdks/typescript/lib/tsserverlibrary.js'
]
for module_path in module_paths:
candidate = os.path.join(workspace_folder, module_path)
if os.path.isfile(candidate):
return os.path.dirname(candidate)
server_directory_path = cls._server_directory_path()
resolve_module_script = os.path.join(server_directory_path, 'resolve_module.js')
find_ts_server_command = [cls._node_bin(), resolve_module_script, current_folder]
startupinfo = None
# Prevent cmd.exe popup on Windows.
if sys.platform == "win32":
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= (
subprocess.SW_HIDE | subprocess.STARTF_USESHOWWINDOW
)
workspace_ts_path = subprocess.check_output(find_ts_server_command, universal_newlines=True, startupinfo=startupinfo)
bundled_ts_path = os.path.join(server_directory_path, 'node_modules', 'typescript', 'lib', 'tsserverlibrary.js')
return workspace_ts_path or bundled_ts_path


def get_default_tag_name_case(configuration: ClientConfig) -> str:
preferred_tag_name_case = configuration.settings.get('volar.completion.preferredTagNameCase')
if preferred_tag_name_case == 'kebab':
return 'kebabCase'
elif preferred_tag_name_case == 'pascal':
return 'pascalCase'
return 'both'


def get_default_attr_name_case(configuration: ClientConfig) -> str:
preferred_attr_name_case = configuration.settings.get('volar.completion.preferredAttrNameCase')
if preferred_attr_name_case == 'camel':
return 'camelCase'
return 'kebabCase'

return os.path.join(server_directory_path, 'node_modules', 'typescript', 'lib')

def get_text_document_sync(configuration: ClientConfig) -> TextDocumentSyncKind:
text_document_sync = configuration.settings.get('volar.vueserver.textDocumentSync')
if text_document_sync == 'full':
return TextDocumentSyncKind.Full
if text_document_sync == 'none':
return TextDocumentSyncKind.None_
return TextDocumentSyncKind.Incremental


def get_ignored_trigger_characters(configuration: ClientConfig) -> str:
return configuration.settings.get('volar.completion.ignoreTriggerCharacters') or ""


def get_language_features(configuration: ClientConfig) -> dict:
language_features = {
"references": True,
"implementation": True,
"definition": True,
"typeDefinition": True,
"callHierarchy": False,
"hover": True,
"rename": True,
"renameFileRefactoring": False,
"signatureHelp": True,
"codeAction": True,
"workspaceSymbol": True,
"completion": {
"defaultTagNameCase": get_default_tag_name_case(configuration),
"defaultAttrNameCase": get_default_attr_name_case(configuration),
"getDocumentNameCasesRequest": False,
"getDocumentSelectionRequest": False,
"ignoreTriggerCharacters": get_ignored_trigger_characters(configuration)
},
"schemaRequestService": False,
"documentHighlight": True,
"documentLink": True,
"codeLens": {"showReferencesNotification": True},
"semanticTokens": True,
"inlayHints": True,
"diagnostics": True,
"schemaRequestService": False
}
return language_features
@notification_handler('vue.findReferences')
def onVueFindReferences(self, params: VueFindReferencesParams) -> None:
session = self.weaksession()
if not session:
return
view = sublime.active_window().active_view()
if not view:
return
references = params['references']
if len(references) == 1:
args = {
'location': references[0],
'session_name': session.config.name,
}
view.run_command('lsp_open_location', args)
elif references:
LocationPicker(view, session, params['references'], side_by_side=False)
else:
sublime.status_message('No references found')
3 changes: 3 additions & 0 deletions pyrightconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"pythonVersion": "3.11"
}

0 comments on commit 32f0c42

Please sign in to comment.