support remove semicolons on format

This commit is contained in:
chemzqm 2018-10-14 13:58:21 +08:00
parent b930a7b193
commit 2f69c55eac
6 changed files with 87 additions and 4 deletions

View file

@ -175,6 +175,10 @@
"relative"
]
},
"typescript.preferences.noSemicolons": {
"type": "boolean",
"default": false
},
"typescript.preferences.suggestionActions.enabled": {
"type": "boolean",
"default": true
@ -283,6 +287,10 @@
"relative"
]
},
"javascript.preferences.noSemicolons": {
"type": "boolean",
"default": false
},
"javascript.preferences.suggestionActions.enabled": {
"type": "boolean",
"default": true
@ -389,9 +397,11 @@
"tslint": "^5.11.0"
},
"dependencies": {
"typescript": "^3.1.3",
"@types/fast-diff": "^1.1.0",
"fast-diff": "^1.2.0",
"semver": "^5.6.0",
"tslib": "^1.9.3",
"typescript": "^3.1.3",
"vscode-languageserver-protocol": "^3.13.0",
"vscode-uri": "^1.0.6",
"which": "^1.3.1"

View file

@ -122,7 +122,7 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP
const completionItems: CompletionItem[] = []
for (const element of msg) {
if (!shouldExcludeCompletionEntry(element, completeOption)) {
if (shouldExcludeCompletionEntry(element, completeOption)) {
continue
}
const item = convertCompletionEntry(

View file

@ -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 {
if (!this.client.apiVersion.gte(API.v290)) {
return {}

View file

@ -2,12 +2,13 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* 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 { DocumentFormattingEditProvider, DocumentRangeFormattingEditProvider } from 'coc.nvim/lib/provider'
import { CancellationToken, FormattingOptions, Position, Range, TextDocument, TextEdit } from 'vscode-languageserver-protocol'
import * as Proto from '../protocol'
import { ITypeScriptServiceClient } from '../typescriptService'
import { languageIds } from '../utils/languageModeIds'
import { removeSemicolon } from '../utils/semicolon'
import * as typeConverters from '../utils/typeConverters'
import FileConfigurationManager from './fileConfigurationManager'
@ -52,7 +53,11 @@ export default class TypeScriptFormattingProvider
try {
const response = await this.client.execute('format', args, token)
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 {
// noop

View 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 }
}

View file

@ -109,6 +109,11 @@
tslint-config-prettier "^1.6.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":
version "0.5.2"
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"
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:
version "2.0.0"
resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58"