Fixes #13266: TSC version mismatch shouldn't be shown for JavaScript

This commit is contained in:
Dirk Baeumer 2016-10-27 12:01:15 +02:00
parent 4a15897b3f
commit b74b36bee0
3 changed files with 106 additions and 76 deletions

View file

@ -4,15 +4,19 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as cp from 'child_process';
import * as path from 'path';
import * as fs from 'fs';
import { workspace, TextDocument, TextDocumentChangeEvent, TextDocumentContentChangeEvent, Disposable } from 'vscode';
import { workspace, window, TextDocument, TextDocumentChangeEvent, TextDocumentContentChangeEvent, Disposable, MessageItem } from 'vscode';
import * as Proto from '../protocol';
import { ITypescriptServiceClient } from '../typescriptService';
import { Delayer } from '../utils/async';
import LinkedMap from './linkedMap';
import * as nls from 'vscode-nls';
let localize = nls.loadMessageBundle();
interface IDiagnosticRequestor {
requestDiagnostic(filepath: string): void;
}
@ -96,6 +100,7 @@ export interface Diagnostics {
delete(file: string): void;
}
const checkTscVersionSettingKey = 'check.tscVersion';
export default class BufferSyncSupport {
private client: ITypescriptServiceClient;
@ -112,6 +117,7 @@ export default class BufferSyncSupport {
private pendingDiagnostics: { [key: string]: number; };
private diagnosticDelayer: Delayer<any>;
private emitQueue: LinkedMap<string>;
private checkGlobalTSCVersion: boolean;
constructor(client: ITypescriptServiceClient, modeIds: string[], diagnostics: Diagnostics, extensions: Map<boolean>, validate: boolean = true) {
this.client = client;
@ -128,6 +134,9 @@ export default class BufferSyncSupport {
this.syncedBuffers = Object.create(null);
this.emitQueue = new LinkedMap<string>();
const tsConfig = workspace.getConfiguration('typescript');
this.checkGlobalTSCVersion = client.checkGlobalTSCVersion && this.modeIds['typescript'] === true && tsConfig.get(checkTscVersionSettingKey, true);
}
public listen(): void {
@ -178,6 +187,7 @@ export default class BufferSyncSupport {
this.syncedBuffers[filepath] = syncedBuffer;
syncedBuffer.open();
this.requestDiagnostic(filepath);
this.checkTSCVersion();
}
private onDidCloseTextDocument(document: TextDocument): void {
@ -276,4 +286,74 @@ export default class BufferSyncSupport {
this.client.execute('geterr', args, false);
this.pendingDiagnostics = Object.create(null);
}
private checkTSCVersion() {
if (!this.checkGlobalTSCVersion) {
return;
}
this.checkGlobalTSCVersion = false;
interface MyMessageItem extends MessageItem {
id: number;
}
function openUrl(url: string) {
let cmd: string;
switch (process.platform) {
case 'darwin':
cmd = 'open';
break;
case 'win32':
cmd = 'start';
break;
default:
cmd = 'xdg-open';
}
return cp.exec(cmd + ' ' + url);
}
let tscVersion: string = undefined;
try {
let out = cp.execSync('tsc --version', { encoding: 'utf8' });
if (out) {
let matches = out.trim().match(/Version\s*(.*)$/);
if (matches && matches.length === 2) {
tscVersion = matches[1];
}
}
} catch (error) {
}
if (tscVersion && tscVersion !== this.client.apiVersion.versionString) {
window.showInformationMessage<MyMessageItem>(
localize('versionMismatch', 'Version mismatch! global tsc ({0}) != VS Code\'s language service ({1}). Inconsistent compile errors might occur', tscVersion, this.client.apiVersion.versionString),
{
title: localize('moreInformation', 'More Information'),
id: 1
},
{
title: localize('doNotCheckAgain', 'Don\'t Check Again'),
id: 2
},
{
title: localize('close', 'Close'),
id: 3,
isCloseAffordance: true
}
).then((selected) => {
if (!selected || selected.id === 3) {
return;
}
switch (selected.id) {
case 1:
openUrl('http://go.microsoft.com/fwlink/?LinkId=826239');
break;
case 2:
const tsConfig = workspace.getConfiguration('typescript');
tsConfig.update(checkTscVersionSettingKey, false, true);
window.showInformationMessage(localize('updateTscCheck', 'Updated user setting \'typescript.check.tscVersion\' to false'));
break;
}
});
}
}
}

View file

@ -18,32 +18,36 @@ export interface ITypescriptServiceClientHost {
export class API {
private version: string;
private _version: string;
constructor(version: string) {
this.version = semver.valid(version);
if (!this.version) {
this.version = '1.0.0';
constructor(private _versionString: string) {
this._version = semver.valid(_versionString);
if (!this._version) {
this._version = '1.0.0';
} else {
// Cut of any prerelease tag since we sometimes consume those
// on purpose.
let index = version.indexOf('-');
let index = _versionString.indexOf('-');
if (index >= 0) {
this.version = this.version.substr(0, index);
this._version = this._version.substr(0, index);
}
}
}
public get versionString(): string {
return this._versionString;
}
public has1xFeatures(): boolean {
return semver.gte(this.version, '1.0.0');
return semver.gte(this._version, '1.0.0');
}
public has203Features(): boolean {
return semver.gte(this.version, '2.0.3');
return semver.gte(this._version, '2.0.3');
}
public has206Features(): boolean {
return semver.gte(this.version, '2.0.6');
return semver.gte(this._version, '2.0.6');
}
}
@ -59,6 +63,7 @@ export interface ITypescriptServiceClient {
experimentalAutoBuild: boolean;
apiVersion: API;
checkGlobalTSCVersion: boolean;
execute(command: 'configure', args: Proto.ConfigureRequestArguments, token?: CancellationToken): Promise<Proto.ConfigureResponse>;
execute(command: 'open', args: Proto.OpenRequestArgs, expectedResult: boolean, token?: CancellationToken): Promise<any>;

View file

@ -77,23 +77,6 @@ interface MyMessageItem extends MessageItem {
id: MessageAction;
}
function openUrl(url: string) {
let cmd: string;
switch (process.platform) {
case 'darwin':
cmd = 'open';
break;
case 'win32':
cmd = 'start';
break;
default:
cmd = 'xdg-open';
}
return cp.exec(cmd + ' ' + url);
}
export default class TypeScriptServiceClient implements ITypescriptServiceClient {
private host: ITypescriptServiceClientHost;
@ -103,6 +86,7 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient
private _onReady: { promise: Promise<void>; resolve: () => void; reject: () => void; };
private tsdk: string;
private _checkGlobalTSCVersion: boolean;
private _experimentalAutoBuild: boolean;
private trace: Trace;
private _output: OutputChannel;
@ -148,6 +132,7 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient
this.tsdk = configuration.get<string>('typescript.tsdk', null);
this._experimentalAutoBuild = false; // configuration.get<boolean>('typescript.tsserver.experimentalAutoBuild', false);
this._apiVersion = new API('1.0.0');
this._checkGlobalTSCVersion = true;
this.trace = this.readTrace();
workspace.onDidChangeConfiguration(() => {
this.trace = this.readTrace();
@ -182,6 +167,10 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient
return this._experimentalAutoBuild;
}
public get checkGlobalTSCVersion(): boolean {
return this._checkGlobalTSCVersion;
}
public get apiVersion(): API {
return this._apiVersion;
}
@ -280,11 +269,10 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient
private startService(resendModels: boolean = false): void {
let modulePath = path.join(__dirname, '..', 'node_modules', 'typescript', 'lib', 'tsserver.js');
let checkGlobalVersion = true;
let showVersionStatusItem = false;
if (this.tsdk) {
checkGlobalVersion = false;
this._checkGlobalTSCVersion = false;
if ((<any>path).isAbsolute(this.tsdk)) {
modulePath = path.join(this.tsdk, 'tsserver.js');
} else if (workspace.rootPath) {
@ -306,7 +294,7 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient
let localVersion = this.getTypeScriptVersion(localModulePath);
let shippedVersion = this.getTypeScriptVersion(modulePath);
if (localVersion && localVersion !== shippedVersion) {
checkGlobalVersion = false;
this._checkGlobalTSCVersion = false;
versionCheckPromise = window.showInformationMessage<MyMessageItem>(
localize(
'localTSFound',
@ -385,6 +373,8 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient
VersionStatus.enable(!!this.tsdk || showVersionStatusItem);
VersionStatus.setInfo(label, tooltip);
// This is backwards compatibility code to move the setting from the local
// store into the workspace setting file.
const doGlobalVersionCheckKey: string = 'doGlobalVersionCheck';
const globalStateValue = this.globalState.get(doGlobalVersionCheckKey, true);
const checkTscVersion = 'check.tscVersion';
@ -392,51 +382,6 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient
tsConfig.update(checkTscVersion, false, true);
this.globalState.update(doGlobalVersionCheckKey, true);
}
if (checkGlobalVersion && tsConfig.get(checkTscVersion)) {
let tscVersion: string = undefined;
try {
let out = cp.execSync('tsc --version', { encoding: 'utf8' });
if (out) {
let matches = out.trim().match(/Version\s*(.*)$/);
if (matches && matches.length === 2) {
tscVersion = matches[1];
}
}
} catch (error) {
}
if (tscVersion && tscVersion !== version) {
window.showInformationMessage<MyMessageItem>(
localize('versionMismatch', 'Version mismatch! global tsc ({0}) != VS Code\'s language service ({1}). Inconsistent compile errors might occur', tscVersion, version),
{
title: localize('moreInformation', 'More Information'),
id: 1
},
{
title: localize('doNotCheckAgain', 'Don\'t Check Again'),
id: 2
},
{
title: localize('close', 'Close'),
id: 3,
isCloseAffordance: true
}
).then((selected) => {
if (!selected || selected.id === 3) {
return;
}
switch (selected.id) {
case 1:
openUrl('http://go.microsoft.com/fwlink/?LinkId=826239');
break;
case 2:
tsConfig.update(checkTscVersion, false, true);
window.showInformationMessage(localize('updateTscCheck', 'Updated user setting \'typescript.check.tscVersion\' to false'));
this.globalState.update(doGlobalVersionCheckKey, false);
break;
}
});
}
}
try {
let options: electron.IForkOptions = {