support remove semicolons on format
This commit is contained in:
parent
b930a7b193
commit
2f69c55eac
6 changed files with 87 additions and 4 deletions
12
package.json
12
package.json
|
@ -175,6 +175,10 @@
|
||||||
"relative"
|
"relative"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"typescript.preferences.noSemicolons": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
"typescript.preferences.suggestionActions.enabled": {
|
"typescript.preferences.suggestionActions.enabled": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": true
|
"default": true
|
||||||
|
@ -283,6 +287,10 @@
|
||||||
"relative"
|
"relative"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"javascript.preferences.noSemicolons": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
"javascript.preferences.suggestionActions.enabled": {
|
"javascript.preferences.suggestionActions.enabled": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": true
|
"default": true
|
||||||
|
@ -389,9 +397,11 @@
|
||||||
"tslint": "^5.11.0"
|
"tslint": "^5.11.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"typescript": "^3.1.3",
|
"@types/fast-diff": "^1.1.0",
|
||||||
|
"fast-diff": "^1.2.0",
|
||||||
"semver": "^5.6.0",
|
"semver": "^5.6.0",
|
||||||
"tslib": "^1.9.3",
|
"tslib": "^1.9.3",
|
||||||
|
"typescript": "^3.1.3",
|
||||||
"vscode-languageserver-protocol": "^3.13.0",
|
"vscode-languageserver-protocol": "^3.13.0",
|
||||||
"vscode-uri": "^1.0.6",
|
"vscode-uri": "^1.0.6",
|
||||||
"which": "^1.3.1"
|
"which": "^1.3.1"
|
||||||
|
|
|
@ -122,7 +122,7 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP
|
||||||
|
|
||||||
const completionItems: CompletionItem[] = []
|
const completionItems: CompletionItem[] = []
|
||||||
for (const element of msg) {
|
for (const element of msg) {
|
||||||
if (!shouldExcludeCompletionEntry(element, completeOption)) {
|
if (shouldExcludeCompletionEntry(element, completeOption)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const item = convertCompletionEntry(
|
const item = convertCompletionEntry(
|
||||||
|
|
|
@ -135,6 +135,12 @@ export default class FileConfigurationManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public removeSemicolons(languageId: string): boolean {
|
||||||
|
const lang = this.isTypeScriptDocument(languageId) ? 'typescript' : 'javascript'
|
||||||
|
const config = workspace.getConfiguration(`${lang}.preferences`)
|
||||||
|
return config.get<boolean>('noSemicolons', false)
|
||||||
|
}
|
||||||
|
|
||||||
public getPreferences(language: string): Proto.UserPreferences {
|
public getPreferences(language: string): Proto.UserPreferences {
|
||||||
if (!this.client.apiVersion.gte(API.v290)) {
|
if (!this.client.apiVersion.gte(API.v290)) {
|
||||||
return {}
|
return {}
|
||||||
|
|
|
@ -2,12 +2,13 @@
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
import { CancellationToken, FormattingOptions, Position, Range, TextDocument, TextEdit } from 'vscode-languageserver-protocol'
|
|
||||||
import { commands, workspace } from 'coc.nvim'
|
import { commands, workspace } from 'coc.nvim'
|
||||||
import { DocumentFormattingEditProvider, DocumentRangeFormattingEditProvider } from 'coc.nvim/lib/provider'
|
import { DocumentFormattingEditProvider, DocumentRangeFormattingEditProvider } from 'coc.nvim/lib/provider'
|
||||||
|
import { CancellationToken, FormattingOptions, Position, Range, TextDocument, TextEdit } from 'vscode-languageserver-protocol'
|
||||||
import * as Proto from '../protocol'
|
import * as Proto from '../protocol'
|
||||||
import { ITypeScriptServiceClient } from '../typescriptService'
|
import { ITypeScriptServiceClient } from '../typescriptService'
|
||||||
import { languageIds } from '../utils/languageModeIds'
|
import { languageIds } from '../utils/languageModeIds'
|
||||||
|
import { removeSemicolon } from '../utils/semicolon'
|
||||||
import * as typeConverters from '../utils/typeConverters'
|
import * as typeConverters from '../utils/typeConverters'
|
||||||
import FileConfigurationManager from './fileConfigurationManager'
|
import FileConfigurationManager from './fileConfigurationManager'
|
||||||
|
|
||||||
|
@ -52,7 +53,11 @@ export default class TypeScriptFormattingProvider
|
||||||
try {
|
try {
|
||||||
const response = await this.client.execute('format', args, token)
|
const response = await this.client.execute('format', args, token)
|
||||||
if (response.body) {
|
if (response.body) {
|
||||||
return response.body.map(typeConverters.TextEdit.fromCodeEdit)
|
let edits = response.body.map(typeConverters.TextEdit.fromCodeEdit)
|
||||||
|
if (this.formattingOptionsManager.removeSemicolons(document.languageId)) {
|
||||||
|
return removeSemicolon(document, edits)
|
||||||
|
}
|
||||||
|
return edits
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// noop
|
// noop
|
||||||
|
|
52
src/server/utils/semicolon.ts
Normal file
52
src/server/utils/semicolon.ts
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import fastDiff from 'fast-diff'
|
||||||
|
import { TextDocument, TextEdit } from 'vscode-languageserver-protocol'
|
||||||
|
|
||||||
|
interface Change {
|
||||||
|
start: number
|
||||||
|
end: number
|
||||||
|
newText: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removeSemicolon(document: TextDocument, edits: TextEdit[]): TextEdit[] {
|
||||||
|
let orig = document.getText()
|
||||||
|
let content = TextDocument.applyEdits(document, edits)
|
||||||
|
let result = content.split('\n').map(s => s.replace(/;$/, '')).join('\n')
|
||||||
|
if (result == content) return edits
|
||||||
|
let change = getChange(orig, result)
|
||||||
|
return [{
|
||||||
|
range: {
|
||||||
|
start: document.positionAt(change.start),
|
||||||
|
end: document.positionAt(change.end)
|
||||||
|
},
|
||||||
|
newText: change.newText
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
function getChange(oldStr: string, newStr: string): Change {
|
||||||
|
let result = fastDiff(oldStr, newStr, 1)
|
||||||
|
let curr = 0
|
||||||
|
let start = -1
|
||||||
|
let end = -1
|
||||||
|
let newText = ''
|
||||||
|
let remain = ''
|
||||||
|
for (let item of result) {
|
||||||
|
let [t, str] = item
|
||||||
|
// equal
|
||||||
|
if (t == 0) {
|
||||||
|
curr = curr + str.length
|
||||||
|
if (start != -1) remain = remain + str
|
||||||
|
} else {
|
||||||
|
if (start == -1) start = curr
|
||||||
|
if (t == 1) {
|
||||||
|
newText = newText + remain + str
|
||||||
|
end = curr
|
||||||
|
} else {
|
||||||
|
newText = newText + remain
|
||||||
|
end = curr + str.length
|
||||||
|
}
|
||||||
|
remain = ''
|
||||||
|
if (t == -1) curr = curr + str.length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { start, end, newText }
|
||||||
|
}
|
10
yarn.lock
10
yarn.lock
|
@ -109,6 +109,11 @@
|
||||||
tslint-config-prettier "^1.6.0"
|
tslint-config-prettier "^1.6.0"
|
||||||
tslint-react "^3.2.0"
|
tslint-react "^3.2.0"
|
||||||
|
|
||||||
|
"@types/fast-diff@^1.1.0":
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/fast-diff/-/fast-diff-1.1.0.tgz#68c7f476025740b0b6756e51e38b1188dd528b0e"
|
||||||
|
integrity sha512-doBwHnPAGdE54EiIFc0/v1qHlRVtNTaxgCZOS9SdSGPq91vx3kUKi5fmz/yivW/RAXEOUJYVXtVFQ6IPpqKRWg==
|
||||||
|
|
||||||
"@types/mkdirp@^0.5.2":
|
"@types/mkdirp@^0.5.2":
|
||||||
version "0.5.2"
|
version "0.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f"
|
resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f"
|
||||||
|
@ -355,6 +360,11 @@ fast-diff@^1.1.2:
|
||||||
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154"
|
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154"
|
||||||
integrity sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==
|
integrity sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==
|
||||||
|
|
||||||
|
fast-diff@^1.2.0:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03"
|
||||||
|
integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==
|
||||||
|
|
||||||
fb-watchman@^2.0.0:
|
fb-watchman@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58"
|
resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58"
|
||||||
|
|
Loading…
Reference in a new issue