Merge branch 'neoclide:master' into master
This commit is contained in:
commit
90013b9637
11 changed files with 151 additions and 29 deletions
|
@ -75,6 +75,7 @@ Almost the same as VSCode.
|
|||
- `tsserver.restart`
|
||||
- `tsserver.organizeImports`
|
||||
- `tsserver.watchBuild`
|
||||
- `tsserver.findAllFileReferences`
|
||||
- Code completion support.
|
||||
- Go to definition (more info in [microsoft/TypeScript#37777](https://github.com/microsoft/TypeScript/issues/37777))
|
||||
- Code validation.
|
||||
|
@ -152,6 +153,11 @@ for guide of coc.nvim's configuration.
|
|||
default: `true`
|
||||
- `typescript.suggest.completeFunctionCalls`:Enable snippet for method
|
||||
suggestion, default: `true`
|
||||
- `typescript.suggest.includeCompletionsForImportStatements`: Enable/disable
|
||||
auto-import-style completions on partially-typed import statements. Requires using
|
||||
TypeScript 4.3+ in the workspace, default: `true`
|
||||
- `typescript.suggest.includeCompletionsWithSnippetText`: Enable snippet completions
|
||||
from TS Server. Requires using TypeScript 4.3+ in the workspace, default: `true`
|
||||
- `typescript.format.enabled`:Enable/disable format of typescript files.
|
||||
- `typescript.format.insertSpaceAfterCommaDelimiter` default: `true`
|
||||
- `typescript.format.insertSpaceAfterConstructor` default: `false`
|
||||
|
@ -200,6 +206,9 @@ for guide of coc.nvim's configuration.
|
|||
default: `true`
|
||||
- `javascript.suggest.completeFunctionCalls`:Enable snippet for method
|
||||
suggestion, default: `true`
|
||||
- `javascript.suggest.includeCompletionsForImportStatements`: Enable/disable
|
||||
auto-import-style completions on partially-typed import statements. Requires
|
||||
using TypeScript 4.3+ in the workspace, default: `true`
|
||||
- `javascript.format.insertSpaceAfterCommaDelimiter` default: `true`
|
||||
- `javascript.format.insertSpaceAfterConstructor` default: `false`
|
||||
- `javascript.format.insertSpaceAfterSemicolonInForStatements` default: `true`
|
||||
|
|
64
package.json
64
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "coc-tsserver",
|
||||
"version": "1.7.0",
|
||||
"version": "1.8.1",
|
||||
"description": "tsserver extension for coc.nvim",
|
||||
"main": "lib/index.js",
|
||||
"publisher": "chemzqm",
|
||||
|
@ -89,6 +89,11 @@
|
|||
"category": "TSServer",
|
||||
"command": "tsserver.restart"
|
||||
},
|
||||
{
|
||||
"title": "Find File References",
|
||||
"category": "TSServer",
|
||||
"command": "tsserver.findAllFileReferences"
|
||||
},
|
||||
{
|
||||
"title": "Run `tsc --watch` for current project by use vim's job feature.",
|
||||
"category": "TSServer",
|
||||
|
@ -109,6 +114,11 @@
|
|||
"default": true,
|
||||
"description": "Enable tsserver extension"
|
||||
},
|
||||
"tsserver.tsconfigPath": {
|
||||
"type": "string",
|
||||
"default": "tsconfig.json",
|
||||
"description": "Path to tsconfig file for the `tsserver.watchBuild` command. Defaults to `tsconfig.json`."
|
||||
},
|
||||
"tsserver.locale": {
|
||||
"type": [
|
||||
"string",
|
||||
|
@ -272,12 +282,19 @@
|
|||
},
|
||||
"typescript.preferences.importModuleSpecifier": {
|
||||
"type": "string",
|
||||
"default": "auto",
|
||||
"default": "shortest",
|
||||
"description": "Preferred path style for auto imports.",
|
||||
"enumDescriptions": [
|
||||
"Prefers a non-relative import only if one is available that has fewer path segments than a relative import",
|
||||
"Prefers a relative path to the imported file location",
|
||||
"Prefers a non-relative import based on the `baseUrl` or `paths` configured in your `jsconfig.json` / `tsconfig.json`.",
|
||||
"Prefers a non-relative import only if the relative import path would leave the package or project directory. Requires using TypeScript 4.2+ in the workspace."
|
||||
],
|
||||
"enum": [
|
||||
"non-relative",
|
||||
"shortest",
|
||||
"relative",
|
||||
"auto"
|
||||
"non-relative",
|
||||
"project-relative"
|
||||
]
|
||||
},
|
||||
"typescript.preferences.importModuleSpecifierEnding": {
|
||||
|
@ -326,6 +343,10 @@
|
|||
"default": true,
|
||||
"description": "Enable/disable suggest paths in import statement and require calls"
|
||||
},
|
||||
"typescript.suggest.importStatements": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"typescript.suggest.autoImports": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
|
@ -336,6 +357,18 @@
|
|||
"default": true,
|
||||
"description": "Enable snippet for method suggestion"
|
||||
},
|
||||
"typescript.suggest.includeCompletionsForImportStatements": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Enable/disable auto-import-style completions on partially-typed import statements. Requires using TypeScript 4.3+ in the workspace.",
|
||||
"scope": "resource"
|
||||
},
|
||||
"typescript.suggest.includeCompletionsWithSnippetText": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Enable/disable snippet completions from TS Server. Requires using TypeScript 4.3+ in the workspace.",
|
||||
"scope": "resource"
|
||||
},
|
||||
"typescript.format.enabled": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
|
@ -454,12 +487,19 @@
|
|||
},
|
||||
"javascript.preferences.importModuleSpecifier": {
|
||||
"type": "string",
|
||||
"default": "auto",
|
||||
"default": "shortest",
|
||||
"description": "Preferred path style for auto imports.",
|
||||
"enumDescriptions": [
|
||||
"Prefers a non-relative import only if one is available that has fewer path segments than a relative import",
|
||||
"Prefers a relative path to the imported file location",
|
||||
"Prefers a non-relative import based on the `baseUrl` or `paths` configured in your `jsconfig.json` / `tsconfig.json`.",
|
||||
"Prefers a non-relative import only if the relative import path would leave the package or project directory. Requires using TypeScript 4.2+ in the workspace."
|
||||
],
|
||||
"enum": [
|
||||
"auto",
|
||||
"shortest",
|
||||
"relative",
|
||||
"non-relative",
|
||||
"relative"
|
||||
"project-relative"
|
||||
]
|
||||
},
|
||||
"javascript.preferences.importModuleSpecifierEnding": {
|
||||
|
@ -522,6 +562,12 @@
|
|||
"default": true,
|
||||
"description": "Enable snippet for method suggestion"
|
||||
},
|
||||
"javascript.suggest.includeCompletionsForImportStatements": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Enable/disable auto-import-style completions on partially-typed import statements. Requires using TypeScript 4.3+ in the workspace.",
|
||||
"scope": "resource"
|
||||
},
|
||||
"javascript.format.enabled": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
|
@ -630,12 +676,12 @@
|
|||
"devDependencies": {
|
||||
"@types/node": "^10.12.0",
|
||||
"coc.nvim": "^0.0.80",
|
||||
"esbuild": "^0.8.29",
|
||||
"semver": "^7.3.2",
|
||||
"vscode-languageserver-protocol": "^3.15.3",
|
||||
"esbuild": "^0.8.29",
|
||||
"which": "^2.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"typescript": "^4.1.3"
|
||||
"typescript": "^4.3.2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { commands, ExtensionContext, services, workspace } from 'coc.nvim'
|
||||
import TsserverService from './server'
|
||||
import { AutoFixCommand, Command, ConfigurePluginCommand, OpenTsServerLogCommand, ReloadProjectsCommand, TypeScriptGoToProjectConfigCommand } from './server/commands'
|
||||
import { AutoFixCommand, Command, ConfigurePluginCommand, FileReferencesCommand, OpenTsServerLogCommand, ReloadProjectsCommand, TypeScriptGoToProjectConfigCommand } from './server/commands'
|
||||
import { OrganizeImportsCommand } from './server/organizeImports'
|
||||
import { PluginManager } from './utils/plugins'
|
||||
|
||||
|
@ -21,6 +21,7 @@ export async function activate(context: ExtensionContext): Promise<API> {
|
|||
registCommand(new ConfigurePluginCommand(pluginManager))
|
||||
registCommand(new AutoFixCommand(service))
|
||||
registCommand(new ReloadProjectsCommand(service))
|
||||
registCommand(new FileReferencesCommand(service))
|
||||
registCommand(new OpenTsServerLogCommand(service))
|
||||
registCommand(new TypeScriptGoToProjectConfigCommand(service))
|
||||
registCommand(new OrganizeImportsCommand(service))
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import { commands, diagnosticManager, CancellationToken, Diagnostic, Disposable, ServiceStat, Uri as URI, window, workspace } from 'coc.nvim'
|
||||
import { Range, TextEdit } from 'vscode-languageserver-types'
|
||||
import { Location, Position, Range, TextEdit } from 'vscode-languageserver-types'
|
||||
import TsserverService from '../server'
|
||||
import { PluginManager } from '../utils/plugins'
|
||||
import * as Proto from './protocol'
|
||||
import TypeScriptServiceClientHost from './typescriptServiceClientHost'
|
||||
import API from './utils/api'
|
||||
import { nodeModules } from './utils/helper'
|
||||
import { installModules } from './utils/modules'
|
||||
import * as typeConverters from './utils/typeConverters'
|
||||
|
@ -184,6 +185,39 @@ export class ConfigurePluginCommand implements Command {
|
|||
}
|
||||
}
|
||||
|
||||
export class FileReferencesCommand implements Command {
|
||||
public readonly id = 'tsserver.findAllFileReferences'
|
||||
public static readonly minVersion = API.v420
|
||||
|
||||
public constructor(
|
||||
private readonly service: TsserverService
|
||||
) {}
|
||||
|
||||
public async execute() {
|
||||
const client = await this.service.getClientHost()
|
||||
if (client.serviceClient.apiVersion.lt(FileReferencesCommand.minVersion)) {
|
||||
window.showMessage('Find file references failed. Requires TypeScript 4.2+.', 'error')
|
||||
return
|
||||
}
|
||||
|
||||
const doc = await workspace.document
|
||||
let { languageId } = doc.textDocument
|
||||
if (client.serviceClient.modeIds.indexOf(languageId) == -1) return
|
||||
|
||||
const openedFiledPath = client.serviceClient.toOpenedFilePath(doc.uri)
|
||||
if (!openedFiledPath) return
|
||||
|
||||
const response = await client.serviceClient.execute('fileReferences', { file: openedFiledPath }, CancellationToken.None)
|
||||
if (response.type !== 'response' || !response.body) return
|
||||
|
||||
const locations: Location[] = (response as Proto.FileReferencesResponse).body.refs.map(r =>
|
||||
typeConverters.Location.fromTextSpan(client.serviceClient.toResource(r.file), r)
|
||||
)
|
||||
|
||||
await commands.executeCommand('editor.action.showReferences', doc.uri, Position.create(0, 0), locations)
|
||||
}
|
||||
}
|
||||
|
||||
export function registCommand(cmd: Command): Disposable {
|
||||
let { id, execute } = cmd
|
||||
return commands.registerCommand(id as string, execute, cmd)
|
||||
|
|
|
@ -49,7 +49,7 @@ class ApplyCompletionCodeActionCommand implements CommandItem {
|
|||
|
||||
export default class TypeScriptCompletionItemProvider implements CompletionItemProvider {
|
||||
|
||||
public static readonly triggerCharacters = ['.', '"', '\'', '`', '/', '@', '<', '#']
|
||||
public static readonly triggerCharacters = ['.', '"', '\'', '`', '/', '@', '<', '#', ' ']
|
||||
private completeOption: SuggestOptions
|
||||
|
||||
constructor(
|
||||
|
@ -148,7 +148,7 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP
|
|||
dotAccessorContext = { range, text }
|
||||
}
|
||||
}
|
||||
isIncomplete = (response as any).metadata && (response as any).metadata.isIncomplete
|
||||
isIncomplete = !!response.body.isIncomplete || (response as any).metadata && (response as any).metadata.isIncomplete
|
||||
entries = response.body.entries
|
||||
} catch (e) {
|
||||
if (e.message == 'No content available.') {
|
||||
|
@ -194,6 +194,8 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP
|
|||
|
||||
case '#': // Workaround for https://github.com/microsoft/TypeScript/issues/36367
|
||||
return this.client.apiVersion.lt(API.v381) ? undefined : '#'
|
||||
case ' ':
|
||||
return this.client.apiVersion.gte(API.v430) ? ' ' : undefined
|
||||
|
||||
case '.':
|
||||
case '"':
|
||||
|
@ -220,7 +222,7 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP
|
|||
): Promise<CompletionItem> {
|
||||
if (item == null) return undefined
|
||||
|
||||
let { uri, position, source, name } = item.data
|
||||
let { uri, position, source, name, data } = item.data
|
||||
const filepath = this.client.toPath(uri)
|
||||
if (!filepath) return undefined
|
||||
let document = workspace.getDocument(uri)
|
||||
|
@ -230,7 +232,7 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP
|
|||
filepath,
|
||||
position
|
||||
),
|
||||
entryNames: [source ? { name, source } : name]
|
||||
entryNames: [source ? { name, source, data } : name]
|
||||
}
|
||||
|
||||
let response: ServerResponse.Response<Proto.CompletionDetailsResponse>
|
||||
|
@ -338,6 +340,13 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP
|
|||
}
|
||||
}
|
||||
|
||||
if (triggerCharacter === ' ') {
|
||||
if (!this.completeOption.importStatementSuggestions || !this.client.apiVersion.lt(API.v430)) {
|
||||
return false
|
||||
}
|
||||
return pre === 'import ';
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,9 @@ export interface SuggestOptions {
|
|||
readonly completeFunctionCalls: boolean
|
||||
readonly autoImports: boolean
|
||||
readonly includeAutomaticOptionalChainCompletions: boolean
|
||||
readonly importStatementSuggestions: boolean
|
||||
readonly includeCompletionsForImportStatements: boolean
|
||||
readonly includeCompletionsWithSnippetText: boolean
|
||||
}
|
||||
|
||||
export default class FileConfigurationManager {
|
||||
|
@ -156,6 +159,9 @@ export default class FileConfigurationManager {
|
|||
paths: config.get<boolean>('paths', true),
|
||||
completeFunctionCalls: config.get<boolean>('completeFunctionCalls', true),
|
||||
autoImports: config.get<boolean>('autoImports', true),
|
||||
importStatementSuggestions: config.get<boolean>('importStatements', true),
|
||||
includeCompletionsForImportStatements: config.get<boolean>('includeCompletionsForImportStatements', true),
|
||||
includeCompletionsWithSnippetText: config.get<boolean>('includeCompletionsWithSnippetText', true),
|
||||
includeAutomaticOptionalChainCompletions: config.get<boolean>('includeAutomaticOptionalChainCompletions', true)
|
||||
}
|
||||
}
|
||||
|
@ -173,6 +179,8 @@ export default class FileConfigurationManager {
|
|||
allowTextChangesInNewFiles: uri.startsWith('file:'),
|
||||
allowRenameOfImportPath: true,
|
||||
providePrefixAndSuffixTextForRename: config.get<boolean>('renameShorthandProperties', true) === false ? false : config.get<boolean>('useAliasesForRenames', true),
|
||||
includeCompletionsForImportStatements: this.getCompleteOptions(language).includeCompletionsForImportStatements,
|
||||
includeCompletionsWithSnippetText: this.getCompleteOptions(language).includeCompletionsWithSnippetText,
|
||||
}
|
||||
return preferences
|
||||
}
|
||||
|
@ -188,17 +196,19 @@ export default class FileConfigurationManager {
|
|||
}
|
||||
}
|
||||
|
||||
type ModuleImportType = 'relative' | 'non-relative' | 'auto'
|
||||
type ModuleImportType = 'shortest' | 'project-relative' | 'relative' | 'non-relative'
|
||||
|
||||
function getImportModuleSpecifier(config): ModuleImportType {
|
||||
function getImportModuleSpecifier(config: WorkspaceConfiguration): ModuleImportType {
|
||||
let val = config.get('importModuleSpecifier')
|
||||
switch (val) {
|
||||
case 'project-relative':
|
||||
return 'project-relative'
|
||||
case 'relative':
|
||||
return 'relative'
|
||||
case 'non-relative':
|
||||
return 'non-relative'
|
||||
default:
|
||||
return 'auto'
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ export default class WatchProject implements Disposable {
|
|||
) {
|
||||
this.statusItem = window.createStatusBarItem(1, { progress: true })
|
||||
let task = this.task = workspace.createTask('TSC')
|
||||
|
||||
this.disposables.push(commands.registerCommand(WatchProject.id, async () => {
|
||||
let opts = this.options = await this.getOptions()
|
||||
await this.start(opts)
|
||||
|
@ -117,15 +118,18 @@ export default class WatchProject implements Disposable {
|
|||
window.showMessage(`Local & global tsc not found`, 'error')
|
||||
return
|
||||
}
|
||||
let find = await workspace.findUp(['tsconfig.json'])
|
||||
|
||||
const tsconfigPath = workspace.getConfiguration('tsserver').get<string>('tsconfigPath', 'tsconfig.json');
|
||||
let find = await workspace.findUp([tsconfigPath])
|
||||
if (!find) {
|
||||
window.showMessage('tsconfig.json not found!', 'error')
|
||||
window.showMessage(`${tsconfigPath} not found!`, 'error')
|
||||
return
|
||||
}
|
||||
|
||||
let root = path.dirname(find)
|
||||
return {
|
||||
cmd: tscPath,
|
||||
args: ['-p', 'tsconfig.json', '--watch', 'true', '--pretty', 'false'],
|
||||
args: ['-p', tsconfigPath, '--watch', 'true', '--pretty', 'false'],
|
||||
cwd: root
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ export namespace ServerResponse {
|
|||
|
||||
constructor(
|
||||
public readonly reason: string
|
||||
) { }
|
||||
) {}
|
||||
}
|
||||
|
||||
// tslint:disable-next-line: new-parens
|
||||
|
@ -80,6 +80,7 @@ export interface TypeScriptRequestTypes {
|
|||
'selectionRange': [Proto.SelectionRangeRequestArgs, Proto.SelectionRangeResponse]
|
||||
'signatureHelp': [Proto.SignatureHelpRequestArgs, Proto.SignatureHelpResponse]
|
||||
'typeDefinition': [Proto.FileLocationRequestArgs, Proto.TypeDefinitionResponse]
|
||||
'fileReferences': [Proto.FileRequestArgs, Proto.FileReferencesResponse]
|
||||
}
|
||||
|
||||
export interface ITypeScriptServiceClient {
|
||||
|
|
|
@ -39,7 +39,9 @@ export default class API {
|
|||
public static readonly v381 = API.fromSimpleString('3.8.1')
|
||||
public static readonly v390 = API.fromSimpleString('3.9.0')
|
||||
public static readonly v400 = API.fromSimpleString('4.0.0')
|
||||
public static readonly v401 = API.fromSimpleString('4.0.1');
|
||||
public static readonly v401 = API.fromSimpleString('4.0.1')
|
||||
public static readonly v420 = API.fromSimpleString('4.2.0')
|
||||
public static readonly v430 = API.fromSimpleString('4.3.0')
|
||||
|
||||
public static fromVersionString(versionString: string): API {
|
||||
let version = semver.valid(versionString)
|
||||
|
|
|
@ -37,7 +37,7 @@ export function convertCompletionEntry(
|
|||
if (tsEntry.isRecommended) {
|
||||
preselect = true
|
||||
}
|
||||
if (tsEntry.source) {
|
||||
if (tsEntry.source && tsEntry.hasAction) {
|
||||
// De-prioritze auto-imports https://github.com/Microsoft/vscode/issues/40311
|
||||
sortText = '\uffff' + sortText
|
||||
} else {
|
||||
|
@ -53,13 +53,18 @@ export function convertCompletionEntry(
|
|||
let insertText = tsEntry.insertText
|
||||
let commitCharacters = getCommitCharacters(tsEntry, context)
|
||||
|
||||
if (tsEntry.isImportStatementCompletion) {
|
||||
insertText = label
|
||||
insertTextFormat = InsertTextFormat.Snippet
|
||||
}
|
||||
|
||||
let textEdit: TextEdit | null = null
|
||||
if (tsEntry.replacementSpan) {
|
||||
let { start, end } = tsEntry.replacementSpan
|
||||
if (start.line == end.line) {
|
||||
textEdit = {
|
||||
range: Range.create(start.line - 1, start.offset - 1, end.line - 1, end.offset - 1),
|
||||
newText: insertText || label
|
||||
newText: tsEntry.insertText || label
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,6 +106,7 @@ export function convertCompletionEntry(
|
|||
uri,
|
||||
position,
|
||||
name: tsEntry.name,
|
||||
data: tsEntry.data,
|
||||
source: tsEntry.source || ''
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,10 +27,10 @@ semver@^7.3.2:
|
|||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
|
||||
integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
|
||||
|
||||
typescript@^4.1.3:
|
||||
version "4.1.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7"
|
||||
integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==
|
||||
typescript@^4.3.2:
|
||||
version "4.3.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.2.tgz#399ab18aac45802d6f2498de5054fcbbe716a805"
|
||||
integrity sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==
|
||||
|
||||
vscode-jsonrpc@^5.0.1:
|
||||
version "5.0.1"
|
||||
|
|
Loading…
Reference in a new issue