提交 a60cd343 编写于 作者: C Cherry Wang

Merge remote-tracking branch 'upstream/master'

......@@ -13,7 +13,7 @@ import * as languageModeIds from '../utils/languageModeIds';
import { disposeAll } from '../utils/dipose';
interface IDiagnosticRequestor {
requestDiagnostic(filepath: string): void;
requestDiagnostic(resource: Uri): void;
}
function mode2ScriptKind(mode: string): 'TS' | 'TSX' | 'JS' | 'JSX' | undefined {
......@@ -94,12 +94,53 @@ class SyncedBuffer {
};
this.client.execute('change', args, false);
}
this.diagnosticRequestor.requestDiagnostic(filePath);
this.diagnosticRequestor.requestDiagnostic(this.document.uri);
}
}
class SyncedBufferMap {
private readonly _map = new Map<string, SyncedBuffer>();
constructor(
private readonly _normalizePath: (resource: Uri) => string | null
) { }
public has(resource: Uri): boolean {
const file = this._normalizePath(resource);
return !!file && this._map.has(file);
}
public get(resource: Uri): SyncedBuffer | undefined {
const file = this._normalizePath(resource);
return file ? this._map.get(file) : undefined;
}
public set(resource: Uri, buffer: SyncedBuffer) {
const file = this._normalizePath(resource);
if (file) {
this._map.set(file, buffer);
}
}
public delete(resource: Uri): void {
const file = this._normalizePath(resource);
if (file) {
this._map.delete(file);
}
}
public get allBuffers(): Iterable<SyncedBuffer> {
return this._map.values();
}
public get allResources(): Iterable<string> {
return this._map.keys();
}
}
export interface Diagnostics {
delete(file: string): void;
delete(resource: Uri): void;
}
export default class BufferSyncSupport {
......@@ -110,7 +151,7 @@ export default class BufferSyncSupport {
private readonly modeIds: Set<string>;
private readonly diagnostics: Diagnostics;
private readonly disposables: Disposable[] = [];
private readonly syncedBuffers: Map<string, SyncedBuffer>;
private readonly syncedBuffers: SyncedBufferMap;
private pendingDiagnostics = new Map<string, number>();
private readonly diagnosticDelayer: Delayer<any>;
......@@ -128,7 +169,7 @@ export default class BufferSyncSupport {
this.diagnosticDelayer = new Delayer<any>(300);
this.syncedBuffers = new Map<string, SyncedBuffer>();
this.syncedBuffers = new SyncedBufferMap(path => this.client.normalizePath(path));
}
public listen(): void {
......@@ -143,12 +184,11 @@ export default class BufferSyncSupport {
}
public handles(resource: Uri): boolean {
const file = this.client.normalizePath(resource);
return !!file && this.syncedBuffers.has(file);
return this.syncedBuffers.has(resource);
}
public reOpenDocuments(): void {
for (const buffer of this.syncedBuffers.values()) {
for (const buffer of this.syncedBuffers.allBuffers) {
buffer.open();
}
}
......@@ -167,45 +207,37 @@ export default class BufferSyncSupport {
return;
}
const syncedBuffer = new SyncedBuffer(document, filepath, this, this.client);
this.syncedBuffers.set(filepath, syncedBuffer);
this.syncedBuffers.set(resource, syncedBuffer);
syncedBuffer.open();
this.requestDiagnostic(filepath);
this.requestDiagnostic(resource);
}
private onDidCloseTextDocument(document: TextDocument): void {
const filepath = this.client.normalizePath(document.uri);
if (!filepath) {
return;
}
const syncedBuffer = this.syncedBuffers.get(filepath);
const resource = document.uri;
const syncedBuffer = this.syncedBuffers.get(resource);
if (!syncedBuffer) {
return;
}
this.diagnostics.delete(filepath);
this.syncedBuffers.delete(filepath);
this.diagnostics.delete(resource);
this.syncedBuffers.delete(resource);
syncedBuffer.close();
if (!fs.existsSync(filepath)) {
if (!fs.existsSync(resource.fsPath)) {
this.requestAllDiagnostics();
}
}
private onDidChangeTextDocument(e: TextDocumentChangeEvent): void {
const filepath = this.client.normalizePath(e.document.uri);
if (!filepath) {
return;
}
let syncedBuffer = this.syncedBuffers.get(filepath);
if (!syncedBuffer) {
return;
const syncedBuffer = this.syncedBuffers.get(e.document.uri);
if (syncedBuffer) {
syncedBuffer.onContentChanged(e.contentChanges);
}
syncedBuffer.onContentChanged(e.contentChanges);
}
public requestAllDiagnostics() {
if (!this._validate) {
return;
}
for (const filePath of this.syncedBuffers.keys()) {
for (const filePath of this.syncedBuffers.allResources) {
this.pendingDiagnostics.set(filePath, Date.now());
}
this.diagnosticDelayer.trigger(() => {
......@@ -213,16 +245,21 @@ export default class BufferSyncSupport {
}, 200);
}
public requestDiagnostic(file: string): void {
public requestDiagnostic(resource: Uri): void {
if (!this._validate) {
return;
}
const file = this.client.normalizePath(resource);
if (!file) {
return;
}
this.pendingDiagnostics.set(file, Date.now());
const buffer = this.syncedBuffers.get(file);
const buffer = this.syncedBuffers.get(resource);
let delay = 300;
if (buffer) {
let lineCount = buffer.lineCount;
const lineCount = buffer.lineCount;
delay = Math.min(Math.max(Math.ceil(lineCount / 20), 300), 800);
}
this.diagnosticDelayer.trigger(() => {
......@@ -246,7 +283,7 @@ export default class BufferSyncSupport {
});
// Add all open TS buffers to the geterr request. They might be visible
for (const file of this.syncedBuffers.keys()) {
for (const file of this.syncedBuffers.allResources) {
if (!this.pendingDiagnostics.get(file)) {
files.push(file);
}
......
......@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
import { Diagnostic, DiagnosticCollection, languages, Uri } from 'vscode';
import { ITypeScriptServiceClient } from '../typescriptService';
class DiagnosticSet {
private _map: ObjectMap<Diagnostic[]> = Object.create(null);
......@@ -39,8 +38,7 @@ export default class DiagnosticsManager {
private _validate: boolean = true;
constructor(
language: string,
private readonly client: ITypeScriptServiceClient
language: string
) {
this.syntaxDiagnostics = new DiagnosticSet();
this.semanticDiagnostics = new DiagnosticSet();
......@@ -81,8 +79,8 @@ export default class DiagnosticsManager {
this.currentDiagnostics.set(file, diagnostics);
}
public delete(file: string): void {
this.currentDiagnostics.delete(this.client.asUrl(file));
public delete(resource: Uri): void {
this.currentDiagnostics.delete(resource);
}
private updateCurrentDiagnostics(file: Uri) {
......
......@@ -75,28 +75,30 @@ export class TypeScriptFormattingProvider implements DocumentRangeFormattingEdit
if (!filepath) {
return [];
}
await this.formattingOptionsManager.ensureFormatOptions(document, options, token);
const args: Proto.FormatOnKeyRequestArgs = {
file: filepath,
line: position.line + 1,
offset: position.character + 1,
key: ch
};
await this.formattingOptionsManager.ensureFormatOptions(document, options, token);
return this.client.execute('formatonkey', args, token).then((response): TextEdit[] => {
let edits = response.body;
let result: TextEdit[] = [];
try {
const response = await this.client.execute('formatonkey', args, token);
const edits = response.body;
const result: TextEdit[] = [];
if (!edits) {
return result;
}
for (const edit of edits) {
let textEdit = this.codeEdit2SingleEditOperation(edit);
let range = textEdit.range;
const textEdit = this.codeEdit2SingleEditOperation(edit);
const range = textEdit.range;
// Work around for https://github.com/Microsoft/TypeScript/issues/6700.
// Check if we have an edit at the beginning of the line which only removes white spaces and leaves
// an empty line. Drop those edits
if (range.start.character === 0 && range.start.line === range.end.line && textEdit.newText === '') {
let lText = document.lineAt(range.start.line).text;
const lText = document.lineAt(range.start.line).text;
// If the edit leaves something on the line keep the edit (note that the end character is exclusive).
// Keep it also if it removes something else than whitespace
if (lText.trim().length > 0 || lText.length > range.end.character) {
......@@ -107,9 +109,10 @@ export class TypeScriptFormattingProvider implements DocumentRangeFormattingEdit
}
}
return result;
}, () => {
return [];
});
} catch {
// noop
}
return [];
}
private codeEdit2SingleEditOperation(edit: Proto.CodeEdit): TextEdit {
......
......@@ -46,12 +46,12 @@ export default class LanguageProvider {
) {
this.formattingOptionsManager = new FormattingConfigurationManager(client);
this.bufferSyncSupport = new BufferSyncSupport(client, description.modeIds, {
delete: (file: string) => {
this.diagnosticsManager.delete(file);
delete: (resource) => {
this.diagnosticsManager.delete(resource);
}
}, this._validate);
this.diagnosticsManager = new DiagnosticsManager(description.id, this.client);
this.diagnosticsManager = new DiagnosticsManager(description.id);
workspace.onDidChangeConfiguration(this.configurationChanged, this, this.disposables);
this.configurationChanged();
......
......@@ -128,7 +128,7 @@ class ForkedTsServerProcess {
public createReader(
callback: ICallback<Proto.Response>,
onError: (error: any) => void = () => ({})
onError: (error: any) => void
) {
// tslint:disable-next-line:no-unused-expression
new Reader<Proto.Response>(this.childProcess.stdout, callback, onError);
......
......@@ -8,40 +8,40 @@ import { TypeScriptVersion } from './versionProvider';
import * as languageModeIds from './languageModeIds';
export default class VersionStatus {
private readonly onChangeEditorSub: vscode.Disposable;
private readonly versionBarEntry: vscode.StatusBarItem;
private readonly _onChangeEditorSub: vscode.Disposable;
private readonly _versionBarEntry: vscode.StatusBarItem;
constructor(
private readonly normalizePath: (resource: vscode.Uri) => string | null
private readonly _normalizePath: (resource: vscode.Uri) => string | null
) {
this.versionBarEntry = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 99 /* to the right of editor status (100) */);
this.onChangeEditorSub = vscode.window.onDidChangeActiveTextEditor(this.showHideStatus, this);
this._versionBarEntry = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 99 /* to the right of editor status (100) */);
this._onChangeEditorSub = vscode.window.onDidChangeActiveTextEditor(this.showHideStatus, this);
}
dispose() {
this.versionBarEntry.dispose();
this.onChangeEditorSub.dispose();
this._versionBarEntry.dispose();
this._onChangeEditorSub.dispose();
}
public onDidChangeTypeScriptVersion(version: TypeScriptVersion) {
this.showHideStatus();
this.versionBarEntry.text = version.versionString;
this.versionBarEntry.tooltip = version.path;
this.versionBarEntry.command = 'typescript.selectTypeScriptVersion';
this._versionBarEntry.text = version.versionString;
this._versionBarEntry.tooltip = version.path;
this._versionBarEntry.command = 'typescript.selectTypeScriptVersion';
}
private showHideStatus() {
if (!vscode.window.activeTextEditor) {
this.versionBarEntry.hide();
this._versionBarEntry.hide();
return;
}
const doc = vscode.window.activeTextEditor.document;
if (vscode.languages.match([languageModeIds.typescript, languageModeIds.typescriptreact], doc)) {
if (this.normalizePath(doc.uri)) {
this.versionBarEntry.show();
if (this._normalizePath(doc.uri)) {
this._versionBarEntry.show();
} else {
this.versionBarEntry.hide();
this._versionBarEntry.hide();
}
return;
}
......@@ -52,6 +52,6 @@ export default class VersionStatus {
return;
}
this.versionBarEntry.hide();
this._versionBarEntry.hide();
}
}
......@@ -90,7 +90,7 @@ export class Reader<T> {
public constructor(
private readonly readable: stream.Readable,
private readonly callback: ICallback<T>,
private readonly onError: (error: any) => void = () => ({})
private readonly onError: (error: any) => void
) {
this.readable.on('data', (data: Buffer) => {
this.onLengthData(data);
......
......@@ -128,7 +128,7 @@ export class ProductContribution implements IWorkbenchContribution {
// was there an update? if so, open release notes
if (!environmentService.skipReleaseNotes && product.releaseNotesUrl && lastVersion && pkg.version !== lastVersion) {
showReleaseNotes(instantiationService, lastVersion)
.then(() => {
.then(undefined, () => {
notificationService.notify({
severity: severity.Info,
message: nls.localize('read the release notes', "Welcome to {0} v{1}! Would you like to read the Release Notes?", product.nameLong, pkg.version),
......
......@@ -6000,9 +6000,9 @@ vscode-textmate@^3.2.0:
fast-plist "^0.1.2"
oniguruma "^6.0.1"
vscode-xterm@3.3.0-beta4:
version "3.3.0-beta4"
resolved "https://registry.yarnpkg.com/vscode-xterm/-/vscode-xterm-3.3.0-beta4.tgz#560c039c3addebe6aa3a81c5b79d2869de87ecc5"
vscode-xterm@3.3.0-beta5:
version "3.3.0-beta5"
resolved "https://registry.yarnpkg.com/vscode-xterm/-/vscode-xterm-3.3.0-beta5.tgz#4477c0ede38e2f39098f410bb7737a62832fb9e0"
vso-node-api@^6.1.2-preview:
version "6.1.2-preview"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册