diff --git a/build/gulpfile.editor.js b/build/gulpfile.editor.js index 0c7a37b1f76..1e492d0f5f8 100644 --- a/build/gulpfile.editor.js +++ b/build/gulpfile.editor.js @@ -28,7 +28,7 @@ var editorEntryPoints = [ name: 'vs/editor/editor.main', include: [], exclude: ['vs/css', 'vs/nls'], - prepend: ['out-build/vs/css.js', 'out-build/vs/nls.js'], + prepend: ['out-editor-build/vs/css.js', 'out-editor-build/vs/nls.js'], }, { name: 'vs/base/common/worker/simpleWorker', @@ -79,16 +79,21 @@ gulp.task('extract-editor-src', ['clean-editor-src'], function () { apiusages, extrausages ], + typings: [ + 'typings/lib.ie11_safe_es6.d.ts', + 'typings/thenable.d.ts', + 'typings/es6-promise.d.ts', + 'typings/require-monaco.d.ts', + 'vs/monaco.d.ts' + ], libs: [ - `lib.d.ts`, - `lib.es2015.collection.d.ts` + `lib.es5.d.ts`, + `lib.dom.d.ts`, + `lib.webworker.importscripts.d.ts` ], redirects: { 'vs/base/browser/ui/octiconLabel/octiconLabel': 'vs/base/browser/ui/octiconLabel/octiconLabel.mock', }, - compilerOptions: { - module: 2, // ModuleKind.AMD - }, shakeLevel: 2, // 0-Files, 1-InnerFile, 2-ClassMembers importIgnorePattern: /^vs\/css!/, destRoot: path.join(root, 'out-editor-src') @@ -108,6 +113,8 @@ gulp.task('optimize-editor', ['clean-optimized-editor', 'compile-editor-build'], loaderConfig: { paths: { 'vs': 'out-editor-build/vs', + 'vs/css': 'out-editor-build/vs/css.build', + 'vs/nls': 'out-editor-build/vs/nls.build', 'vscode': 'empty:' } }, @@ -125,7 +132,7 @@ gulp.task('clean-editor-esm', util.rimraf('out-editor-esm')); gulp.task('extract-editor-esm', ['clean-editor-esm', 'clean-editor-distro', 'extract-editor-src'], function () { standalone.createESMSourcesAndResources2({ srcFolder: './out-editor-src', - outFolder: './out-editor-esm/src', + outFolder: './out-editor-esm', outResourcesFolder: './out-monaco-editor-core/esm', ignores: [ 'inlineEntryPoint:0.ts', diff --git a/build/lib/bundle.js b/build/lib/bundle.js index a44db25afe8..4ea67389619 100644 --- a/build/lib/bundle.js +++ b/build/lib/bundle.js @@ -32,8 +32,12 @@ function bundle(entryPoints, config, callback) { var loader = loaderModule.exports; config.isBuild = true; config.paths = config.paths || {}; - config.paths['vs/nls'] = 'out-build/vs/nls.build'; - config.paths['vs/css'] = 'out-build/vs/css.build'; + if (!config.paths['vs/nls']) { + config.paths['vs/nls'] = 'out-build/vs/nls.build'; + } + if (!config.paths['vs/css']) { + config.paths['vs/css'] = 'out-build/vs/css.build'; + } loader.config(config); loader(['require'], function (localRequire) { var resolvePath = function (path) { diff --git a/build/lib/bundle.ts b/build/lib/bundle.ts index b83e4637892..562b050d1fd 100644 --- a/build/lib/bundle.ts +++ b/build/lib/bundle.ts @@ -123,8 +123,12 @@ export function bundle(entryPoints: IEntryPoint[], config: ILoaderConfig, callba const loader: any = loaderModule.exports; config.isBuild = true; config.paths = config.paths || {}; - config.paths['vs/nls'] = 'out-build/vs/nls.build'; - config.paths['vs/css'] = 'out-build/vs/css.build'; + if (!config.paths['vs/nls']) { + config.paths['vs/nls'] = 'out-build/vs/nls.build'; + } + if (!config.paths['vs/css']) { + config.paths['vs/css'] = 'out-build/vs/css.build'; + } loader.config(config); loader(['require'], (localRequire: any) => { diff --git a/build/lib/compilation.js b/build/lib/compilation.js index ae0726f273d..60fd1f7ddfb 100644 --- a/build/lib/compilation.js +++ b/build/lib/compilation.js @@ -4,23 +4,31 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); -var gulp = require("gulp"); -var tsb = require("gulp-tsb"); var es = require("event-stream"); -var watch = require('./watch'); -var nls = require("./nls"); -var util = require("./util"); -var reporter_1 = require("./reporter"); -var path = require("path"); +var fs = require("fs"); +var gulp = require("gulp"); var bom = require("gulp-bom"); var sourcemaps = require("gulp-sourcemaps"); +var tsb = require("gulp-tsb"); +var path = require("path"); var _ = require("underscore"); var monacodts = require("../monaco/api"); -var fs = require("fs"); +var nls = require("./nls"); +var reporter_1 = require("./reporter"); +var util = require("./util"); +var watch = require('./watch'); +var assign = require("object-assign"); var reporter = reporter_1.createReporter(); function getTypeScriptCompilerOptions(src) { var rootDir = path.join(__dirname, "../../" + src); - var options = require("../../" + src + "/tsconfig.json").compilerOptions; + var tsconfig = require("../../" + src + "/tsconfig.json"); + var options; + if (tsconfig.extends) { + options = assign({}, require(path.join(rootDir, tsconfig.extends)).compilerOptions, tsconfig.compilerOptions); + } + else { + options = tsconfig.compilerOptions; + } options.verbose = false; options.sourceMap = true; if (process.env['VSCODE_NO_SOURCEMAP']) { // To be used by developers in a hurry diff --git a/build/lib/compilation.ts b/build/lib/compilation.ts index e945859bc56..21fbb6a7731 100644 --- a/build/lib/compilation.ts +++ b/build/lib/compilation.ts @@ -5,25 +5,32 @@ 'use strict'; -import * as gulp from 'gulp'; -import * as tsb from 'gulp-tsb'; import * as es from 'event-stream'; -const watch = require('./watch'); -import * as nls from './nls'; -import * as util from './util'; -import { createReporter } from './reporter'; -import * as path from 'path'; +import * as fs from 'fs'; +import * as gulp from 'gulp'; import * as bom from 'gulp-bom'; import * as sourcemaps from 'gulp-sourcemaps'; +import * as tsb from 'gulp-tsb'; +import * as path from 'path'; import * as _ from 'underscore'; import * as monacodts from '../monaco/api'; -import * as fs from 'fs'; +import * as nls from './nls'; +import { createReporter } from './reporter'; +import * as util from './util'; +const watch = require('./watch'); +import assign = require('object-assign'); const reporter = createReporter(); function getTypeScriptCompilerOptions(src: string) { const rootDir = path.join(__dirname, `../../${src}`); - const options = require(`../../${src}/tsconfig.json`).compilerOptions; + const tsconfig = require(`../../${src}/tsconfig.json`); + let options: { [key: string]: any }; + if (tsconfig.extends) { + options = assign({}, require(path.join(rootDir, tsconfig.extends)).compilerOptions, tsconfig.compilerOptions); + } else { + options = tsconfig.compilerOptions; + } options.verbose = false; options.sourceMap = true; if (process.env['VSCODE_NO_SOURCEMAP']) { // To be used by developers in a hurry diff --git a/build/lib/i18n.resources.json b/build/lib/i18n.resources.json index 9afcbb24891..204ea6beea6 100644 --- a/build/lib/i18n.resources.json +++ b/build/lib/i18n.resources.json @@ -78,10 +78,6 @@ "name": "vs/workbench/parts/logs", "project": "vscode-workbench" }, - { - "name": "vs/workbench/parts/navigation", - "project": "vscode-workbench" - }, { "name": "vs/workbench/parts/output", "project": "vscode-workbench" diff --git a/build/lib/standalone.js b/build/lib/standalone.js index 3e2bacc25d5..88fa28dbbcd 100644 --- a/build/lib/standalone.js +++ b/build/lib/standalone.js @@ -27,6 +27,13 @@ function writeFile(filePath, contents) { fs.writeFileSync(filePath, contents); } function extractEditor(options) { + var tsConfig = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.json')).toString()); + tsConfig.compilerOptions.noUnusedLocals = false; + tsConfig.compilerOptions.preserveConstEnums = false; + tsConfig.compilerOptions.declaration = false; + delete tsConfig.compilerOptions.types; + tsConfig.exclude = []; + options.compilerOptions = tsConfig.compilerOptions; var result = tss.shake(options); for (var fileName in result) { if (result.hasOwnProperty(fileName)) { @@ -73,25 +80,16 @@ function extractEditor(options) { } } } - var tsConfig = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.json')).toString()); - tsConfig.compilerOptions.noUnusedLocals = false; - tsConfig.compilerOptions.preserveConstEnums = false; - tsConfig.compilerOptions.declaration = false; writeOutputFile('tsconfig.json', JSON.stringify(tsConfig, null, '\t')); [ 'vs/css.build.js', 'vs/css.d.ts', 'vs/css.js', 'vs/loader.js', - 'vs/monaco.d.ts', 'vs/nls.build.js', 'vs/nls.d.ts', 'vs/nls.js', 'vs/nls.mock.ts', - 'typings/lib.ie11_safe_es6.d.ts', - 'typings/thenable.d.ts', - 'typings/es6-promise.d.ts', - 'typings/require.d.ts', ].forEach(copyFile); } exports.extractEditor = extractEditor; @@ -102,7 +100,7 @@ function createESMSourcesAndResources2(options) { var getDestAbsoluteFilePath = function (file) { var dest = options.renames[file.replace(/\\/g, '/')] || file; if (dest === 'tsconfig.json') { - return path.join(OUT_FOLDER, "../tsconfig.json"); + return path.join(OUT_FOLDER, "tsconfig.json"); } if (/\.ts$/.test(dest)) { return path.join(OUT_FOLDER, dest); @@ -117,11 +115,8 @@ function createESMSourcesAndResources2(options) { } if (file === 'tsconfig.json') { var tsConfig = JSON.parse(fs.readFileSync(path.join(SRC_FOLDER, file)).toString()); - tsConfig.compilerOptions.moduleResolution = undefined; - tsConfig.compilerOptions.baseUrl = undefined; tsConfig.compilerOptions.module = 'es6'; - tsConfig.compilerOptions.rootDir = 'src'; - tsConfig.compilerOptions.outDir = path.relative(path.dirname(OUT_FOLDER), OUT_RESOURCES_FOLDER); + tsConfig.compilerOptions.outDir = path.join(path.relative(OUT_FOLDER, OUT_RESOURCES_FOLDER), 'vs'); write(getDestAbsoluteFilePath(file), JSON.stringify(tsConfig, null, '\t')); continue; } diff --git a/build/lib/standalone.ts b/build/lib/standalone.ts index e68e10f740a..aba118ab529 100644 --- a/build/lib/standalone.ts +++ b/build/lib/standalone.ts @@ -31,6 +31,15 @@ function writeFile(filePath: string, contents: Buffer | string): void { } export function extractEditor(options: tss.ITreeShakingOptions & { destRoot: string }): void { + const tsConfig = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.json')).toString()); + tsConfig.compilerOptions.noUnusedLocals = false; + tsConfig.compilerOptions.preserveConstEnums = false; + tsConfig.compilerOptions.declaration = false; + delete tsConfig.compilerOptions.types; + tsConfig.exclude = []; + + options.compilerOptions = tsConfig.compilerOptions; + let result = tss.shake(options); for (let fileName in result) { if (result.hasOwnProperty(fileName)) { @@ -79,10 +88,6 @@ export function extractEditor(options: tss.ITreeShakingOptions & { destRoot: str } } - const tsConfig = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.json')).toString()); - tsConfig.compilerOptions.noUnusedLocals = false; - tsConfig.compilerOptions.preserveConstEnums = false; - tsConfig.compilerOptions.declaration = false; writeOutputFile('tsconfig.json', JSON.stringify(tsConfig, null, '\t')); [ @@ -90,15 +95,10 @@ export function extractEditor(options: tss.ITreeShakingOptions & { destRoot: str 'vs/css.d.ts', 'vs/css.js', 'vs/loader.js', - 'vs/monaco.d.ts', 'vs/nls.build.js', 'vs/nls.d.ts', 'vs/nls.js', 'vs/nls.mock.ts', - 'typings/lib.ie11_safe_es6.d.ts', - 'typings/thenable.d.ts', - 'typings/es6-promise.d.ts', - 'typings/require.d.ts', ].forEach(copyFile); } @@ -118,7 +118,7 @@ export function createESMSourcesAndResources2(options: IOptions2): void { const getDestAbsoluteFilePath = (file: string): string => { let dest = options.renames[file.replace(/\\/g, '/')] || file; if (dest === 'tsconfig.json') { - return path.join(OUT_FOLDER, `../tsconfig.json`); + return path.join(OUT_FOLDER, `tsconfig.json`); } if (/\.ts$/.test(dest)) { return path.join(OUT_FOLDER, dest); @@ -136,11 +136,8 @@ export function createESMSourcesAndResources2(options: IOptions2): void { if (file === 'tsconfig.json') { const tsConfig = JSON.parse(fs.readFileSync(path.join(SRC_FOLDER, file)).toString()); - tsConfig.compilerOptions.moduleResolution = undefined; - tsConfig.compilerOptions.baseUrl = undefined; tsConfig.compilerOptions.module = 'es6'; - tsConfig.compilerOptions.rootDir = 'src'; - tsConfig.compilerOptions.outDir = path.relative(path.dirname(OUT_FOLDER), OUT_RESOURCES_FOLDER); + tsConfig.compilerOptions.outDir = path.join(path.relative(OUT_FOLDER, OUT_RESOURCES_FOLDER), 'vs'); write(getDestAbsoluteFilePath(file), JSON.stringify(tsConfig, null, '\t')); continue; } diff --git a/build/lib/treeshaking.js b/build/lib/treeshaking.js index ca1f2156047..f383eb09597 100644 --- a/build/lib/treeshaking.js +++ b/build/lib/treeshaking.js @@ -14,8 +14,39 @@ var ShakeLevel; ShakeLevel[ShakeLevel["InnerFile"] = 1] = "InnerFile"; ShakeLevel[ShakeLevel["ClassMembers"] = 2] = "ClassMembers"; })(ShakeLevel = exports.ShakeLevel || (exports.ShakeLevel = {})); +function printDiagnostics(diagnostics) { + for (var i = 0; i < diagnostics.length; i++) { + var diag = diagnostics[i]; + var result = ''; + if (diag.file) { + result += diag.file.fileName + ": "; + } + if (diag.file && diag.start) { + var location_1 = diag.file.getLineAndCharacterOfPosition(diag.start); + result += "- " + (location_1.line + 1) + "," + location_1.character + " - "; + } + result += JSON.stringify(diag.messageText); + console.log(result); + } +} function shake(options) { var languageService = createTypeScriptLanguageService(options); + var program = languageService.getProgram(); + var globalDiagnostics = program.getGlobalDiagnostics(); + if (globalDiagnostics.length > 0) { + printDiagnostics(globalDiagnostics); + throw new Error("Compilation Errors encountered."); + } + var syntacticDiagnostics = program.getSyntacticDiagnostics(); + if (syntacticDiagnostics.length > 0) { + printDiagnostics(syntacticDiagnostics); + throw new Error("Compilation Errors encountered."); + } + var semanticDiagnostics = program.getSemanticDiagnostics(); + if (semanticDiagnostics.length > 0) { + printDiagnostics(semanticDiagnostics); + throw new Error("Compilation Errors encountered."); + } markNodes(languageService, options); return generateResult(languageService, options.shakeLevel); } @@ -28,13 +59,18 @@ function createTypeScriptLanguageService(options) { options.inlineEntryPoints.forEach(function (inlineEntryPoint, index) { FILES["inlineEntryPoint:" + index + ".ts"] = inlineEntryPoint; }); + // Add additional typings + options.typings.forEach(function (typing) { + var filePath = path.join(options.sourcesRoot, typing); + FILES[typing] = fs.readFileSync(filePath).toString(); + }); // Resolve libs var RESOLVED_LIBS = {}; options.libs.forEach(function (filename) { var filepath = path.join(TYPESCRIPT_LIB_FOLDER, filename); RESOLVED_LIBS["defaultLib:" + filename] = fs.readFileSync(filepath).toString(); }); - var host = new TypeScriptLanguageServiceHost(RESOLVED_LIBS, FILES, options.compilerOptions); + var host = new TypeScriptLanguageServiceHost(RESOLVED_LIBS, FILES, ts.convertCompilerOptionsFromJson(options.compilerOptions, "").options); return ts.createLanguageService(host); } /** @@ -57,7 +93,7 @@ function discoverAndReadFiles(options) { var dts_filename = path.join(options.sourcesRoot, moduleId + '.d.ts'); if (fs.existsSync(dts_filename)) { var dts_filecontents = fs.readFileSync(dts_filename).toString(); - FILES[moduleId + '.d.ts'] = dts_filecontents; + FILES[moduleId + ".d.ts"] = dts_filecontents; continue; } var ts_filename = void 0; @@ -81,7 +117,7 @@ function discoverAndReadFiles(options) { } enqueue(importedModuleId); } - FILES[moduleId + '.ts'] = ts_filecontents; + FILES[moduleId + ".ts"] = ts_filecontents; } return FILES; } @@ -517,68 +553,9 @@ function generateResult(languageService, shakeLevel) { * Returns the node's symbol and the `import` node (if the symbol resolved from a different module) */ function getRealNodeSymbol(checker, node) { - /** - * Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 } - */ - /* @internal */ - function getContainingObjectLiteralElement(node) { - switch (node.kind) { - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NumericLiteral: - if (node.parent.kind === ts.SyntaxKind.ComputedPropertyName) { - return ts.isObjectLiteralElement(node.parent.parent) ? node.parent.parent : undefined; - } - // falls through - case ts.SyntaxKind.Identifier: - return ts.isObjectLiteralElement(node.parent) && - (node.parent.parent.kind === ts.SyntaxKind.ObjectLiteralExpression || node.parent.parent.kind === ts.SyntaxKind.JsxAttributes) && - node.parent.name === node ? node.parent : undefined; - } - return undefined; - } - function getPropertySymbolsFromType(type, propName) { - function getTextOfPropertyName(name) { - function isStringOrNumericLiteral(node) { - var kind = node.kind; - return kind === ts.SyntaxKind.StringLiteral - || kind === ts.SyntaxKind.NumericLiteral; - } - switch (name.kind) { - case ts.SyntaxKind.Identifier: - return name.text; - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NumericLiteral: - return name.text; - case ts.SyntaxKind.ComputedPropertyName: - return isStringOrNumericLiteral(name.expression) ? name.expression.text : undefined; - } - } - var name = getTextOfPropertyName(propName); - if (name && type) { - var result = []; - var symbol_1 = type.getProperty(name); - if (type.flags & ts.TypeFlags.Union) { - for (var _i = 0, _a = type.types; _i < _a.length; _i++) { - var t = _a[_i]; - var symbol_2 = t.getProperty(name); - if (symbol_2) { - result.push(symbol_2); - } - } - return result; - } - if (symbol_1) { - result.push(symbol_1); - return result; - } - } - return undefined; - } - function getPropertySymbolsFromContextualType(typeChecker, node) { - var objectLiteral = node.parent; - var contextualType = typeChecker.getContextualType(objectLiteral); - return getPropertySymbolsFromType(contextualType, node.name); - } + var getPropertySymbolsFromContextualType = ts.getPropertySymbolsFromContextualType; + var getContainingObjectLiteralElement = ts.getContainingObjectLiteralElement; + var getNameFromPropertyName = ts.getNameFromPropertyName; // Go to the original declaration for cases: // // (1) when the aliased symbol was declared in the location(parent). @@ -606,8 +583,13 @@ function getRealNodeSymbol(checker, node) { return [null, null]; } } + var parent = node.parent; var symbol = checker.getSymbolAtLocation(node); var importNode = null; + // If this is an alias, and the request came at the declaration location + // get the aliased symbol instead. This allows for goto def on an import e.g. + // import {A, B} from "mod"; + // to jump to the implementation directly. if (symbol && symbol.flags & ts.SymbolFlags.Alias && shouldSkipAlias(node, symbol.declarations[0])) { var aliased = checker.getAliasedSymbol(symbol); if (aliased.declarations) { @@ -636,13 +618,22 @@ function getRealNodeSymbol(checker, node) { // pr/*destination*/op1: number // } // bar(({pr/*goto*/op1})=>{}); - if (ts.isPropertyName(node) && ts.isBindingElement(node.parent) && ts.isObjectBindingPattern(node.parent.parent) && - (node === (node.parent.propertyName || node.parent.name))) { - var type = checker.getTypeAtLocation(node.parent.parent); - if (type) { - var propSymbols = getPropertySymbolsFromType(type, node); - if (propSymbols) { - symbol = propSymbols[0]; + if (ts.isPropertyName(node) && ts.isBindingElement(parent) && ts.isObjectBindingPattern(parent.parent) && + (node === (parent.propertyName || parent.name))) { + var name_1 = getNameFromPropertyName(node); + var type = checker.getTypeAtLocation(parent.parent); + if (name_1 && type) { + if (type.isUnion()) { + var prop = type.types[0].getProperty(name_1); + if (prop) { + symbol = prop; + } + } + else { + var prop = type.getProperty(name_1); + if (prop) { + symbol = prop; + } } } } @@ -656,10 +647,13 @@ function getRealNodeSymbol(checker, node) { // function Foo(arg: Props) {} // Foo( { pr/*1*/op1: 10, prop2: false }) var element = getContainingObjectLiteralElement(node); - if (element && checker.getContextualType(element.parent)) { - var propertySymbols = getPropertySymbolsFromContextualType(checker, element); - if (propertySymbols) { - symbol = propertySymbols[0]; + if (element) { + var contextualType = element && checker.getContextualType(element.parent); + if (contextualType) { + var propertySymbols = getPropertySymbolsFromContextualType(element, checker, contextualType, /*unionSymbolOk*/ false); + if (propertySymbols) { + symbol = propertySymbols[0]; + } } } } diff --git a/build/lib/treeshaking.ts b/build/lib/treeshaking.ts index 13c74c086f0..3439b1437ac 100644 --- a/build/lib/treeshaking.ts +++ b/build/lib/treeshaking.ts @@ -36,10 +36,14 @@ export interface ITreeShakingOptions { * e.g. `lib.d.ts`, `lib.es2015.collection.d.ts` */ libs: string[]; + /** + * Other .d.ts files + */ + typings: string[]; /** * TypeScript compiler options. */ - compilerOptions: ts.CompilerOptions; + compilerOptions?: any; /** * The shake level to perform. */ @@ -56,8 +60,43 @@ export interface ITreeShakingResult { [file: string]: string; } +function printDiagnostics(diagnostics: ReadonlyArray): void { + for (let i = 0; i < diagnostics.length; i++) { + const diag = diagnostics[i]; + let result = ''; + if (diag.file) { + result += `${diag.file.fileName}: `; + } + if (diag.file && diag.start) { + let location = diag.file.getLineAndCharacterOfPosition(diag.start); + result += `- ${location.line + 1},${location.character} - ` + } + result += JSON.stringify(diag.messageText); + console.log(result); + } +} + export function shake(options: ITreeShakingOptions): ITreeShakingResult { const languageService = createTypeScriptLanguageService(options); + const program = languageService.getProgram()!; + + const globalDiagnostics = program.getGlobalDiagnostics(); + if (globalDiagnostics.length > 0) { + printDiagnostics(globalDiagnostics); + throw new Error(`Compilation Errors encountered.`); + } + + const syntacticDiagnostics = program.getSyntacticDiagnostics(); + if (syntacticDiagnostics.length > 0) { + printDiagnostics(syntacticDiagnostics); + throw new Error(`Compilation Errors encountered.`); + } + + const semanticDiagnostics = program.getSemanticDiagnostics(); + if (semanticDiagnostics.length > 0) { + printDiagnostics(semanticDiagnostics); + throw new Error(`Compilation Errors encountered.`); + } markNodes(languageService, options); @@ -74,6 +113,12 @@ function createTypeScriptLanguageService(options: ITreeShakingOptions): ts.Langu FILES[`inlineEntryPoint:${index}.ts`] = inlineEntryPoint; }); + // Add additional typings + options.typings.forEach((typing) => { + const filePath = path.join(options.sourcesRoot, typing); + FILES[typing] = fs.readFileSync(filePath).toString(); + }); + // Resolve libs const RESOLVED_LIBS: ILibMap = {}; options.libs.forEach((filename) => { @@ -81,7 +126,7 @@ function createTypeScriptLanguageService(options: ITreeShakingOptions): ts.Langu RESOLVED_LIBS[`defaultLib:${filename}`] = fs.readFileSync(filepath).toString(); }); - const host = new TypeScriptLanguageServiceHost(RESOLVED_LIBS, FILES, options.compilerOptions); + const host = new TypeScriptLanguageServiceHost(RESOLVED_LIBS, FILES, ts.convertCompilerOptionsFromJson(options.compilerOptions, ``).options); return ts.createLanguageService(host); } @@ -109,7 +154,7 @@ function discoverAndReadFiles(options: ITreeShakingOptions): IFileMap { const dts_filename = path.join(options.sourcesRoot, moduleId + '.d.ts'); if (fs.existsSync(dts_filename)) { const dts_filecontents = fs.readFileSync(dts_filename).toString(); - FILES[moduleId + '.d.ts'] = dts_filecontents; + FILES[`${moduleId}.d.ts`] = dts_filecontents; continue; } @@ -136,7 +181,7 @@ function discoverAndReadFiles(options: ITreeShakingOptions): IFileMap { enqueue(importedModuleId); } - FILES[moduleId + '.ts'] = ts_filecontents; + FILES[`${moduleId}.ts`] = ts_filecontents; } return FILES; @@ -636,73 +681,12 @@ function generateResult(languageService: ts.LanguageService, shakeLevel: ShakeLe * Returns the node's symbol and the `import` node (if the symbol resolved from a different module) */ function getRealNodeSymbol(checker: ts.TypeChecker, node: ts.Node): [ts.Symbol | null, ts.Declaration | null] { - /** - * Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 } - */ - /* @internal */ - function getContainingObjectLiteralElement(node: ts.Node): ts.ObjectLiteralElement | undefined { - switch (node.kind) { - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NumericLiteral: - if (node.parent.kind === ts.SyntaxKind.ComputedPropertyName) { - return ts.isObjectLiteralElement(node.parent.parent) ? node.parent.parent : undefined; - } - // falls through - case ts.SyntaxKind.Identifier: - return ts.isObjectLiteralElement(node.parent) && - (node.parent.parent.kind === ts.SyntaxKind.ObjectLiteralExpression || node.parent.parent.kind === ts.SyntaxKind.JsxAttributes) && - node.parent.name === node ? node.parent : undefined; - } - return undefined; - } - function getPropertySymbolsFromType(type: ts.Type, propName: ts.PropertyName) { - function getTextOfPropertyName(name: ts.PropertyName): string { - - function isStringOrNumericLiteral(node: ts.Node): node is ts.StringLiteral | ts.NumericLiteral { - const kind = node.kind; - return kind === ts.SyntaxKind.StringLiteral - || kind === ts.SyntaxKind.NumericLiteral; - } - - switch (name.kind) { - case ts.SyntaxKind.Identifier: - return name.text; - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NumericLiteral: - return name.text; - case ts.SyntaxKind.ComputedPropertyName: - return isStringOrNumericLiteral(name.expression) ? name.expression.text : undefined!; - } - } - - const name = getTextOfPropertyName(propName); - if (name && type) { - const result: ts.Symbol[] = []; - const symbol = type.getProperty(name); - if (type.flags & ts.TypeFlags.Union) { - for (const t of (type).types) { - const symbol = t.getProperty(name); - if (symbol) { - result.push(symbol); - } - } - return result; - } - - if (symbol) { - result.push(symbol); - return result; - } - } - return undefined; - } - - function getPropertySymbolsFromContextualType(typeChecker: ts.TypeChecker, node: ts.ObjectLiteralElement): ts.Symbol[] { - const objectLiteral = node.parent; - const contextualType = typeChecker.getContextualType(objectLiteral)!; - return getPropertySymbolsFromType(contextualType, node.name!)!; - } + // Use some TypeScript internals to avoid code duplication + type ObjectLiteralElementWithName = ts.ObjectLiteralElement & { name: ts.PropertyName; parent: ts.ObjectLiteralExpression | ts.JsxAttributes }; + const getPropertySymbolsFromContextualType: (node: ObjectLiteralElementWithName, checker: ts.TypeChecker, contextualType: ts.Type, unionSymbolOk: boolean) => ReadonlyArray = (ts).getPropertySymbolsFromContextualType; + const getContainingObjectLiteralElement: (node: ts.Node) => ObjectLiteralElementWithName | undefined = (ts).getContainingObjectLiteralElement; + const getNameFromPropertyName: (name: ts.PropertyName) => string | undefined = (ts).getNameFromPropertyName; // Go to the original declaration for cases: // @@ -733,8 +717,14 @@ function getRealNodeSymbol(checker: ts.TypeChecker, node: ts.Node): [ts.Symbol | } } + const { parent } = node; + let symbol = checker.getSymbolAtLocation(node); let importNode: ts.Declaration | null = null; + // If this is an alias, and the request came at the declaration location + // get the aliased symbol instead. This allows for goto def on an import e.g. + // import {A, B} from "mod"; + // to jump to the implementation directly. if (symbol && symbol.flags & ts.SymbolFlags.Alias && shouldSkipAlias(node, symbol.declarations[0])) { const aliased = checker.getAliasedSymbol(symbol); if (aliased.declarations) { @@ -765,13 +755,21 @@ function getRealNodeSymbol(checker: ts.TypeChecker, node: ts.Node): [ts.Symbol | // pr/*destination*/op1: number // } // bar(({pr/*goto*/op1})=>{}); - if (ts.isPropertyName(node) && ts.isBindingElement(node.parent) && ts.isObjectBindingPattern(node.parent.parent) && - (node === (node.parent.propertyName || node.parent.name))) { - const type = checker.getTypeAtLocation(node.parent.parent); - if (type) { - const propSymbols = getPropertySymbolsFromType(type, node); - if (propSymbols) { - symbol = propSymbols[0]; + if (ts.isPropertyName(node) && ts.isBindingElement(parent) && ts.isObjectBindingPattern(parent.parent) && + (node === (parent.propertyName || parent.name))) { + const name = getNameFromPropertyName(node); + const type = checker.getTypeAtLocation(parent.parent); + if (name && type) { + if (type.isUnion()) { + const prop = type.types[0].getProperty(name); + if (prop) { + symbol = prop; + } + } else { + const prop = type.getProperty(name); + if (prop) { + symbol = prop; + } } } } @@ -786,10 +784,13 @@ function getRealNodeSymbol(checker: ts.TypeChecker, node: ts.Node): [ts.Symbol | // function Foo(arg: Props) {} // Foo( { pr/*1*/op1: 10, prop2: false }) const element = getContainingObjectLiteralElement(node); - if (element && checker.getContextualType(element.parent as ts.Expression)) { - const propertySymbols = getPropertySymbolsFromContextualType(checker, element); - if (propertySymbols) { - symbol = propertySymbols[0]; + if (element) { + const contextualType = element && checker.getContextualType(element.parent); + if (contextualType) { + const propertySymbols = getPropertySymbolsFromContextualType(element, checker, contextualType, /*unionSymbolOk*/ false); + if (propertySymbols) { + symbol = propertySymbols[0]; + } } } } diff --git a/build/monaco/api.js b/build/monaco/api.js index f411ab4a566..51e22fd83c8 100644 --- a/build/monaco/api.js +++ b/build/monaco/api.js @@ -241,7 +241,7 @@ function generateDeclarationFile(out, inputFiles, recipe) { usage.push("var b;"); var generateUsageImport = function (moduleId) { var importName = 'm' + (++usageCounter); - usageImports.push("import * as " + importName + " from '" + moduleId.replace(/\.d\.ts$/, '') + "';"); + usageImports.push("import * as " + importName + " from './" + moduleId.replace(/\.d\.ts$/, '') + "';"); return importName; }; lines.forEach(function (line) { diff --git a/build/monaco/api.ts b/build/monaco/api.ts index 8c9e2b03890..ec30cc00c48 100644 --- a/build/monaco/api.ts +++ b/build/monaco/api.ts @@ -281,7 +281,7 @@ function generateDeclarationFile(out: string, inputFiles: { [file: string]: stri const generateUsageImport = (moduleId: string) => { let importName = 'm' + (++usageCounter); - usageImports.push(`import * as ${importName} from '${moduleId.replace(/\.d\.ts$/, '')}';`); + usageImports.push(`import * as ${importName} from './${moduleId.replace(/\.d\.ts$/, '')}';`); return importName; }; diff --git a/build/monaco/monaco.usage.recipe b/build/monaco/monaco.usage.recipe index beaad500aad..663f7b7cc26 100644 --- a/build/monaco/monaco.usage.recipe +++ b/build/monaco/monaco.usage.recipe @@ -1,19 +1,19 @@ // This file is adding references to various symbols which should not be removed via tree shaking -import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; -import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; -import { IHighlight } from 'vs/base/parts/quickopen/browser/quickOpenModel'; -import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge'; -import { SimpleWorkerClient, create as create1 } from 'vs/base/common/worker/simpleWorker'; -import { create as create2 } from 'vs/editor/common/services/editorSimpleWorker'; -import { QuickOpenWidget } from 'vs/base/parts/quickopen/browser/quickOpenWidget'; -import { SyncDescriptor0, SyncDescriptor1, SyncDescriptor2, SyncDescriptor3, SyncDescriptor4, SyncDescriptor5, SyncDescriptor6, SyncDescriptor7, SyncDescriptor8 } from 'vs/platform/instantiation/common/descriptors'; -import { PolyfillPromise } from 'vs/base/common/winjs.polyfill.promise'; -import { DiffNavigator } from 'vs/editor/browser/widget/diffNavigator'; -import * as editorAPI from 'vs/editor/editor.api'; +import { ServiceIdentifier } from './vs/platform/instantiation/common/instantiation'; +import { IContextViewService } from './vs/platform/contextview/browser/contextView'; +import { IHighlight } from './vs/base/parts/quickopen/browser/quickOpenModel'; +import { IWorkspaceContextService } from './vs/platform/workspace/common/workspace'; +import { IEnvironmentService } from './vs/platform/environment/common/environment'; +import { CountBadge } from './vs/base/browser/ui/countBadge/countBadge'; +import { SimpleWorkerClient, create as create1 } from './vs/base/common/worker/simpleWorker'; +import { create as create2 } from './vs/editor/common/services/editorSimpleWorker'; +import { QuickOpenWidget } from './vs/base/parts/quickopen/browser/quickOpenWidget'; +import { SyncDescriptor0, SyncDescriptor1, SyncDescriptor2, SyncDescriptor3, SyncDescriptor4, SyncDescriptor5, SyncDescriptor6, SyncDescriptor7, SyncDescriptor8 } from './vs/platform/instantiation/common/descriptors'; +import { PolyfillPromise } from './vs/base/common/winjs.polyfill.promise'; +import { DiffNavigator } from './vs/editor/browser/widget/diffNavigator'; +import * as editorAPI from './vs/editor/editor.api'; (function () { var a: any; diff --git a/build/package.json b/build/package.json index 3d95c6d0315..e0163836801 100644 --- a/build/package.json +++ b/build/package.json @@ -17,7 +17,7 @@ "@types/gulp-uglify": "^3.0.5", "@types/gulp-util": "^3.0.34", "@types/mime": "0.0.29", - "@types/minimatch": "^2.0.29", + "@types/minimatch": "^3.0.3", "@types/node": "8.0.33", "@types/pump": "^1.0.1", "@types/request": "^2.47.0", @@ -35,6 +35,7 @@ "mime": "^1.3.4", "minimist": "^1.2.0", "request": "^2.85.0", + "typescript": "3.1.1", "xml2js": "^0.4.17" }, "scripts": { @@ -43,4 +44,4 @@ "postinstall": "npm run compile", "npmCheckJs": "tsc --noEmit" } -} \ No newline at end of file +} diff --git a/build/tfs/darwin/continuous-build-darwin.yml b/build/tfs/darwin/continuous-build-darwin.yml index fb753fdded1..28e2a6079ab 100644 --- a/build/tfs/darwin/continuous-build-darwin.yml +++ b/build/tfs/darwin/continuous-build-darwin.yml @@ -17,6 +17,9 @@ steps: - script: | yarn monaco-compile-check displayName: Run Monaco Editor Checks +- script: | + yarn strict-null-check + displayName: Run Strict Null Checks - script: | yarn compile displayName: Compile Sources diff --git a/build/tfs/darwin/product-build-darwin.yml b/build/tfs/darwin/product-build-darwin.yml index 7911a60817d..f5520d06036 100644 --- a/build/tfs/darwin/product-build-darwin.yml +++ b/build/tfs/darwin/product-build-darwin.yml @@ -13,6 +13,7 @@ steps: yarn yarn gulp -- hygiene yarn monaco-compile-check + yarn strict-null-check VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" yarn gulp -- mixin node build/tfs/common/installDistro.js node build/lib/builtInExtensions.js diff --git a/build/tfs/linux/continuous-build-linux.yml b/build/tfs/linux/continuous-build-linux.yml index 1ec363a4066..459b82b9a39 100644 --- a/build/tfs/linux/continuous-build-linux.yml +++ b/build/tfs/linux/continuous-build-linux.yml @@ -27,6 +27,9 @@ steps: - script: | yarn monaco-compile-check displayName: Run Monaco Editor Checks +- script: | + yarn strict-null-check + displayName: Run Strict Null Checks - script: | yarn compile displayName: Compile Sources diff --git a/build/tfs/linux/product-build-linux.yml b/build/tfs/linux/product-build-linux.yml index 24835a59ca6..7a8c637ef84 100644 --- a/build/tfs/linux/product-build-linux.yml +++ b/build/tfs/linux/product-build-linux.yml @@ -18,6 +18,7 @@ steps: CHILD_CONCURRENCY=1 yarn npm run gulp -- hygiene npm run monaco-compile-check + npm run strict-null-check VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- mixin node build/tfs/common/installDistro.js node build/lib/builtInExtensions.js diff --git a/build/tfs/win32/continuous-build-win32.yml b/build/tfs/win32/continuous-build-win32.yml index 83e56327fa1..0df397a0a6a 100644 --- a/build/tfs/win32/continuous-build-win32.yml +++ b/build/tfs/win32/continuous-build-win32.yml @@ -21,6 +21,9 @@ steps: - powershell: | yarn monaco-compile-check displayName: Run Monaco Editor Checks +- script: | + yarn strict-null-check + displayName: Run Strict Null Checks - powershell: | yarn compile displayName: Compile Sources diff --git a/build/tfs/win32/product-build-win32.yml b/build/tfs/win32/product-build-win32.yml index 0baed977782..9dd2d4c6516 100644 --- a/build/tfs/win32/product-build-win32.yml +++ b/build/tfs/win32/product-build-win32.yml @@ -22,6 +22,7 @@ steps: exec { yarn } exec { npm run gulp -- hygiene } exec { npm run monaco-compile-check } + exec { npm run strict-null-check } exec { npm run gulp -- mixin } exec { node build/tfs/common/installDistro.js } exec { node build/lib/builtInExtensions.js } diff --git a/build/yarn.lock b/build/yarn.lock index 8931ea7f3cf..d107c379047 100644 --- a/build/yarn.lock +++ b/build/yarn.lock @@ -156,16 +156,11 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-0.0.29.tgz#fbcfd330573b912ef59eeee14602bface630754b" integrity sha1-+8/TMFc7kS71nu7hRgK/rOYwdUs= -"@types/minimatch@*": +"@types/minimatch@*", "@types/minimatch@^3.0.3": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== -"@types/minimatch@^2.0.29": - version "2.0.29" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-2.0.29.tgz#5002e14f75e2d71e564281df0431c8c1b4a2a36a" - integrity sha1-UALhT3Xi1x5WQoHfBDHIwbSio2o= - "@types/node@*": version "8.0.51" resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.51.tgz#b31d716fb8d58eeb95c068a039b9b6292817d5fb" @@ -1493,6 +1488,11 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= +typescript@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.1.1.tgz#3362ba9dd1e482ebb2355b02dfe8bcd19a2c7c96" + integrity sha512-Veu0w4dTc/9wlWNf2jeRInNodKlcdLgemvPsrNpfu5Pq39sgfFjvIIgTsvUHCoLBnMhPoUA+tFxsXjU6VexVRQ== + underscore@1.8.3, underscore@~1.8.3: version "1.8.3" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" diff --git a/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json b/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json index 1103d7e06e8..c74fb3ba70e 100644 --- a/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json +++ b/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/microsoft/vscode-markdown-tm-grammar/commit/0bd394a33046eeb204a9ebebdffb113d39587591", + "version": "https://github.com/microsoft/vscode-markdown-tm-grammar/commit/ee6a11d0bbbe8ef6bcf8e664f446c00fb14212f2", "name": "Markdown", "scopeName": "text.html.markdown", "patterns": [ @@ -2469,7 +2469,7 @@ "2": { "name": "string.other.link.title.markdown" }, - "4": { + "3": { "name": "punctuation.definition.string.end.markdown" } }, diff --git a/extensions/package.json b/extensions/package.json index 5d1eaf63e22..10a06e899b4 100644 --- a/extensions/package.json +++ b/extensions/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "description": "Dependencies shared by all extensions", "dependencies": { - "typescript": "3.1.2" + "typescript": "3.1.3" }, "scripts": { "postinstall": "node ./postinstall" diff --git a/extensions/yarn.lock b/extensions/yarn.lock index fa9bc190628..0630b4a19f8 100644 --- a/extensions/yarn.lock +++ b/extensions/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -typescript@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.1.2.tgz#c03a5d16f30bb60ad8bb6fe8e7cb212eedeec950" - integrity sha512-gOoGJWbNnFAfP9FlrSV63LYD5DJqYJHG5ky1kOXSl3pCImn4rqWy/flyq1BRd4iChQsoCqjbQaqtmXO4yCVPCA== +typescript@3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.1.3.tgz#01b70247a6d3c2467f70c45795ef5ea18ce191d5" + integrity sha512-+81MUSyX+BaSo+u2RbozuQk/UWx6hfG0a5gHu4ANEM4sU96XbuIyAB+rWBW1u70c6a5QuZfuYICn3s2UjuHUpA== diff --git a/package.json b/package.json index 8a3213512a5..853569a7249 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.29.0", - "distro": "d880cac56e2f97abfbd0a6b8388caebfa96bb40c", + "distro": "41eb7ae09bf97fe9448a168eb37838124a2a3695", "author": { "name": "Microsoft Corporation" }, @@ -22,7 +22,8 @@ "update-localization-extension": "node build/npm/update-localization-extension.js", "smoketest": "cd test/smoke && node test/index.js", "monaco-compile-check": "tsc -p src/tsconfig.monaco.json --noEmit", - "download-builtin-extensions": "node build/lib/builtInExtensions.js" + "download-builtin-extensions": "node build/lib/builtInExtensions.js", + "strict-null-check": "tsc -p src/tsconfig.strictNullChecks.json" }, "dependencies": { "applicationinsights": "1.0.5", @@ -50,7 +51,7 @@ "vscode-nsfw": "1.0.17", "vscode-ripgrep": "^1.2.2", "vscode-textmate": "^4.0.1", - "vscode-xterm": "3.9.0-beta5", + "vscode-xterm": "3.9.0-beta7", "winreg": "^1.2.4", "yauzl": "^2.9.1", "yazl": "^2.4.3" @@ -107,7 +108,7 @@ "lazy.js": "^0.4.2", "merge-options": "^1.0.1", "mime": "^1.4.1", - "minimatch": "^2.0.10", + "minimatch": "^3.0.4", "mkdirp": "^0.5.0", "mocha": "^2.2.5", "mocha-junit-reporter": "^1.17.0", diff --git a/resources/darwin/bat.icns b/resources/darwin/bat.icns index 35d48dc518e..b5f6d28e084 100644 Binary files a/resources/darwin/bat.icns and b/resources/darwin/bat.icns differ diff --git a/resources/darwin/bower.icns b/resources/darwin/bower.icns index 84db7801ba3..d8d0930bb0d 100644 Binary files a/resources/darwin/bower.icns and b/resources/darwin/bower.icns differ diff --git a/resources/darwin/c.icns b/resources/darwin/c.icns index 35a7e21b99f..139975ddc8e 100644 Binary files a/resources/darwin/c.icns and b/resources/darwin/c.icns differ diff --git a/resources/darwin/config.icns b/resources/darwin/config.icns index 31684a274ee..68f6631a268 100644 Binary files a/resources/darwin/config.icns and b/resources/darwin/config.icns differ diff --git a/resources/darwin/cpp.icns b/resources/darwin/cpp.icns index d681e4592db..b19f43ad371 100644 Binary files a/resources/darwin/cpp.icns and b/resources/darwin/cpp.icns differ diff --git a/resources/darwin/csharp.icns b/resources/darwin/csharp.icns index 627968fe5cd..763356d81c2 100644 Binary files a/resources/darwin/csharp.icns and b/resources/darwin/csharp.icns differ diff --git a/resources/darwin/css.icns b/resources/darwin/css.icns index 379d89b9a4c..47967529b7e 100644 Binary files a/resources/darwin/css.icns and b/resources/darwin/css.icns differ diff --git a/resources/darwin/default.icns b/resources/darwin/default.icns index dd176ef824e..9bca8a6634a 100644 Binary files a/resources/darwin/default.icns and b/resources/darwin/default.icns differ diff --git a/resources/darwin/go.icns b/resources/darwin/go.icns index 133998682eb..daf31d3fecb 100644 Binary files a/resources/darwin/go.icns and b/resources/darwin/go.icns differ diff --git a/resources/darwin/html.icns b/resources/darwin/html.icns index 65de27a8467..24ac7bcd3e2 100644 Binary files a/resources/darwin/html.icns and b/resources/darwin/html.icns differ diff --git a/resources/darwin/jade.icns b/resources/darwin/jade.icns index 0523101dac4..a29e343f391 100644 Binary files a/resources/darwin/jade.icns and b/resources/darwin/jade.icns differ diff --git a/resources/darwin/java.icns b/resources/darwin/java.icns index 75b3c354529..e999d6093fc 100644 Binary files a/resources/darwin/java.icns and b/resources/darwin/java.icns differ diff --git a/resources/darwin/javascript.icns b/resources/darwin/javascript.icns index a5150d9b121..7f88645ec27 100644 Binary files a/resources/darwin/javascript.icns and b/resources/darwin/javascript.icns differ diff --git a/resources/darwin/json.icns b/resources/darwin/json.icns index d59ae79ce10..634147ef9d0 100644 Binary files a/resources/darwin/json.icns and b/resources/darwin/json.icns differ diff --git a/resources/darwin/less.icns b/resources/darwin/less.icns index 7b8184f1c99..93687eb9428 100644 Binary files a/resources/darwin/less.icns and b/resources/darwin/less.icns differ diff --git a/resources/darwin/markdown.icns b/resources/darwin/markdown.icns index 13f2d05288f..3f4cb3bb462 100644 Binary files a/resources/darwin/markdown.icns and b/resources/darwin/markdown.icns differ diff --git a/resources/darwin/php.icns b/resources/darwin/php.icns index 17567107ae7..1990ad3b39c 100644 Binary files a/resources/darwin/php.icns and b/resources/darwin/php.icns differ diff --git a/resources/darwin/powershell.icns b/resources/darwin/powershell.icns index 07a1d37935d..f6b6bd01cce 100644 Binary files a/resources/darwin/powershell.icns and b/resources/darwin/powershell.icns differ diff --git a/resources/darwin/python.icns b/resources/darwin/python.icns index dfc70744e00..88757356d1c 100644 Binary files a/resources/darwin/python.icns and b/resources/darwin/python.icns differ diff --git a/resources/darwin/react.icns b/resources/darwin/react.icns index 28cd4f4deda..c76d537658d 100644 Binary files a/resources/darwin/react.icns and b/resources/darwin/react.icns differ diff --git a/resources/darwin/ruby.icns b/resources/darwin/ruby.icns index 68f61162d25..07f70cc1d9f 100644 Binary files a/resources/darwin/ruby.icns and b/resources/darwin/ruby.icns differ diff --git a/resources/darwin/sass.icns b/resources/darwin/sass.icns index 08f25da444f..d03b5e6d721 100644 Binary files a/resources/darwin/sass.icns and b/resources/darwin/sass.icns differ diff --git a/resources/darwin/shell.icns b/resources/darwin/shell.icns index b6ff58f8f2e..e1ee594fbf5 100644 Binary files a/resources/darwin/shell.icns and b/resources/darwin/shell.icns differ diff --git a/resources/darwin/sql.icns b/resources/darwin/sql.icns index de019a4a6da..3333be0926c 100644 Binary files a/resources/darwin/sql.icns and b/resources/darwin/sql.icns differ diff --git a/resources/darwin/typescript.icns b/resources/darwin/typescript.icns index f9dafb75d64..473d1dd71e8 100644 Binary files a/resources/darwin/typescript.icns and b/resources/darwin/typescript.icns differ diff --git a/resources/darwin/vue.icns b/resources/darwin/vue.icns index aeeaf6389fd..97384632aa6 100644 Binary files a/resources/darwin/vue.icns and b/resources/darwin/vue.icns differ diff --git a/resources/darwin/xml.icns b/resources/darwin/xml.icns index cf83783fc36..d99be4ed742 100644 Binary files a/resources/darwin/xml.icns and b/resources/darwin/xml.icns differ diff --git a/resources/darwin/yaml.icns b/resources/darwin/yaml.icns index a331a43da04..f4d6c59bdc9 100644 Binary files a/resources/darwin/yaml.icns and b/resources/darwin/yaml.icns differ diff --git a/resources/win32/bower.ico b/resources/win32/bower.ico index 38dc21015c9..f00c8218e70 100644 Binary files a/resources/win32/bower.ico and b/resources/win32/bower.ico differ diff --git a/resources/win32/c.ico b/resources/win32/c.ico index ea9211b2ee0..59e34e3ebc7 100644 Binary files a/resources/win32/c.ico and b/resources/win32/c.ico differ diff --git a/resources/win32/config.ico b/resources/win32/config.ico index 0bd8377673d..c82a372dedf 100644 Binary files a/resources/win32/config.ico and b/resources/win32/config.ico differ diff --git a/resources/win32/cpp.ico b/resources/win32/cpp.ico index 56ebbe66804..cd2af5770f1 100644 Binary files a/resources/win32/cpp.ico and b/resources/win32/cpp.ico differ diff --git a/resources/win32/csharp.ico b/resources/win32/csharp.ico index 99c0495d103..a8e843b5a08 100644 Binary files a/resources/win32/csharp.ico and b/resources/win32/csharp.ico differ diff --git a/resources/win32/css.ico b/resources/win32/css.ico index 67e4f41b330..1ecd3dc373e 100644 Binary files a/resources/win32/css.ico and b/resources/win32/css.ico differ diff --git a/resources/win32/default.ico b/resources/win32/default.ico index 605d7a75279..6f012d78249 100644 Binary files a/resources/win32/default.ico and b/resources/win32/default.ico differ diff --git a/resources/win32/go.ico b/resources/win32/go.ico index 0e30b92207b..f2ec069781a 100644 Binary files a/resources/win32/go.ico and b/resources/win32/go.ico differ diff --git a/resources/win32/html.ico b/resources/win32/html.ico index c381d54da8e..ea51ce4ce8d 100644 Binary files a/resources/win32/html.ico and b/resources/win32/html.ico differ diff --git a/resources/win32/jade.ico b/resources/win32/jade.ico index 471d0682a91..14938b2aeeb 100644 Binary files a/resources/win32/jade.ico and b/resources/win32/jade.ico differ diff --git a/resources/win32/java.ico b/resources/win32/java.ico index f97eba41d95..7ceb02ef829 100644 Binary files a/resources/win32/java.ico and b/resources/win32/java.ico differ diff --git a/resources/win32/javascript.ico b/resources/win32/javascript.ico index 2e647e3c85e..6bc6e5b06b1 100644 Binary files a/resources/win32/javascript.ico and b/resources/win32/javascript.ico differ diff --git a/resources/win32/json.ico b/resources/win32/json.ico index 63412409dd7..afc588e767d 100644 Binary files a/resources/win32/json.ico and b/resources/win32/json.ico differ diff --git a/resources/win32/less.ico b/resources/win32/less.ico index f27700612dc..f8967d77e17 100644 Binary files a/resources/win32/less.ico and b/resources/win32/less.ico differ diff --git a/resources/win32/markdown.ico b/resources/win32/markdown.ico index 88d54320a31..ad5992ffa9b 100644 Binary files a/resources/win32/markdown.ico and b/resources/win32/markdown.ico differ diff --git a/resources/win32/php.ico b/resources/win32/php.ico index 9cbee6d0252..5cdaff2fabf 100644 Binary files a/resources/win32/php.ico and b/resources/win32/php.ico differ diff --git a/resources/win32/powershell.ico b/resources/win32/powershell.ico index 26648c41427..12c268824e6 100644 Binary files a/resources/win32/powershell.ico and b/resources/win32/powershell.ico differ diff --git a/resources/win32/python.ico b/resources/win32/python.ico index 00aea872f14..c07947dfa3a 100644 Binary files a/resources/win32/python.ico and b/resources/win32/python.ico differ diff --git a/resources/win32/react.ico b/resources/win32/react.ico index 42461836ed0..06d14fead31 100644 Binary files a/resources/win32/react.ico and b/resources/win32/react.ico differ diff --git a/resources/win32/ruby.ico b/resources/win32/ruby.ico index f5e93e1e6b6..f82c3c4aa5c 100644 Binary files a/resources/win32/ruby.ico and b/resources/win32/ruby.ico differ diff --git a/resources/win32/sass.ico b/resources/win32/sass.ico index 44d5fe1b050..641ef7ff6d4 100644 Binary files a/resources/win32/sass.ico and b/resources/win32/sass.ico differ diff --git a/resources/win32/shell.ico b/resources/win32/shell.ico index ac68bc2f62f..b1e4d94a4d4 100644 Binary files a/resources/win32/shell.ico and b/resources/win32/shell.ico differ diff --git a/resources/win32/sql.ico b/resources/win32/sql.ico index 6ae7af9ae16..89900fbcd78 100644 Binary files a/resources/win32/sql.ico and b/resources/win32/sql.ico differ diff --git a/resources/win32/typescript.ico b/resources/win32/typescript.ico index 539baf73e96..ab9dc0348a0 100644 Binary files a/resources/win32/typescript.ico and b/resources/win32/typescript.ico differ diff --git a/resources/win32/vue.ico b/resources/win32/vue.ico index 681118e8c75..a31853907d0 100644 Binary files a/resources/win32/vue.ico and b/resources/win32/vue.ico differ diff --git a/resources/win32/xml.ico b/resources/win32/xml.ico index a4fd7617251..419de1049fd 100644 Binary files a/resources/win32/xml.ico and b/resources/win32/xml.ico differ diff --git a/resources/win32/yaml.ico b/resources/win32/yaml.ico index 4774cdba2f2..b1d590d2724 100644 Binary files a/resources/win32/yaml.ico and b/resources/win32/yaml.ico differ diff --git a/src/tsconfig.base.json b/src/tsconfig.base.json new file mode 100644 index 00000000000..2235d2eefa5 --- /dev/null +++ b/src/tsconfig.base.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "module": "amd", + "moduleResolution": "node", + "noImplicitAny": false, + "target": "es5", + "experimentalDecorators": true, + "noImplicitReturns": true, + "noUnusedLocals": true, + "noImplicitThis": true, + "alwaysStrict": true, + "baseUrl": ".", + "paths": { + "vs/*": [ + "./vs/*" + ] + }, + "types": [ + "keytar", + "minimist", + "mocha", + "semver", + "sinon", + "winreg" + ] + } +} \ No newline at end of file diff --git a/src/tsconfig.json b/src/tsconfig.json index c5a31a458f8..6f552e5ca05 100644 --- a/src/tsconfig.json +++ b/src/tsconfig.json @@ -1,33 +1,11 @@ { + "extends": "./tsconfig.base.json", "compilerOptions": { - "module": "amd", - "moduleResolution": "node", - "noImplicitAny": false, "removeComments": false, "preserveConstEnums": true, - "target": "es5", "sourceMap": false, - "experimentalDecorators": true, "declaration": true, - "noImplicitReturns": true, - "noUnusedLocals": true, - "noImplicitThis": true, - "alwaysStrict": true, - "baseUrl": ".", - "outDir": "../out", - "paths": { - "vs/*": [ - "./vs/*" - ] - }, - "types": [ - "keytar", - "minimist", - "mocha", - "semver", - "sinon", - "winreg" - ] + "outDir": "../out" }, "include": [ "./typings", diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json new file mode 100644 index 00000000000..43c3c987864 --- /dev/null +++ b/src/tsconfig.strictNullChecks.json @@ -0,0 +1,273 @@ +{ + "extends": "./tsconfig.base.json", + "compilerOptions": { + "noEmit": true, + "strictNullChecks": true + }, + "include": [ + "./typings", + "./vs/base/browser/browser.ts", + "./vs/base/browser/dom.ts", + "./vs/base/browser/event.ts", + "./vs/base/browser/history.ts", + "./vs/base/browser/iframe.ts", + "./vs/base/browser/keyboardEvent.ts", + "./vs/base/browser/mouseEvent.ts", + "./vs/base/browser/ui/list/splice.ts", + "./vs/base/browser/ui/octiconLabel/octiconLabel.mock.ts", + "./vs/base/browser/ui/octiconLabel/octiconLabel.ts", + "./vs/base/browser/ui/scrollbar/scrollableElementOptions.ts", + "./vs/base/browser/ui/scrollbar/scrollbarState.ts", + "./vs/base/browser/ui/tree/tree.ts", + "./vs/base/common/actions.ts", + "./vs/base/common/amd.ts", + "./vs/base/common/arrays.ts", + "./vs/base/common/assert.ts", + "./vs/base/common/async.ts", + "./vs/base/common/cache.ts", + "./vs/base/common/cancellation.ts", + "./vs/base/common/charCode.ts", + "./vs/base/common/collections.ts", + "./vs/base/common/color.ts", + "./vs/base/common/comparers.ts", + "./vs/base/common/date.ts", + "./vs/base/common/decorators.ts", + "./vs/base/common/diff/diff.ts", + "./vs/base/common/diff/diffChange.ts", + "./vs/base/common/errorMessage.ts", + "./vs/base/common/errors.ts", + "./vs/base/common/errorsWithActions.ts", + "./vs/base/common/event.ts", + "./vs/base/common/filters.ts", + "./vs/base/common/functional.ts", + "./vs/base/common/glob.ts", + "./vs/base/common/hash.ts", + "./vs/base/common/history.ts", + "./vs/base/common/htmlContent.ts", + "./vs/base/common/idGenerator.ts", + "./vs/base/common/iterator.ts", + "./vs/base/common/jsonSchema.ts", + "./vs/base/common/keyCodes.ts", + "./vs/base/common/keybindingParser.ts", + "./vs/base/common/labels.ts", + "./vs/base/common/lifecycle.ts", + "./vs/base/common/linkedList.ts", + "./vs/base/common/map.ts", + "./vs/base/common/marshalling.ts", + "./vs/base/common/network.ts", + "./vs/base/common/normalization.ts", + "./vs/base/common/numbers.ts", + "./vs/base/common/objects.ts", + "./vs/base/common/parsers.ts", + "./vs/base/common/paths.ts", + "./vs/base/common/platform.ts", + "./vs/base/common/processes.ts", + "./vs/base/common/range.ts", + "./vs/base/common/resources.ts", + "./vs/base/common/scanCode.ts", + "./vs/base/common/scrollable.ts", + "./vs/base/common/sequence.ts", + "./vs/base/common/severity.ts", + "./vs/base/common/stopwatch.ts", + "./vs/base/common/strings.ts", + "./vs/base/common/types.ts", + "./vs/base/common/uri.ts", + "./vs/base/common/uriIpc.ts", + "./vs/base/common/uuid.ts", + "./vs/base/common/winjs.base.d.ts", + "./vs/base/common/winjs.polyfill.promise.ts", + "./vs/base/common/worker/simpleWorker.ts", + "./vs/base/node/decoder.ts", + "./vs/base/node/id.ts", + "./vs/base/node/paths.ts", + "./vs/base/node/ports.ts", + "./vs/base/parts/contextmenu/common/contextmenu.ts", + "./vs/base/parts/contextmenu/electron-main/contextmenu.ts", + "./vs/base/parts/quickopen/common/quickOpen.ts", + "./vs/base/test/common/utils.ts", + "./vs/base/test/node/uri.test.perf.ts", + "./vs/base/worker/defaultWorkerFactory.ts", + "./vs/base/worker/workerMain.ts", + "./vs/code/electron-browser/issue/issueReporterPage.ts", + "./vs/code/electron-browser/issue/issueReporterUtil.ts", + "./vs/code/electron-main/keyboard.ts", + "./vs/code/electron-main/theme.ts", + "./vs/code/node/shellEnv.ts", + "./vs/editor/browser/config/charWidthReader.ts", + "./vs/editor/browser/config/elementSizeObserver.ts", + "./vs/editor/browser/controller/textAreaState.ts", + "./vs/editor/common/commands/replaceCommand.ts", + "./vs/editor/common/commands/surroundSelectionCommand.ts", + "./vs/editor/common/commands/trimTrailingWhitespaceCommand.ts", + "./vs/editor/common/config/editorOptions.ts", + "./vs/editor/common/config/editorZoom.ts", + "./vs/editor/common/config/fontInfo.ts", + "./vs/editor/common/controller/cursorEvents.ts", + "./vs/editor/common/controller/wordCharacterClassifier.ts", + "./vs/editor/common/core/characterClassifier.ts", + "./vs/editor/common/core/editOperation.ts", + "./vs/editor/common/core/lineTokens.ts", + "./vs/editor/common/core/position.ts", + "./vs/editor/common/core/range.ts", + "./vs/editor/common/core/rgba.ts", + "./vs/editor/common/core/selection.ts", + "./vs/editor/common/core/stringBuilder.ts", + "./vs/editor/common/core/token.ts", + "./vs/editor/common/core/uint.ts", + "./vs/editor/common/diff/diffComputer.ts", + "./vs/editor/common/editorAction.ts", + "./vs/editor/common/editorCommon.ts", + "./vs/editor/common/editorContextKeys.ts", + "./vs/editor/common/model.ts", + "./vs/editor/common/model/editStack.ts", + "./vs/editor/common/model/indentationGuesser.ts", + "./vs/editor/common/model/intervalTree.ts", + "./vs/editor/common/model/mirrorTextModel.ts", + "./vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts", + "./vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts", + "./vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder.ts", + "./vs/editor/common/model/pieceTreeTextBuffer/rbTreeBase.ts", + "./vs/editor/common/model/textModel.ts", + "./vs/editor/common/model/textModelEvents.ts", + "./vs/editor/common/model/textModelSearch.ts", + "./vs/editor/common/model/textModelTokens.ts", + "./vs/editor/common/model/wordHelper.ts", + "./vs/editor/common/modes.ts", + "./vs/editor/common/modes/abstractMode.ts", + "./vs/editor/common/modes/languageConfiguration.ts", + "./vs/editor/common/modes/languageConfigurationRegistry.ts", + "./vs/editor/common/modes/languageFeatureRegistry.ts", + "./vs/editor/common/modes/languageSelector.ts", + "./vs/editor/common/modes/linkComputer.ts", + "./vs/editor/common/modes/nullMode.ts", + "./vs/editor/common/modes/supports.ts", + "./vs/editor/common/modes/supports/characterPair.ts", + "./vs/editor/common/modes/supports/electricCharacter.ts", + "./vs/editor/common/modes/supports/indentRules.ts", + "./vs/editor/common/modes/supports/inplaceReplaceSupport.ts", + "./vs/editor/common/modes/supports/onEnter.ts", + "./vs/editor/common/modes/supports/richEditBrackets.ts", + "./vs/editor/common/modes/supports/tokenization.ts", + "./vs/editor/common/modes/textToHtmlTokenizer.ts", + "./vs/editor/common/modes/tokenizationRegistry.ts", + "./vs/editor/common/services/editorWorkerService.ts", + "./vs/editor/common/services/modelService.ts", + "./vs/editor/common/services/modeService.ts", + "./vs/editor/common/services/resolverService.ts", + "./vs/editor/common/standalone/standaloneBase.ts", + "./vs/editor/common/view/minimapCharRenderer.ts", + "./vs/editor/common/view/overviewZoneManager.ts", + "./vs/editor/common/view/runtimeMinimapCharRenderer.ts", + "./vs/editor/common/view/viewEvents.ts", + "./vs/editor/common/viewLayout/whitespaceComputer.ts", + "./vs/editor/common/viewModel/prefixSumComputer.ts", + "./vs/editor/contrib/codeAction/codeActionTrigger.ts", + "./vs/editor/contrib/colorPicker/colorPickerModel.ts", + "./vs/editor/contrib/find/findState.ts", + "./vs/editor/contrib/find/replaceAllCommand.ts", + "./vs/editor/contrib/find/replacePattern.ts", + "./vs/editor/contrib/indentation/indentUtils.ts", + "./vs/editor/contrib/inPlaceReplace/inPlaceReplaceCommand.ts", + "./vs/editor/contrib/linesOperations/copyLinesCommand.ts", + "./vs/editor/standalone/common/monarch/monarchCommon.ts", + "./vs/editor/standalone/common/monarch/monarchCompile.ts", + "./vs/editor/standalone/common/monarch/monarchTypes.ts", + "./vs/editor/test/common/commentMode.ts", + "./vs/editor/test/common/core/viewLineToken.ts", + "./vs/editor/test/common/editorTestUtils.ts", + "./vs/editor/test/common/mocks/mockMode.ts", + "./vs/editor/test/common/model/benchmark/benchmarkUtils.ts", + "./vs/editor/test/common/modes/supports/javascriptOnEnterRules.ts", + "./vs/editor/test/common/modesTestUtils.ts", + "./vs/monaco.d.ts", + "./vs/nls.mock.ts", + "./vs/platform/broadcast/electron-browser/broadcastService.ts", + "./vs/platform/clipboard/common/clipboardService.ts", + "./vs/platform/clipboard/electron-browser/clipboardService.ts", + "./vs/platform/contextkey/common/contextkey.ts", + "./vs/platform/download/common/download.ts", + "./vs/platform/editor/common/editor.ts", + "./vs/platform/environment/common/environment.ts", + "./vs/platform/extensions/common/extensionHost.ts", + "./vs/platform/extensions/common/extensions.ts", + "./vs/platform/files/common/files.ts", + "./vs/platform/files/node/files.ts", + "./vs/platform/instantiation/common/descriptors.ts", + "./vs/platform/instantiation/common/extensions.ts", + "./vs/platform/instantiation/common/graph.ts", + "./vs/platform/instantiation/common/instantiation.ts", + "./vs/platform/instantiation/common/serviceCollection.ts", + "./vs/platform/integrity/common/integrity.ts", + "./vs/platform/jsonschemas/common/jsonContributionRegistry.ts", + "./vs/platform/lifecycle/common/lifecycle.ts", + "./vs/platform/localizations/common/localizations.ts", + "./vs/platform/log/common/bufferLog.ts", + "./vs/platform/log/common/log.ts", + "./vs/platform/log/node/spdlogService.ts", + "./vs/platform/markers/common/markers.ts", + "./vs/platform/menubar/common/menubar.ts", + "./vs/platform/node/minimalTranslations.ts", + "./vs/platform/node/package.ts", + "./vs/platform/node/product.ts", + "./vs/platform/notification/common/notification.ts", + "./vs/platform/notification/test/common/testNotificationService.ts", + "./vs/platform/opener/common/opener.ts", + "./vs/platform/output/node/outputAppender.ts", + "./vs/platform/progress/common/progress.ts", + "./vs/platform/quickinput/common/quickInput.ts", + "./vs/platform/quickOpen/common/quickOpen.ts", + "./vs/platform/registry/common/platform.ts", + "./vs/platform/search/common/search.ts", + "./vs/platform/state/common/state.ts", + "./vs/platform/statusbar/common/statusbar.ts", + "./vs/platform/telemetry/common/telemetry.ts", + "./vs/platform/telemetry/node/telemetryNodeUtils.ts", + "./vs/platform/theme/common/colorRegistry.ts", + "./vs/platform/theme/common/themeService.ts", + "./vs/platform/update/common/update.ts", + "./vs/platform/url/common/url.ts", + "./vs/platform/url/common/urlService.ts", + "./vs/platform/workbench/common/contextkeys.ts", + "./vs/workbench/api/shared/tasks.ts", + "./vs/workbench/browser/parts/statusbar/statusbar.ts", + "./vs/workbench/common/activity.ts", + "./vs/workbench/common/composite.ts", + "./vs/workbench/common/contributions.ts", + "./vs/workbench/common/extensionHostProtocol.ts", + "./vs/workbench/common/panel.ts", + "./vs/workbench/common/viewlet.ts", + "./vs/workbench/parts/codeEditor/browser/simpleEditorOptions.ts", + "./vs/workbench/parts/execution/common/execution.ts", + "./vs/workbench/parts/extensions/common/extensionQuery.ts", + "./vs/workbench/parts/logs/common/logConstants.ts", + "./vs/workbench/parts/markers/electron-browser/constants.ts", + "./vs/workbench/parts/outline/electron-browser/outline.ts", + "./vs/workbench/parts/output/common/output.ts", + "./vs/workbench/parts/scm/electron-browser/scmUtil.ts", + "./vs/workbench/parts/search/common/constants.ts", + "./vs/workbench/parts/terminal/browser/terminalWidgetManager.ts", + "./vs/workbench/parts/terminal/common/terminal.ts", + "./vs/workbench/parts/welcome/page/electron-browser/vs_code_welcome_page.ts", + "./vs/workbench/services/activity/common/activity.ts", + "./vs/workbench/services/backup/common/backup.ts", + "./vs/workbench/services/configuration/common/jsonEditing.ts", + "./vs/workbench/services/decorations/browser/decorations.ts", + "./vs/workbench/services/extensions/node/lazyPromise.ts", + "./vs/workbench/services/extensions/node/proxyIdentifier.ts", + "./vs/workbench/services/files/node/watcher/common.ts", + "./vs/workbench/services/files/node/watcher/nsfw/watcher.ts", + "./vs/workbench/services/files/node/watcher/unix/watcher.ts", + "./vs/workbench/services/hash/common/hashService.ts", + "./vs/workbench/services/hash/node/hashService.ts", + "./vs/workbench/services/panel/common/panelService.ts", + "./vs/workbench/services/scm/common/scm.ts", + "./vs/workbench/services/scm/common/scmService.ts", + "./vs/workbench/services/search/node/search.ts", + "./vs/workbench/services/textMate/electron-browser/textMateService.ts", + "./vs/workbench/services/title/common/titleService.ts", + "./vs/workbench/test/electron-browser/api/mock.ts" + ], + "exclude": [ + "./typings/require-monaco.d.ts" + ] +} \ No newline at end of file diff --git a/src/typings/require-monaco.d.ts b/src/typings/require-monaco.d.ts index 4d00b30f34d..1d823ddb860 100644 --- a/src/typings/require-monaco.d.ts +++ b/src/typings/require-monaco.d.ts @@ -4,7 +4,9 @@ *--------------------------------------------------------------------------------------------*/ interface NodeRequire { - (moduleName: string): any; - } + toUrl(path: string): string; + (dependencies: string[], callback: (...args: any[]) => any, errorback?: (err: any) => void): any; + config(data: any): any; +} declare var require: NodeRequire; \ No newline at end of file diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index f36e59ba51b..4c7c9ae2240 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -20,7 +20,7 @@ export function clearNode(node: HTMLElement): void { } } -export function isInDOM(node: Node): boolean { +export function isInDOM(node: Node | null): boolean { while (node) { if (node === document.body) { return true; @@ -151,7 +151,7 @@ const _manualClassList = new class implements IDomClassList { const _nativeClassList = new class implements IDomClassList { hasClass(node: HTMLElement, className: string): boolean { - return className && node.classList && node.classList.contains(className); + return Boolean(className) && node.classList && node.classList.contains(className); } addClasses(node: HTMLElement, ...classNames: string[]): void { @@ -198,7 +198,7 @@ class DomListener implements IDisposable { private readonly _type: string; private readonly _useCapture: boolean; - constructor(node: Element | Window | Document, type: string, handler: (e: any) => void, useCapture: boolean) { + constructor(node: Element | Window | Document, type: string, handler: (e: any) => void, useCapture?: boolean) { this._node = node; this._type = type; this._handler = handler; @@ -215,8 +215,8 @@ class DomListener implements IDisposable { this._node.removeEventListener(this._type, this._handler, this._useCapture); // Prevent leakers from holding on to the dom or handler func - this._node = null; - this._handler = null; + this._node = null!; + this._handler = null!; } } @@ -257,7 +257,7 @@ export let addStandardDisposableListener: IAddStandardDisposableListenerSignatur export function addDisposableNonBubblingMouseOutListener(node: Element, handler: (event: MouseEvent) => void): IDisposable { return addDisposableListener(node, 'mouseout', (e: MouseEvent) => { // Mouse out bubbles, so this is an attempt to ignore faux mouse outs coming from children elements - let toElement = (e.relatedTarget || e.toElement); + let toElement: Node | null = (e.relatedTarget || e.toElement); while (toElement && toElement !== node) { toElement = toElement.parentNode; } @@ -272,7 +272,7 @@ export function addDisposableNonBubblingMouseOutListener(node: Element, handler: interface IRequestAnimationFrame { (callback: (time: number) => void): number; } -let _animationFrame: IRequestAnimationFrame = null; +let _animationFrame: IRequestAnimationFrame | null = null; function doRequestAnimationFrame(callback: (time: number) => void): number { if (!_animationFrame) { const emulatedRequestAnimationFrame = (callback: (time: number) => void): any => { @@ -311,7 +311,7 @@ class AnimationFrameQueueItem implements IDisposable { public priority: number; private _canceled: boolean; - constructor(runner: () => void, priority: number) { + constructor(runner: () => void, priority: number = 0) { this._runner = runner; this.priority = priority; this._canceled = false; @@ -347,7 +347,7 @@ class AnimationFrameQueueItem implements IDisposable { /** * The runners scheduled at the current animation frame */ - let CURRENT_QUEUE: AnimationFrameQueueItem[] = null; + let CURRENT_QUEUE: AnimationFrameQueueItem[] | null = null; /** * A flag to keep track if the native requestAnimationFrame was already called */ @@ -366,7 +366,7 @@ class AnimationFrameQueueItem implements IDisposable { inAnimationFrameRunner = true; while (CURRENT_QUEUE.length > 0) { CURRENT_QUEUE.sort(AnimationFrameQueueItem.sort); - let top = CURRENT_QUEUE.shift(); + let top = CURRENT_QUEUE.shift()!; top.execute(); } inAnimationFrameRunner = false; @@ -387,7 +387,7 @@ class AnimationFrameQueueItem implements IDisposable { runAtThisOrScheduleAtNextAnimationFrame = (runner: () => void, priority?: number) => { if (inAnimationFrameRunner) { let item = new AnimationFrameQueueItem(runner, priority); - CURRENT_QUEUE.push(item); + CURRENT_QUEUE!.push(item); return item; } else { return scheduleAtNextAnimationFrame(runner, priority); @@ -407,7 +407,7 @@ export function modify(callback: () => void): IDisposable { * Add a throttled listener. `handler` is fired at most every 16ms or with the next animation frame (if browser supports it). */ export interface IEventMerger { - (lastEvent: R, currentEvent: E): R; + (lastEvent: R | null, currentEvent: E): R; } export interface DOMEvent { @@ -425,13 +425,13 @@ class TimeoutThrottledDomListener extends Disposable { constructor(node: any, type: string, handler: (event: R) => void, eventMerger: IEventMerger = DEFAULT_EVENT_MERGER, minimumTimeMs: number = MINIMUM_TIME_MS) { super(); - let lastEvent: R = null; + let lastEvent: R | null = null; let lastHandlerTime = 0; let timeout = this._register(new TimeoutTimer()); let invokeHandler = () => { lastHandlerTime = (new Date()).getTime(); - handler(lastEvent); + handler(lastEvent); lastEvent = null; }; @@ -455,7 +455,7 @@ export function addDisposableThrottledListener } export function getComputedStyle(el: HTMLElement): CSSStyleDeclaration { - return document.defaultView.getComputedStyle(el, null); + return document.defaultView!.getComputedStyle(el, null); } // Adapted from WinJS @@ -660,7 +660,7 @@ export const StandardWindow: IStandardWindow = new class implements IStandardWin // modern browsers return window.scrollX; } else { - return document.body.scrollLeft + document.documentElement.scrollLeft; + return document.body.scrollLeft + document.documentElement!.scrollLeft; } } @@ -669,7 +669,7 @@ export const StandardWindow: IStandardWindow = new class implements IStandardWin // modern browsers return window.scrollY; } else { - return document.body.scrollTop + document.documentElement.scrollTop; + return document.body.scrollTop + document.documentElement!.scrollTop; } } }; @@ -728,7 +728,7 @@ export function getLargestChildWidth(parent: HTMLElement, children: HTMLElement[ // ---------------------------------------------------------------------------------------- -export function isAncestor(testChild: Node, testAncestor: Node): boolean { +export function isAncestor(testChild: Node | null, testAncestor: Node): boolean { while (testChild) { if (testChild === testAncestor) { return true; @@ -739,7 +739,7 @@ export function isAncestor(testChild: Node, testAncestor: Node): boolean { return false; } -export function findParentWithClass(node: HTMLElement, clazz: string, stopAtClazzOrNode?: string | HTMLElement): HTMLElement { +export function findParentWithClass(node: HTMLElement, clazz: string, stopAtClazzOrNode?: string | HTMLElement): HTMLElement | null { while (node) { if (hasClass(node, clazz)) { return node; @@ -771,7 +771,7 @@ export function createStyleSheet(container: HTMLElement = document.getElementsBy return style; } -let _sharedStyleSheet: HTMLStyleElement = null; +let _sharedStyleSheet: HTMLStyleElement | null = null; function getSharedStyleSheet(): HTMLStyleElement { if (!_sharedStyleSheet) { _sharedStyleSheet = createStyleSheet(); @@ -1002,17 +1002,18 @@ export function $(description: string, attrs?: { [key: st result.className = match[4].replace(/\./g, ' ').trim(); } - Object.keys(attrs || {}).forEach(name => { + attrs = attrs || {}; + Object.keys(attrs).forEach(name => { + const value = attrs![name]; if (/^on\w+$/.test(name)) { - (result)[name] = attrs[name]; + (result)[name] = value; } else if (name === 'selected') { - const value = attrs[name]; if (value) { result.setAttribute(name, 'true'); } } else { - result.setAttribute(name, attrs[name]); + result.setAttribute(name, value); } }); @@ -1061,7 +1062,7 @@ export function hide(...elements: HTMLElement[]): void { } } -function findParentWithAttribute(node: Node, attribute: string): HTMLElement { +function findParentWithAttribute(node: Node | null, attribute: string): HTMLElement | null { while (node) { if (node instanceof HTMLElement && node.hasAttribute(attribute)) { return node; diff --git a/src/vs/base/browser/iframe.ts b/src/vs/base/browser/iframe.ts index 3cede5b4173..96937dcf71e 100644 --- a/src/vs/base/browser/iframe.ts +++ b/src/vs/base/browser/iframe.ts @@ -14,13 +14,13 @@ export interface IWindowChainElement { /** * The iframe element inside the window.parent corresponding to window */ - iframeElement: HTMLIFrameElement; + iframeElement: HTMLIFrameElement | null; } let hasDifferentOriginAncestorFlag: boolean = false; -let sameOriginWindowChainCache: IWindowChainElement[] = null; +let sameOriginWindowChainCache: IWindowChainElement[] | null = null; -function getParentWindowIfSameOrigin(w: Window): Window { +function getParentWindowIfSameOrigin(w: Window): Window | null { if (!w.parent || w.parent === w) { return null; } @@ -41,7 +41,7 @@ function getParentWindowIfSameOrigin(w: Window): Window { return w.parent; } -function findIframeElementInParentWindow(parentWindow: Window, childWindow: Window): HTMLIFrameElement { +function findIframeElementInParentWindow(parentWindow: Window, childWindow: Window): HTMLIFrameElement | null { let parentWindowIframes = parentWindow.document.getElementsByTagName('iframe'); let iframe: HTMLIFrameElement; for (let i = 0, len = parentWindowIframes.length; i < len; i++) { @@ -63,7 +63,8 @@ export class IframeUtils { public static getSameOriginWindowChain(): IWindowChainElement[] { if (!sameOriginWindowChainCache) { sameOriginWindowChainCache = []; - let w = window, parent: Window; + let w: Window | null = window; + let parent: Window | null; do { parent = getParentWindowIfSameOrigin(w); if (parent) { diff --git a/src/vs/base/browser/mouseEvent.ts b/src/vs/base/browser/mouseEvent.ts index cba7c60fb6b..871506af1f2 100644 --- a/src/vs/base/browser/mouseEvent.ts +++ b/src/vs/base/browser/mouseEvent.ts @@ -66,8 +66,8 @@ export class StandardMouseEvent implements IMouseEvent { this.posy = e.pageY; } else { // Probably hit by MSGestureEvent - this.posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; - this.posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; + this.posx = e.clientX + document.body.scrollLeft + document.documentElement!.scrollLeft; + this.posy = e.clientY + document.body.scrollTop + document.documentElement!.scrollTop; } // Find the position of the iframe this code is executing in relative to the iframe where the event was captured. diff --git a/src/vs/base/browser/ui/actionbar/actionbar.ts b/src/vs/base/browser/ui/actionbar/actionbar.ts index 4d25c01ecfd..d07946d2aa3 100644 --- a/src/vs/base/browser/ui/actionbar/actionbar.ts +++ b/src/vs/base/browser/ui/actionbar/actionbar.ts @@ -286,7 +286,7 @@ export class ActionItem extends BaseActionItem { } updateTooltip(): void { - let title: string = null; + let title: string | null = null; if (this.getAction().tooltip) { title = this.getAction().tooltip; @@ -602,7 +602,7 @@ export class ActionBar extends Disposable implements IActionRunner { e.stopPropagation(); })); - let item: IActionItem = null; + let item: IActionItem | null = null; if (this.options.actionItemProvider) { item = this.options.actionItemProvider(action); diff --git a/src/vs/base/browser/ui/inputbox/inputBox.ts b/src/vs/base/browser/ui/inputbox/inputBox.ts index 39b3a5c0fe9..947e36a2c77 100644 --- a/src/vs/base/browser/ui/inputbox/inputBox.ts +++ b/src/vs/base/browser/ui/inputbox/inputBox.ts @@ -260,7 +260,7 @@ export class InputBox extends Widget { return document.activeElement === this.input; } - public select(range: IRange = null): void { + public select(range: IRange | null = null): void { this.input.select(); if (range) { @@ -339,7 +339,7 @@ export class InputBox extends Widget { } public validate(): boolean { - let errorMsg: IMessage = null; + let errorMsg: IMessage | null = null; if (this.validation) { errorMsg = this.validation(this.value); diff --git a/src/vs/base/browser/ui/list/rangeMap.ts b/src/vs/base/browser/ui/list/rangeMap.ts index 602125030ef..3c4d78563b9 100644 --- a/src/vs/base/browser/ui/list/rangeMap.ts +++ b/src/vs/base/browser/ui/list/rangeMap.ts @@ -60,7 +60,7 @@ export function shift({ start, end }: IRange, much: number): IRange { */ export function consolidate(groups: IRangedGroup[]): IRangedGroup[] { const result: IRangedGroup[] = []; - let previousGroup: IRangedGroup = null; + let previousGroup: IRangedGroup | null = null; for (let group of groups) { const start = group.range.start; diff --git a/src/vs/base/browser/ui/menu/menu.ts b/src/vs/base/browser/ui/menu/menu.ts index 57a6253d2b5..1cc3f375b27 100644 --- a/src/vs/base/browser/ui/menu/menu.ts +++ b/src/vs/base/browser/ui/menu/menu.ts @@ -347,7 +347,7 @@ class MenuActionItem extends BaseActionItem { } updateTooltip(): void { - let title: string = null; + let title: string | null = null; if (this.getAction().tooltip) { title = this.getAction().tooltip; diff --git a/src/vs/base/browser/ui/selectBox/selectBoxCustom.css b/src/vs/base/browser/ui/selectBox/selectBoxCustom.css index 9bf02542ec4..c2f95bd9f13 100644 --- a/src/vs/base/browser/ui/selectBox/selectBoxCustom.css +++ b/src/vs/base/browser/ui/selectBox/selectBoxCustom.css @@ -78,8 +78,16 @@ white-space: nowrap; } -.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row > .option-text-description { - display: none; +/* Accepted CSS hiding technique for accessibility reader text */ +/* https://webaim.org/techniques/css/invisiblecontent/ */ + +.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row > .visually-hidden { + position: absolute; + left: -10000px; + top: auto; + width: 1px; + height: 1px; + overflow: hidden; } .monaco-select-box-dropdown-container > .select-box-dropdown-container-width-control { diff --git a/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts b/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts index fe455555e10..af3e03e1ba7 100644 --- a/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts +++ b/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts @@ -5,7 +5,6 @@ import 'vs/css!./selectBoxCustom'; -import * as nls from 'vs/nls'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { Event, Emitter, chain } from 'vs/base/common/event'; import { KeyCode, KeyCodeUtils } from 'vs/base/common/keyCodes'; @@ -50,6 +49,7 @@ class SelectListRenderer implements IRendererelement).optionDisabled; data.optionText.textContent = optionText; - data.root.setAttribute('aria-label', nls.localize('selectAriaOption', "{0}", optionText) + ',.'); if (typeof element.optionDescriptionText === 'string') { const optionDescriptionId = (optionText.replace(/ /g, '_').toLowerCase() + '_description_' + data.root.id); - data.root.setAttribute('aria-describedby', optionDescriptionId); + data.optionText.setAttribute('aria-describedby', optionDescriptionId); data.optionDescriptionText.id = optionDescriptionId; - data.optionDescriptionText.setAttribute('aria-label', element.optionDescriptionText); + data.optionDescriptionText.innerText = element.optionDescriptionText; } - // Workaround for list labels - data.root.setAttribute('aria-selected', 'true'); - // pseudo-select disabled option if (optionDisabled) { dom.addClass((data.root), 'option-disabled'); diff --git a/src/vs/base/browser/ui/splitview/panelview.ts b/src/vs/base/browser/ui/splitview/panelview.ts index 3d0da96fb2d..4364bf1432d 100644 --- a/src/vs/base/browser/ui/splitview/panelview.ts +++ b/src/vs/base/browser/ui/splitview/panelview.ts @@ -46,7 +46,6 @@ export abstract class Panel implements IView { protected _expanded: boolean; protected disposables: IDisposable[] = []; - private expandedSize: number | undefined = undefined; private _headerVisible = true; private _minimumBodySize: number; private _maximumBodySize: number; @@ -55,6 +54,9 @@ export abstract class Panel implements IView { private header: HTMLElement; + private cachedExpandedSize: number | undefined = undefined; + private cachedBodySize: number | undefined = undefined; + private _onDidChange = new Emitter(); readonly onDidChange: Event = this._onDidChange.event; @@ -129,7 +131,7 @@ export abstract class Panel implements IView { this._expanded = !!expanded; this.updateHeader(); - this._onDidChange.fire(expanded ? this.expandedSize : undefined); + this._onDidChange.fire(expanded ? this.cachedExpandedSize : undefined); } get headerVisible(): boolean { @@ -190,8 +192,14 @@ export abstract class Panel implements IView { const headerSize = this.headerVisible ? Panel.HEADER_SIZE : 0; if (this.isExpanded()) { - this.layoutBody(size - headerSize); - this.expandedSize = size; + const bodySize = size - headerSize; + + if (bodySize !== this.cachedBodySize) { + this.layoutBody(bodySize); + this.cachedBodySize = bodySize; + } + + this.cachedExpandedSize = size; } } @@ -326,7 +334,7 @@ class PanelDraggable extends Disposable { } private render(): void { - let backgroundColor: string = null; + let backgroundColor: string | null = null; if (this.dragOverCounter > 0) { backgroundColor = (this.panel.dropBackground || PanelDraggable.DefaultDragOverBackgroundColor).toString(); diff --git a/src/vs/base/common/actions.ts b/src/vs/base/common/actions.ts index 939b00b82e4..23494efa11a 100644 --- a/src/vs/base/common/actions.ts +++ b/src/vs/base/common/actions.ts @@ -60,7 +60,7 @@ export class Action implements IAction { protected _enabled: boolean; protected _checked: boolean; protected _radio: boolean; - protected _actionCallback: (event?: any) => Thenable; + protected _actionCallback?: (event?: any) => Thenable; constructor(id: string, label: string = '', cssClass: string = '', enabled: boolean = true, actionCallback?: (event?: any) => Thenable) { this._id = id; @@ -165,7 +165,7 @@ export class Action implements IAction { } run(event?: any, _data?: ITelemetryData): Thenable { - if (this._actionCallback !== void 0) { + if (this._actionCallback) { return this._actionCallback(event); } diff --git a/src/vs/base/common/arrays.ts b/src/vs/base/common/arrays.ts index 0abb4867d9a..e8b6ef67004 100644 --- a/src/vs/base/common/arrays.ts +++ b/src/vs/base/common/arrays.ts @@ -138,7 +138,7 @@ function _sort(a: T[], compare: Compare, lo: number, hi: number, aux: T[]) export function groupBy(data: T[], compare: (a: T, b: T) => number): T[][] { const result: T[][] = []; - let currentGroup: T[]; + let currentGroup: T[] | undefined = undefined; for (const element of mergeSort(data.slice(0), compare)) { if (!currentGroup || compare(currentGroup[0], element) !== 0) { currentGroup = [element]; @@ -388,7 +388,9 @@ export function firstIndex(array: T[] | ReadonlyArray, fn: (item: T) => bo return -1; } -export function first(array: T[] | ReadonlyArray, fn: (item: T) => boolean, notFoundValue: T = null): T { +export function first(array: T[] | ReadonlyArray, fn: (item: T) => boolean, notFoundValue: T): T; +export function first(array: T[] | ReadonlyArray, fn: (item: T) => boolean): T | null; +export function first(array: T[] | ReadonlyArray, fn: (item: T) => boolean, notFoundValue: T | null = null): T | null { const index = firstIndex(array, fn); return index < 0 ? notFoundValue : array[index]; } @@ -404,7 +406,7 @@ export function commonPrefixLength(one: T[], other: T[], equals: (a: T, b: T) } export function flatten(arr: T[][]): T[] { - return [].concat(...arr); + return ([]).concat(...arr); } export function range(to: number): number[]; @@ -481,15 +483,20 @@ export function arrayInsert(target: T[], insertIndex: number, insertArr: T[]) * Uses Fisher-Yates shuffle to shuffle the given array * @param array */ -export function shuffle(array: T[], seed?: number): void { - // Seeded random number generator in JS. Modified from: - // https://stackoverflow.com/questions/521295/seeding-the-random-number-generator-in-javascript - const random = () => { - var x = Math.sin(seed++) * 179426549; // throw away most significant digits and reduce any potential bias - return x - Math.floor(x); - }; +export function shuffle(array: T[], _seed?: number): void { + let rand: () => number; - const rand = typeof seed === 'number' ? random : Math.random; + if (typeof _seed === 'number') { + let seed = _seed; + // Seeded random number generator in JS. Modified from: + // https://stackoverflow.com/questions/521295/seeding-the-random-number-generator-in-javascript + rand = () => { + var x = Math.sin(seed++) * 179426549; // throw away most significant digits and reduce any potential bias + return x - Math.floor(x); + }; + } else { + rand = Math.random; + } for (let i = array.length - 1; i > 0; i -= 1) { let j = Math.floor(rand() * (i + 1)); diff --git a/src/vs/base/common/async.ts b/src/vs/base/common/async.ts index bcf32e22066..d67bfdc8b4c 100644 --- a/src/vs/base/common/async.ts +++ b/src/vs/base/common/async.ts @@ -91,9 +91,9 @@ export interface ITask { */ export class Throttler { - private activePromise: TPromise; - private queuedPromise: TPromise; - private queuedPromiseFactory: ITask; + private activePromise: TPromise | null; + private queuedPromise: TPromise | null; + private queuedPromiseFactory: ITask | null; constructor() { this.activePromise = null; @@ -109,26 +109,26 @@ export class Throttler { const onComplete = () => { this.queuedPromise = null; - const result = this.queue(this.queuedPromiseFactory); + const result = this.queue(this.queuedPromiseFactory!); this.queuedPromiseFactory = null; return result; }; this.queuedPromise = new TPromise(c => { - this.activePromise.then(onComplete, onComplete).then(c); + this.activePromise!.then(onComplete, onComplete).then(c); }); } return new TPromise((c, e) => { - this.queuedPromise.then(c, e); + this.queuedPromise!.then(c, e); }); } this.activePromise = promiseFactory(); return new TPromise((c, e) => { - this.activePromise.then((result: any) => { + this.activePromise!.then((result: any) => { this.activePromise = null; c(result); }, (err: any) => { @@ -175,10 +175,10 @@ export class SimpleThrottler { export class Delayer { private timeout: any; - private completionPromise: TPromise; - private doResolve: ValueCallback; + private completionPromise: TPromise | null; + private doResolve: ValueCallback | null; private doReject: (err: any) => void; - private task: ITask>; + private task: ITask> | null; constructor(public defaultDelay: number) { this.timeout = null; @@ -198,7 +198,7 @@ export class Delayer { }).then(() => { this.completionPromise = null; this.doResolve = null; - const task = this.task; + const task = this.task!; this.task = null; return task(); @@ -207,7 +207,7 @@ export class Delayer { this.timeout = setTimeout(() => { this.timeout = null; - this.doResolve(null); + this.doResolve!(null); }, delay); return this.completionPromise; @@ -363,11 +363,11 @@ export function sequence(promiseFactories: ITask>[]): Promise(promiseFactories: ITask>[], shouldStop: (t: T) => boolean = t => !!t, defaultValue: T = null): Promise { +export function first(promiseFactories: ITask>[], shouldStop: (t: T) => boolean = t => !!t, defaultValue: T | null = null): Promise { let index = 0; const len = promiseFactories.length; - const loop: () => Promise = () => { + const loop: () => Promise = () => { if (index >= len) { return Promise.resolve(defaultValue); } @@ -429,7 +429,7 @@ export class Limiter { private consume(): void { while (this.outstandingPromises.length && this.runningPromises < this.maxDegreeOfParalellism) { - const iLimitedTask = this.outstandingPromises.shift(); + const iLimitedTask = this.outstandingPromises.shift()!; this.runningPromises++; const promise = iLimitedTask.factory(); @@ -567,7 +567,7 @@ export class IntervalTimer extends Disposable { export class RunOnceScheduler { - protected runner: (...args: any[]) => void; + protected runner: ((...args: any[]) => void) | null; private timeoutToken: any; private timeout: number; @@ -621,7 +621,9 @@ export class RunOnceScheduler { } protected doRun(): void { - this.runner(); + if (this.runner) { + this.runner(); + } } } @@ -644,7 +646,9 @@ export class RunOnceWorker extends RunOnceScheduler { const units = this.units; this.units = []; - this.runner(units); + if (this.runner) { + this.runner(units); + } } dispose(): void { @@ -689,12 +693,30 @@ declare function cancelIdleCallback(handle: number): void; }); runWhenIdle = (runner, timeout = 0) => { let handle = setTimeout(() => runner(dummyIdle), timeout); - return { dispose() { clearTimeout(handle); handle = undefined; } }; + let disposed = false; + return { + dispose() { + if (disposed) { + return; + } + disposed = true; + clearTimeout(handle); + } + }; }; } else { runWhenIdle = (runner, timeout?) => { - let handle = requestIdleCallback(runner, typeof timeout === 'number' ? { timeout } : undefined); - return { dispose() { cancelIdleCallback(handle); handle = undefined; } }; + let handle: number = requestIdleCallback(runner, typeof timeout === 'number' ? { timeout } : undefined); + let disposed = false; + return { + dispose() { + if (disposed) { + return; + } + disposed = true; + cancelIdleCallback(handle); + } + }; }; } })(); diff --git a/src/vs/base/common/cache.ts b/src/vs/base/common/cache.ts index efab5f50a49..42c07e4d289 100644 --- a/src/vs/base/common/cache.ts +++ b/src/vs/base/common/cache.ts @@ -13,7 +13,7 @@ export interface CacheResult { export class Cache { - private result: CacheResult = null; + private result: CacheResult | null = null; constructor(private task: (ct: CancellationToken) => Promise) { } get(): CacheResult { diff --git a/src/vs/base/common/cancellation.ts b/src/vs/base/common/cancellation.ts index a68d1f3b3f7..39f672c9751 100644 --- a/src/vs/base/common/cancellation.ts +++ b/src/vs/base/common/cancellation.ts @@ -51,7 +51,7 @@ export namespace CancellationToken { class MutableToken implements CancellationToken { private _isCancelled: boolean = false; - private _emitter: Emitter; + private _emitter: Emitter | null = null; public cancel() { if (!this._isCancelled) { @@ -80,7 +80,7 @@ class MutableToken implements CancellationToken { public dispose(): void { if (this._emitter) { this._emitter.dispose(); - this._emitter = undefined; + this._emitter = null; } } } diff --git a/src/vs/base/common/collections.ts b/src/vs/base/common/collections.ts index 00feeb38739..05758a81246 100644 --- a/src/vs/base/common/collections.ts +++ b/src/vs/base/common/collections.ts @@ -45,7 +45,7 @@ export function size(from: IStringDictionary | INumberDictionary): numb return count; } -export function first(from: IStringDictionary | INumberDictionary): T { +export function first(from: IStringDictionary | INumberDictionary): T | undefined { for (let key in from) { if (hasOwnProperty.call(from, key)) { return from[key]; diff --git a/src/vs/base/common/color.ts b/src/vs/base/common/color.ts index 6dc7eb65aef..a8df525c7cb 100644 --- a/src/vs/base/common/color.ts +++ b/src/vs/base/common/color.ts @@ -416,7 +416,7 @@ export class Color { } toString(): string { - return Color.Format.CSS.format(this); + return '' + Color.Format.CSS.format(this); } static getLighterColor(of: Color, relative: Color, factor?: number): Color { diff --git a/src/vs/base/common/comparers.ts b/src/vs/base/common/comparers.ts index a1cf984e5ef..a3f3ca3582f 100644 --- a/src/vs/base/common/comparers.ts +++ b/src/vs/base/common/comparers.ts @@ -98,7 +98,7 @@ function noIntlCompareFileExtensions(one: string, other: string): number { } function extractNameAndExtension(str?: string): [string, string] { - const match = str ? FileNameMatch.exec(str) : [] as RegExpExecArray; + const match = str ? FileNameMatch.exec(str) as Array : ([] as Array); return [(match && match[1]) || '', (match && match[3]) || '']; } diff --git a/src/vs/base/common/decorators.ts b/src/vs/base/common/decorators.ts index ad829d14ff6..01478d3c3ad 100644 --- a/src/vs/base/common/decorators.ts +++ b/src/vs/base/common/decorators.ts @@ -5,8 +5,8 @@ export function createDecorator(mapFn: (fn: Function, key: string) => Function): Function { return (target: any, key: string, descriptor: any) => { - let fnKey: string = null; - let fn: Function = null; + let fnKey: string | null = null; + let fn: Function | null = null; if (typeof descriptor.value === 'function') { fnKey = 'value'; @@ -20,19 +20,19 @@ export function createDecorator(mapFn: (fn: Function, key: string) => Function): throw new Error('not supported'); } - descriptor[fnKey] = mapFn(fn, key); + descriptor[fnKey!] = mapFn(fn, key); }; } export function memoize(target: any, key: string, descriptor: any) { - let fnKey: string = null; - let fn: Function = null; + let fnKey: string | null = null; + let fn: Function | null = null; if (typeof descriptor.value === 'function') { fnKey = 'value'; fn = descriptor.value; - if (fn.length !== 0) { + if (fn!.length !== 0) { console.warn('Memoize should only be used in functions with zero parameters'); } } else if (typeof descriptor.get === 'function') { @@ -46,13 +46,13 @@ export function memoize(target: any, key: string, descriptor: any) { const memoizeKey = `$memoize$${key}`; - descriptor[fnKey] = function (...args: any[]) { + descriptor[fnKey!] = function (...args: any[]) { if (!this.hasOwnProperty(memoizeKey)) { Object.defineProperty(this, memoizeKey, { configurable: false, enumerable: false, writable: false, - value: fn.apply(this, args) + value: fn!.apply(this, args) }); } diff --git a/src/vs/base/common/diff/diff.ts b/src/vs/base/common/diff/diff.ts index c393b0ad026..c7f09694da7 100644 --- a/src/vs/base/common/diff/diff.ts +++ b/src/vs/base/common/diff/diff.ts @@ -216,7 +216,7 @@ export class LcsDiff { private OriginalSequence: ISequence; private ModifiedSequence: ISequence; - private ContinueProcessingPredicate: IContinueProcessingPredicate; + private ContinueProcessingPredicate: IContinueProcessingPredicate | null; private m_forwardHistory: number[][]; private m_reverseHistory: number[][]; @@ -224,7 +224,7 @@ export class LcsDiff { /** * Constructs the DiffFinder */ - constructor(originalSequence: ISequence, newSequence: ISequence, continueProcessingPredicate: IContinueProcessingPredicate = null) { + constructor(originalSequence: ISequence, newSequence: ISequence, continueProcessingPredicate: IContinueProcessingPredicate | null = null) { this.OriginalSequence = originalSequence; this.ModifiedSequence = newSequence; this.ContinueProcessingPredicate = continueProcessingPredicate; @@ -362,7 +362,7 @@ export class LcsDiff { originalIndex: number, originalEnd: number, midOriginalArr: number[], modifiedIndex: number, modifiedEnd: number, midModifiedArr: number[], deltaIsEven: boolean, quitEarlyArr: boolean[]): DiffChange[] { - let forwardChanges: DiffChange[] = null, reverseChanges: DiffChange[] = null; + let forwardChanges: DiffChange[] | null = null, reverseChanges: DiffChange[] | null = null; // First, walk backward through the forward diagonals history let changeHelper = new DiffChangeHelper(); @@ -498,7 +498,7 @@ export class LcsDiff { * @returns The diff changes, if available, otherwise null */ private ComputeRecursionPoint(originalStart: number, originalEnd: number, modifiedStart: number, modifiedEnd: number, midOriginalArr: number[], midModifiedArr: number[], quitEarlyArr: boolean[]) { - let originalIndex: number, modifiedIndex: number; + let originalIndex = 0, modifiedIndex = 0; let diagonalForwardStart = 0, diagonalForwardEnd = 0; let diagonalReverseStart = 0, diagonalReverseEnd = 0; let numDifferences: number; @@ -763,9 +763,9 @@ export class LcsDiff { change.modifiedStart++; } - let mergedChangeArr: DiffChange[] = [null]; + let mergedChangeArr: (DiffChange | null)[] = [null]; if (i < changes.length - 1 && this.ChangesOverlap(changes[i], changes[i + 1], mergedChangeArr)) { - changes[i] = mergedChangeArr[0]; + changes[i] = mergedChangeArr[0]!; changes.splice(i + 1, 1); i--; continue; @@ -882,7 +882,6 @@ export class LcsDiff { */ private ConcatenateChanges(left: DiffChange[], right: DiffChange[]): DiffChange[] { let mergedChangeArr: DiffChange[] = []; - let result: DiffChange[] = null; if (left.length === 0 || right.length === 0) { return (right.length > 0) ? right : left; @@ -891,14 +890,14 @@ export class LcsDiff { // might recurse in the middle of a change thereby splitting it into // two changes. Here in the combining stage, we detect and fuse those // changes back together - result = new Array(left.length + right.length - 1); + let result = new Array(left.length + right.length - 1); MyArray.Copy(left, 0, result, 0, left.length - 1); result[left.length - 1] = mergedChangeArr[0]; MyArray.Copy(right, 1, result, left.length, right.length - 1); return result; } else { - result = new Array(left.length + right.length); + let result = new Array(left.length + right.length); MyArray.Copy(left, 0, result, 0, left.length); MyArray.Copy(right, 0, result, left.length, right.length); @@ -914,7 +913,7 @@ export class LcsDiff { * @param mergedChange The merged change if the two overlap, null otherwise * @returns True if the two changes overlap */ - private ChangesOverlap(left: DiffChange, right: DiffChange, mergedChangeArr: DiffChange[]): boolean { + private ChangesOverlap(left: DiffChange, right: DiffChange, mergedChangeArr: (DiffChange | null)[]): boolean { Debug.Assert(left.originalStart <= right.originalStart, 'Left change is not less than or equal to right change'); Debug.Assert(left.modifiedStart <= right.modifiedStart, 'Left change is not less than or equal to right change'); diff --git a/src/vs/base/common/errors.ts b/src/vs/base/common/errors.ts index c2061d01c75..e760a55d65b 100644 --- a/src/vs/base/common/errors.ts +++ b/src/vs/base/common/errors.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IAction } from 'vs/base/common/actions'; import { TPromise, IPromiseError, IPromiseErrorDetail } from 'vs/base/common/winjs.base'; // ------ BEGIN Hook up error listeners to winjs promises @@ -233,28 +232,6 @@ export function disposed(what: string): Error { return result; } -export interface IErrorOptions { - actions?: IAction[]; -} - -export interface IErrorWithActions { - actions?: IAction[]; -} - -export function isErrorWithActions(obj: any): obj is IErrorWithActions { - return obj instanceof Error && Array.isArray((obj as IErrorWithActions).actions); -} - -export function create(message: string, options: IErrorOptions = Object.create(null)): Error & IErrorWithActions { - const result = new Error(message); - - if (options.actions) { - (result).actions = options.actions; - } - - return result; -} - export function getErrorMessage(err: any): string { if (!err) { return 'Error'; diff --git a/src/vs/base/common/errorsWithActions.ts b/src/vs/base/common/errorsWithActions.ts new file mode 100644 index 00000000000..6b77eb5c7b1 --- /dev/null +++ b/src/vs/base/common/errorsWithActions.ts @@ -0,0 +1,28 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IAction } from 'vs/base/common/actions'; + +export interface IErrorOptions { + actions?: IAction[]; +} + +export interface IErrorWithActions { + actions?: IAction[]; +} + +export function isErrorWithActions(obj: any): obj is IErrorWithActions { + return obj instanceof Error && Array.isArray((obj as IErrorWithActions).actions); +} + +export function createErrorWithActions(message: string, options: IErrorOptions = Object.create(null)): Error & IErrorWithActions { + const result = new Error(message); + + if (options.actions) { + (result).actions = options.actions; + } + + return result; +} diff --git a/src/vs/base/common/event.ts b/src/vs/base/common/event.ts index 431960a43f2..0447231832d 100644 --- a/src/vs/base/common/event.ts +++ b/src/vs/base/common/event.ts @@ -56,13 +56,16 @@ export class Emitter { private static readonly _noop = function () { }; - private _event: Event; + private _event: Event | null; private _disposed: boolean; - private _deliveryQueue: [Listener, T][]; - protected _listeners: LinkedList; - - constructor(private _options?: EmitterOptions) { + private _deliveryQueue: [Listener, (T | undefined)][] | null; + protected _listeners: LinkedList | null; + constructor(private _options: EmitterOptions | null = null) { + this._event = null; + this._disposed = false; + this._deliveryQueue = null; + this._listeners = null; } /** @@ -98,8 +101,11 @@ export class Emitter { result.dispose = Emitter._noop; if (!this._disposed) { remove(); - if (this._options && this._options.onLastListenerRemove && this._listeners.isEmpty()) { - this._options.onLastListenerRemove(this); + if (this._options && this._options.onLastListenerRemove) { + const hasListeners = (this._listeners && !this._listeners.isEmpty()); + if (!hasListeners) { + this._options.onLastListenerRemove(this); + } } } } @@ -133,7 +139,7 @@ export class Emitter { } while (this._deliveryQueue.length > 0) { - const [listener, event] = this._deliveryQueue.shift(); + const [listener, event] = this._deliveryQueue.shift()!; try { if (typeof listener === 'function') { listener.call(undefined, event); @@ -149,7 +155,7 @@ export class Emitter { dispose() { if (this._listeners) { - this._listeners = undefined; + this._listeners = null; } if (this._deliveryQueue) { this._deliveryQueue.length = 0; @@ -184,7 +190,7 @@ export class AsyncEmitter extends Emitter { } while (this._asyncDeliveryQueue.length > 0) { - const [listener, event, thenables] = this._asyncDeliveryQueue.shift(); + const [listener, event, thenables] = this._asyncDeliveryQueue.shift()!; try { if (typeof listener === 'function') { listener.call(undefined, event); @@ -208,7 +214,7 @@ export class EventMultiplexer implements IDisposable { private readonly emitter: Emitter; private hasListeners = false; - private events: { event: Event; listener: IDisposable; }[] = []; + private events: { event: Event; listener: IDisposable | null; }[] = []; constructor() { this.emitter = new Emitter({ @@ -251,12 +257,14 @@ export class EventMultiplexer implements IDisposable { this.events.forEach(e => this.unhook(e)); } - private hook(e: { event: Event; listener: IDisposable; }): void { + private hook(e: { event: Event; listener: IDisposable | null; }): void { e.listener = e.event(r => this.emitter.fire(r)); } - private unhook(e: { event: Event; listener: IDisposable; }): void { - e.listener.dispose(); + private unhook(e: { event: Event; listener: IDisposable | null; }): void { + if (e.listener) { + e.listener.dispose(); + } e.listener = null; } @@ -270,7 +278,7 @@ export function fromPromise(promise: Thenable): Event { let shouldEmit = false; promise - .then(null, () => null) + .then(undefined, () => null) .then(() => { if (!shouldEmit) { setTimeout(() => emitter.fire(), 0); @@ -321,11 +329,11 @@ export function anyEvent(...events: Event[]): Event { } export function debounceEvent(event: Event, merger: (last: T, event: T) => T, delay?: number, leading?: boolean): Event; -export function debounceEvent(event: Event, merger: (last: O, event: I) => O, delay?: number, leading?: boolean): Event; -export function debounceEvent(event: Event, merger: (last: O, event: I) => O, delay: number = 100, leading = false): Event { +export function debounceEvent(event: Event, merger: (last: O | undefined, event: I) => O, delay?: number, leading?: boolean): Event; +export function debounceEvent(event: Event, merger: (last: O | undefined, event: I) => O, delay: number = 100, leading = false): Event { let subscription: IDisposable; - let output: O = undefined; + let output: O | undefined = undefined; let handle: any = undefined; let numDebouncedCalls = 0; @@ -497,10 +505,10 @@ export function stopwatch(event: Event): Event { * // 4 * ``` */ -export function buffer(event: Event, nextTick = false, buffer: T[] = []): Event { - buffer = buffer.slice(); +export function buffer(event: Event, nextTick = false, _buffer: T[] = []): Event { + let buffer: T[] | null = _buffer.slice(); - let listener = event(e => { + let listener: IDisposable | null = event(e => { if (buffer) { buffer.push(e); } else { @@ -509,7 +517,9 @@ export function buffer(event: Event, nextTick = false, buffer: T[] = []): }); const flush = () => { - buffer.forEach(e => emitter.fire(e)); + if (buffer) { + buffer.forEach(e => emitter.fire(e)); + } buffer = null; }; @@ -531,7 +541,9 @@ export function buffer(event: Event, nextTick = false, buffer: T[] = []): }, onLastListenerRemove() { - listener.dispose(); + if (listener) { + listener.dispose(); + } listener = null; } }); diff --git a/src/vs/base/common/filters.ts b/src/vs/base/common/filters.ts index ac4f6b73538..9a3eab50363 100644 --- a/src/vs/base/common/filters.ts +++ b/src/vs/base/common/filters.ts @@ -9,7 +9,7 @@ import * as strings from 'vs/base/common/strings'; export interface IFilter { // Returns null if word doesn't match. - (word: string, wordToMatchAgainst: string): IMatch[]; + (word: string, wordToMatchAgainst: string): IMatch[] | null; } export interface IMatch { @@ -26,7 +26,7 @@ export interface IMatch { * filter. */ export function or(...filter: IFilter[]): IFilter { - return function (word: string, wordToMatchAgainst: string): IMatch[] { + return function (word: string, wordToMatchAgainst: string): IMatch[] | null { for (let i = 0, len = filter.length; i < len; i++) { let match = filter[i](word, wordToMatchAgainst); if (match) { @@ -42,7 +42,7 @@ export function or(...filter: IFilter[]): IFilter { export const matchesStrictPrefix: IFilter = _matchesPrefix.bind(undefined, false); export const matchesPrefix: IFilter = _matchesPrefix.bind(undefined, true); -function _matchesPrefix(ignoreCase: boolean, word: string, wordToMatchAgainst: string): IMatch[] { +function _matchesPrefix(ignoreCase: boolean, word: string, wordToMatchAgainst: string): IMatch[] | null { if (!wordToMatchAgainst || wordToMatchAgainst.length < word.length) { return null; } @@ -63,7 +63,7 @@ function _matchesPrefix(ignoreCase: boolean, word: string, wordToMatchAgainst: s // Contiguous Substring -export function matchesContiguousSubString(word: string, wordToMatchAgainst: string): IMatch[] { +export function matchesContiguousSubString(word: string, wordToMatchAgainst: string): IMatch[] | null { let index = wordToMatchAgainst.toLowerCase().indexOf(word.toLowerCase()); if (index === -1) { return null; @@ -74,18 +74,18 @@ export function matchesContiguousSubString(word: string, wordToMatchAgainst: str // Substring -export function matchesSubString(word: string, wordToMatchAgainst: string): IMatch[] { +export function matchesSubString(word: string, wordToMatchAgainst: string): IMatch[] | null { return _matchesSubString(word.toLowerCase(), wordToMatchAgainst.toLowerCase(), 0, 0); } -function _matchesSubString(word: string, wordToMatchAgainst: string, i: number, j: number): IMatch[] { +function _matchesSubString(word: string, wordToMatchAgainst: string, i: number, j: number): IMatch[] | null { if (i === word.length) { return []; } else if (j === wordToMatchAgainst.length) { return null; } else { if (word[i] === wordToMatchAgainst[j]) { - let result: IMatch[] = null; + let result: IMatch[] | null = null; if (result = _matchesSubString(word, wordToMatchAgainst, i + 1, j + 1)) { return join({ start: j, end: j + 1 }, result); } @@ -144,7 +144,7 @@ function nextAnchor(camelCaseWord: string, start: number): number { return camelCaseWord.length; } -function _matchesCamelCase(word: string, camelCaseWord: string, i: number, j: number): IMatch[] { +function _matchesCamelCase(word: string, camelCaseWord: string, i: number, j: number): IMatch[] | null { if (i === word.length) { return []; } else if (j === camelCaseWord.length) { @@ -152,7 +152,7 @@ function _matchesCamelCase(word: string, camelCaseWord: string, i: number, j: nu } else if (word[i] !== camelCaseWord[j].toLowerCase()) { return null; } else { - let result: IMatch[] = null; + let result: IMatch[] | null = null; let nextUpperIndex = j + 1; result = _matchesCamelCase(word, camelCaseWord, i + 1, j + 1); while (!result && (nextUpperIndex = nextAnchor(camelCaseWord, nextUpperIndex)) < camelCaseWord.length) { @@ -222,7 +222,7 @@ function isCamelCasePattern(word: string): boolean { } } -export function matchesCamelCase(word: string, camelCaseWord: string): IMatch[] { +export function matchesCamelCase(word: string, camelCaseWord: string): IMatch[] | null { if (!camelCaseWord) { return null; } @@ -251,7 +251,7 @@ export function matchesCamelCase(word: string, camelCaseWord: string): IMatch[] camelCaseWord = camelCaseWord.toLowerCase(); } - let result: IMatch[] = null; + let result: IMatch[] | null = null; let i = 0; word = word.toLowerCase(); @@ -267,12 +267,12 @@ export function matchesCamelCase(word: string, camelCaseWord: string): IMatch[] // Otherwise also matches sub string of the word with beginnings of the words in the target. E.g. "gp" or "g p" will match "Git: Pull" // Useful in cases where the target is words (e.g. command labels) -export function matchesWords(word: string, target: string, contiguous: boolean = false): IMatch[] { +export function matchesWords(word: string, target: string, contiguous: boolean = false): IMatch[] | null { if (!target || target.length === 0) { return null; } - let result: IMatch[] = null; + let result: IMatch[] | null = null; let i = 0; word = word.toLowerCase(); @@ -284,7 +284,7 @@ export function matchesWords(word: string, target: string, contiguous: boolean = return result; } -function _matchesWords(word: string, target: string, i: number, j: number, contiguous: boolean): IMatch[] { +function _matchesWords(word: string, target: string, i: number, j: number, contiguous: boolean): IMatch[] | null { if (i === word.length) { return []; } else if (j === target.length) { @@ -292,7 +292,7 @@ function _matchesWords(word: string, target: string, i: number, j: number, conti } else if (word[i] !== target[j]) { return null; } else { - let result: IMatch[] = null; + let result: IMatch[] | null = null; let nextWordIndex = j + 1; result = _matchesWords(word, target, i + 1, j + 1, contiguous); if (!contiguous) { @@ -321,7 +321,7 @@ export const fuzzyContiguousFilter = or(matchesPrefix, matchesCamelCase, matches const fuzzySeparateFilter = or(matchesPrefix, matchesCamelCase, matchesSubString); const fuzzyRegExpCache = new LRUCache(10000); // bounded to 10000 elements -export function matchesFuzzy(word: string, wordToMatchAgainst: string, enableSeparateSubstringMatching = false): IMatch[] { +export function matchesFuzzy(word: string, wordToMatchAgainst: string, enableSeparateSubstringMatching = false): IMatch[] | null { if (typeof word !== 'string' || typeof wordToMatchAgainst !== 'string') { return null; // return early for invalid input } @@ -334,7 +334,7 @@ export function matchesFuzzy(word: string, wordToMatchAgainst: string, enableSep } // RegExp Filter - let match: RegExpExecArray = regexp.exec(wordToMatchAgainst); + let match = regexp.exec(wordToMatchAgainst); if (match) { return [{ start: match.index, end: match.index + match[0].length }]; } @@ -372,7 +372,7 @@ export function createMatches(offsetOrScore: number[] | FuzzyScore): IMatch[] { } else { offsets = offsetOrScore as number[]; } - let last: IMatch; + let last: IMatch | undefined; for (const pos of offsets) { if (last && last.end === pos) { last.end += 1; @@ -466,7 +466,7 @@ export interface FuzzyScorer { (pattern: string, lowPattern: string, patternPos: number, word: string, lowWord: string, wordPos: number, firstMatchCanBeWeak: boolean): FuzzyScore; } -export function fuzzyScore(pattern: string, lowPattern: string, patternPos: number, word: string, lowWord: string, wordPos: number, firstMatchCanBeWeak: boolean): FuzzyScore { +export function fuzzyScore(pattern: string, lowPattern: string, patternPos: number, word: string, lowWord: string, wordPos: number, firstMatchCanBeWeak: boolean): FuzzyScore | undefined { const patternLen = pattern.length > 100 ? 100 : pattern.length; const wordLen = word.length > 100 ? 100 : word.length; @@ -711,16 +711,16 @@ class LazyArray { //#region --- graceful --- -export function fuzzyScoreGracefulAggressive(pattern: string, lowPattern: string, patternPos: number, word: string, lowWord: string, wordPos: number, firstMatchCanBeWeak: boolean): FuzzyScore { +export function fuzzyScoreGracefulAggressive(pattern: string, lowPattern: string, patternPos: number, word: string, lowWord: string, wordPos: number, firstMatchCanBeWeak: boolean): FuzzyScore | undefined { return fuzzyScoreWithPermutations(pattern, lowPattern, patternPos, word, lowWord, wordPos, true, firstMatchCanBeWeak); } -export function fuzzyScoreGraceful(pattern: string, lowPattern: string, patternPos: number, word: string, lowWord: string, wordPos: number, firstMatchCanBeWeak: boolean): FuzzyScore { +export function fuzzyScoreGraceful(pattern: string, lowPattern: string, patternPos: number, word: string, lowWord: string, wordPos: number, firstMatchCanBeWeak: boolean): FuzzyScore | undefined { return fuzzyScoreWithPermutations(pattern, lowPattern, patternPos, word, lowWord, wordPos, false, firstMatchCanBeWeak); } -function fuzzyScoreWithPermutations(pattern: string, lowPattern: string, patternPos: number, word: string, lowWord: string, wordPos: number, aggressive: boolean, firstMatchCanBeWeak: boolean): FuzzyScore { - let top: [number, number[]] = fuzzyScore(pattern, lowPattern, patternPos, word, lowWord, wordPos, firstMatchCanBeWeak); +function fuzzyScoreWithPermutations(pattern: string, lowPattern: string, patternPos: number, word: string, lowWord: string, wordPos: number, aggressive: boolean, firstMatchCanBeWeak: boolean): FuzzyScore | undefined { + let top = fuzzyScore(pattern, lowPattern, patternPos, word, lowWord, wordPos, firstMatchCanBeWeak); if (top && !aggressive) { // when using the original pattern yield a result we` @@ -752,7 +752,7 @@ function fuzzyScoreWithPermutations(pattern: string, lowPattern: string, pattern return top; } -function nextTypoPermutation(pattern: string, patternPos: number): string { +function nextTypoPermutation(pattern: string, patternPos: number): string | undefined { if (patternPos + 1 >= pattern.length) { return undefined; diff --git a/src/vs/base/common/glob.ts b/src/vs/base/common/glob.ts index 09853098d2e..cb4771b2d3c 100644 --- a/src/vs/base/common/glob.ts +++ b/src/vs/base/common/glob.ts @@ -248,7 +248,7 @@ const T5 = /^([\w\.-]+(\/[\w\.-]+)*)\/?$/; // something/else export type ParsedPattern = (path: string, basename?: string) => boolean; // The ParsedExpression returns a Promise iff hasSibling returns a Promise. -export type ParsedExpression = (path: string, basename?: string, hasSibling?: (name: string) => boolean | TPromise) => string | TPromise /* the matching pattern */; +export type ParsedExpression = (path: string, basename?: string, hasSibling?: (name: string) => boolean | TPromise) => string | null | TPromise /* the matching pattern */; export interface IGlobOptions { /** @@ -258,14 +258,14 @@ export interface IGlobOptions { } interface ParsedStringPattern { - (path: string, basename: string): string | TPromise /* the matching pattern */; + (path: string, basename: string): string | null | TPromise /* the matching pattern */; basenames?: string[]; patterns?: string[]; allBasenames?: string[]; allPaths?: string[]; } interface ParsedExpressionPattern { - (path: string, basename: string, name: string, hasSibling: (name: string) => boolean | TPromise): string | TPromise /* the matching pattern */; + (path: string, basename: string, name?: string, hasSibling?: (name: string) => boolean | TPromise): string | null | TPromise /* the matching pattern */; requiresSiblings?: boolean; allBasenames?: string[]; allPaths?: string[]; @@ -277,7 +277,7 @@ const FALSE = function () { return false; }; -const NULL = function (): string { +const NULL = function (): string | null { return null; }; @@ -305,7 +305,7 @@ function parsePattern(arg1: string | IRelativePattern, options: IGlobOptions): P } // Check for Trivias - let match: RegExpExecArray; + let match: RegExpExecArray | null; if (T1.test(pattern)) { // common pattern: **/*.txt just need endsWith check const base = pattern.substr(4); // '**/*'.length === 4 parsedPattern = function (path, basename) { @@ -530,7 +530,7 @@ export function isRelativePattern(obj: any): obj is IRelativePattern { */ export function parseToAsync(expression: IExpression, options?: IGlobOptions): ParsedExpression { const parsedExpression = parse(expression, options); - return (path: string, basename?: string, hasSibling?: (name: string) => boolean | TPromise): string | TPromise => { + return (path: string, basename?: string, hasSibling?: (name: string) => boolean | TPromise): string | null | TPromise => { const result = parsedExpression(path, basename, hasSibling); return result instanceof TPromise ? result : TPromise.as(result); }; @@ -554,7 +554,7 @@ function parsedExpression(expression: IExpression, options: IGlobOptions): Parse return NULL; } - if (!parsedPatterns.some(parsedPattern => (parsedPattern).requiresSiblings)) { + if (!parsedPatterns.some(parsedPattern => !!(parsedPattern).requiresSiblings)) { if (n === 1) { return parsedPatterns[0]; } @@ -585,7 +585,7 @@ function parsedExpression(expression: IExpression, options: IGlobOptions): Parse } const resultExpression: ParsedStringPattern = function (path: string, basename: string, hasSibling?: (name: string) => boolean | TPromise) { - let name: string; + let name: string | undefined = undefined; for (let i = 0, n = parsedPatterns.length; i < n; i++) { // Pattern matches path @@ -665,7 +665,10 @@ function aggregateBasenameMatches(parsedPatterns: (ParsedStringPattern | ParsedE return parsedPatterns; } - const basenames = basenamePatterns.reduce((all, current) => all.concat((current).basenames), []); + const basenames = basenamePatterns.reduce((all, current) => { + const basenames = (current).basenames; + return basenames ? all.concat(basenames) : all; + }, []); let patterns: string[]; if (result) { patterns = []; @@ -673,7 +676,10 @@ function aggregateBasenameMatches(parsedPatterns: (ParsedStringPattern | ParsedE patterns.push(result); } } else { - patterns = basenamePatterns.reduce((all, current) => all.concat((current).patterns), []); + patterns = basenamePatterns.reduce((all, current) => { + const patterns = (current).patterns; + return patterns ? all.concat(patterns) : all; + }, []); } const aggregate: ParsedStringPattern = function (path, basename) { if (!path) { diff --git a/src/vs/base/common/hash.ts b/src/vs/base/common/hash.ts index 18aac042f16..613c5e307fc 100644 --- a/src/vs/base/common/hash.ts +++ b/src/vs/base/common/hash.ts @@ -22,9 +22,9 @@ export function hash(obj: any, hashVal = 0): number { case 'number': return numberHash(obj, hashVal); case 'undefined': - return numberHash(obj, 937); + return numberHash(0, 937); default: - return numberHash(obj, 617); + return numberHash(0, 617); } } diff --git a/src/vs/base/common/history.ts b/src/vs/base/common/history.ts index 5bc83979f67..95551eb1a7a 100644 --- a/src/vs/base/common/history.ts +++ b/src/vs/base/common/history.ts @@ -27,27 +27,27 @@ export class HistoryNavigator implements INavigator { this._onChange(); } - public next(): T { + public next(): T | null { return this._navigator.next(); } - public previous(): T { + public previous(): T | null { return this._navigator.previous(); } - public current(): T { + public current(): T | null { return this._navigator.current(); } - public parent(): T { + public parent(): null { return null; } - public first(): T { + public first(): T | null { return this._navigator.first(); } - public last(): T { + public last(): T | null { return this._navigator.last(); } diff --git a/src/vs/base/common/iterator.ts b/src/vs/base/common/iterator.ts index 78f2117a656..038bf263222 100644 --- a/src/vs/base/common/iterator.ts +++ b/src/vs/base/common/iterator.ts @@ -3,10 +3,16 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -export interface IteratorResult { - readonly done: boolean; - readonly value: T | undefined; +export interface IteratorDefinedResult { + readonly done: false; + readonly value: T; } +export interface IteratorUndefinedResult { + readonly done: true; + readonly value: undefined; +} +export const FIN: IteratorUndefinedResult = { done: true, value: undefined }; +export type IteratorResult = IteratorDefinedResult | IteratorUndefinedResult; export interface Iterator { next(): IteratorResult; @@ -15,7 +21,7 @@ export interface Iterator { export module Iterator { const _empty: Iterator = { next() { - return { done: true, value: undefined }; + return FIN; } }; @@ -27,7 +33,7 @@ export module Iterator { return { next(): IteratorResult { if (index >= length) { - return { done: true, value: undefined }; + return FIN; } return { done: false, value: array[index++] }; @@ -48,8 +54,12 @@ export module Iterator { export function map(iterator: Iterator, fn: (t: T) => R): Iterator { return { next() { - const { done, value } = iterator.next(); - return { done, value: done ? undefined : fn(value) }; + const element = iterator.next(); + if (element.done) { + return FIN; + } else { + return { done: false, value: fn(element.value) }; + } } }; } @@ -58,14 +68,12 @@ export module Iterator { return { next() { while (true) { - const { done, value } = iterator.next(); - - if (done) { - return { done, value: undefined }; + const element = iterator.next(); + if (element.done) { + return FIN; } - - if (fn(value)) { - return { done, value }; + if (fn(element.value)) { + return { done: false, value: element.value }; } } } @@ -96,7 +104,7 @@ export function getSequenceIterator(arg: Iterator | T[]): Iterator { } export interface INextIterator { - next(): T; + next(): T | null; } export class ArrayIterator implements INextIterator { @@ -113,17 +121,17 @@ export class ArrayIterator implements INextIterator { this.index = index; } - public first(): T { + public first(): T | null { this.index = this.start; return this.current(); } - public next(): T { + public next(): T | null { this.index = Math.min(this.index + 1, this.end); return this.current(); } - protected current(): T { + protected current(): T | null { if (this.index === this.start - 1 || this.index === this.end) { return null; } @@ -138,34 +146,33 @@ export class ArrayNavigator extends ArrayIterator implements INavigator super(items, start, end, index); } - public current(): T { + public current(): T | null { return super.current(); } - public previous(): T { + public previous(): T | null { this.index = Math.max(this.index - 1, this.start - 1); return this.current(); } - public first(): T { + public first(): T | null { this.index = this.start; return this.current(); } - public last(): T { + public last(): T | null { this.index = this.end - 1; return this.current(); } - public parent(): T { + public parent(): T | null { return null; } - } export class MappedIterator implements INextIterator { - constructor(protected iterator: INextIterator, protected fn: (item: T) => R) { + constructor(protected iterator: INextIterator, protected fn: (item: T | null) => R) { // noop } @@ -173,12 +180,12 @@ export class MappedIterator implements INextIterator { } export interface INavigator extends INextIterator { - current(): T; - previous(): T; - parent(): T; - first(): T; - last(): T; - next(): T; + current(): T | null; + previous(): T | null; + parent(): T | null; + first(): T | null; + last(): T | null; + next(): T | null; } export class MappedNavigator extends MappedIterator implements INavigator { diff --git a/src/vs/base/common/json.ts b/src/vs/base/common/json.ts index 1c812fc2801..1cfaa1f4201 100644 --- a/src/vs/base/common/json.ts +++ b/src/vs/base/common/json.ts @@ -636,7 +636,7 @@ export interface ParseOptions { * Therefore always check the errors list to find out if the input was valid. */ export function parse(text: string, errors: ParseError[] = [], options?: ParseOptions): any { - let currentProperty: string = null; + let currentProperty: string | null = null; let currentParent: any = []; let previousParents: any[] = []; diff --git a/src/vs/base/common/keyCodes.ts b/src/vs/base/common/keyCodes.ts index 097578a6697..74352496c07 100644 --- a/src/vs/base/common/keyCodes.ts +++ b/src/vs/base/common/keyCodes.ts @@ -410,7 +410,7 @@ export function KeyChord(firstPart: number, secondPart: number): number { return (firstPart | chordPart) >>> 0; } -export function createKeybinding(keybinding: number, OS: OperatingSystem): Keybinding { +export function createKeybinding(keybinding: number, OS: OperatingSystem): Keybinding | null { if (keybinding === 0) { return null; } diff --git a/src/vs/base/common/keybindingParser.ts b/src/vs/base/common/keybindingParser.ts index 98f17d809d8..99b05253dc8 100644 --- a/src/vs/base/common/keybindingParser.ts +++ b/src/vs/base/common/keybindingParser.ts @@ -80,13 +80,13 @@ export class KeybindingParser { return [new SimpleKeybinding(mods.ctrl, mods.shift, mods.alt, mods.meta, keyCode), mods.remains]; } - public static parseKeybinding(input: string, OS: OperatingSystem): Keybinding { + public static parseKeybinding(input: string, OS: OperatingSystem): Keybinding | null { if (!input) { return null; } let [firstPart, remains] = this.parseSimpleKeybinding(input); - let chordPart: SimpleKeybinding = null; + let chordPart: SimpleKeybinding | null = null; if (remains.length > 0) { [chordPart] = this.parseSimpleKeybinding(remains); } @@ -109,13 +109,13 @@ export class KeybindingParser { return [new SimpleKeybinding(mods.ctrl, mods.shift, mods.alt, mods.meta, keyCode), mods.remains]; } - static parseUserBinding(input: string): [SimpleKeybinding | ScanCodeBinding, SimpleKeybinding | ScanCodeBinding] { + static parseUserBinding(input: string): [SimpleKeybinding | ScanCodeBinding | null, SimpleKeybinding | ScanCodeBinding | null] { if (!input) { return [null, null]; } let [firstPart, remains] = this.parseSimpleUserBinding(input); - let chordPart: SimpleKeybinding | ScanCodeBinding = null; + let chordPart: SimpleKeybinding | ScanCodeBinding | null = null; if (remains.length > 0) { [chordPart] = this.parseSimpleUserBinding(remains); } diff --git a/src/vs/base/common/labels.ts b/src/vs/base/common/labels.ts index 9310456816e..e171497848a 100644 --- a/src/vs/base/common/labels.ts +++ b/src/vs/base/common/labels.ts @@ -24,9 +24,9 @@ export interface IUserHomeProvider { /** * @deprecated use LabelService instead */ -export function getPathLabel(resource: URI | string, userHomeProvider: IUserHomeProvider, rootProvider?: IWorkspaceFolderProvider): string { +export function getPathLabel(resource: URI | string, userHomeProvider: IUserHomeProvider, rootProvider?: IWorkspaceFolderProvider): string | undefined { if (!resource) { - return null; + return undefined; } if (typeof resource === 'string') { @@ -34,23 +34,25 @@ export function getPathLabel(resource: URI | string, userHomeProvider: IUserHome } // return early if we can resolve a relative path label from the root - const baseResource = rootProvider ? rootProvider.getWorkspaceFolder(resource) : null; - if (baseResource) { - const hasMultipleRoots = rootProvider.getWorkspace().folders.length > 1; + if (rootProvider) { + const baseResource = rootProvider.getWorkspaceFolder(resource); + if (baseResource) { + const hasMultipleRoots = rootProvider.getWorkspace().folders.length > 1; - let pathLabel: string; - if (isEqual(baseResource.uri, resource, !isLinux)) { - pathLabel = ''; // no label if paths are identical - } else { - pathLabel = normalize(ltrim(resource.path.substr(baseResource.uri.path.length), sep), true); + let pathLabel: string; + if (isEqual(baseResource.uri, resource, !isLinux)) { + pathLabel = ''; // no label if paths are identical + } else { + pathLabel = normalize(ltrim(resource.path.substr(baseResource.uri.path.length), sep)!, true); + } + + if (hasMultipleRoots) { + const rootName = (baseResource && baseResource.name) ? baseResource.name : pathsBasename(baseResource.uri.fsPath); + pathLabel = pathLabel ? (rootName + ' • ' + pathLabel) : rootName; // always show root basename if there are multiple + } + + return pathLabel; } - - if (hasMultipleRoots) { - const rootName = (baseResource && baseResource.name) ? baseResource.name : pathsBasename(baseResource.uri.fsPath); - pathLabel = pathLabel ? (rootName + ' • ' + pathLabel) : rootName; // always show root basename if there are multiple - } - - return pathLabel; } // return if the resource is neither file:// nor untitled:// and no baseResource was provided @@ -72,9 +74,9 @@ export function getPathLabel(resource: URI | string, userHomeProvider: IUserHome return res; } -export function getBaseLabel(resource: URI | string): string { +export function getBaseLabel(resource: URI | string): string | undefined { if (!resource) { - return null; + return undefined; } if (typeof resource === 'string') { @@ -92,7 +94,7 @@ export function getBaseLabel(resource: URI | string): string { } function hasDriveLetter(path: string): boolean { - return isWindows && path && path[1] === ':'; + return !!(isWindows && path && path[1] === ':'); } export function normalizeDriveLetter(path: string): string { diff --git a/src/vs/base/common/lifecycle.ts b/src/vs/base/common/lifecycle.ts index 8b44cd2c687..405752fdb57 100644 --- a/src/vs/base/common/lifecycle.ts +++ b/src/vs/base/common/lifecycle.ts @@ -17,7 +17,7 @@ export function isDisposable(thing: E): thing is E & IDisposab export function dispose(disposable: T): T; export function dispose(...disposables: T[]): T[]; export function dispose(disposables: T[]): T[]; -export function dispose(first: T | T[], ...rest: T[]): T | T[] { +export function dispose(first: T | T[], ...rest: T[]): T | T[] | undefined { if (Array.isArray(first)) { first.forEach(d => d && d.dispose()); return []; diff --git a/src/vs/base/common/linkedList.ts b/src/vs/base/common/linkedList.ts index 97b02a163fd..898586f29ab 100644 --- a/src/vs/base/common/linkedList.ts +++ b/src/vs/base/common/linkedList.ts @@ -3,12 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Iterator } from 'vs/base/common/iterator'; +import { Iterator, IteratorResult, FIN } from 'vs/base/common/iterator'; class Node { element: E; - next: Node; - prev: Node; + next: Node | undefined; + prev: Node | undefined; constructor(element: E) { this.element = element; @@ -17,8 +17,8 @@ class Node { export class LinkedList { - private _first: Node; - private _last: Node; + private _first: Node | undefined; + private _last: Node | undefined; isEmpty(): boolean { return !this._first; @@ -45,7 +45,7 @@ export class LinkedList { } else if (atTheEnd) { // push - const oldLast = this._last; + const oldLast = this._last!; this._last = newNode; newNode.prev = oldLast; oldLast.next = newNode; @@ -59,9 +59,10 @@ export class LinkedList { } return () => { - - for (let candidate = this._first; candidate instanceof Node; candidate = candidate.next) { + let candidate: Node | undefined = this._first; + while (candidate instanceof Node) { if (candidate !== newNode) { + candidate = candidate.next; continue; } if (candidate.prev && candidate.next) { @@ -77,12 +78,12 @@ export class LinkedList { } else if (!candidate.next) { // last - this._last = this._last.prev; + this._last = this._last!.prev!; this._last.next = undefined; } else if (!candidate.prev) { // first - this._first = this._first.next; + this._first = this._first!.next!; this._first.prev = undefined; } @@ -93,21 +94,20 @@ export class LinkedList { } iterator(): Iterator { - let element = { - done: undefined, - value: undefined, - }; + let element: { done: false; value: E; }; let node = this._first; return { - next(): { done: boolean; value: E } { + next(): IteratorResult { if (!node) { - element.done = true; - element.value = undefined; - } else { - element.done = false; - element.value = node.element; - node = node.next; + return FIN; } + + if (!element) { + element = { done: false, value: node.element }; + } else { + element.value = node.element; + } + node = node.next; return element; } }; diff --git a/src/vs/base/common/map.ts b/src/vs/base/common/map.ts index 134dfe33cb1..f5c25133c5b 100644 --- a/src/vs/base/common/map.ts +++ b/src/vs/base/common/map.ts @@ -5,7 +5,7 @@ import { URI } from 'vs/base/common/uri'; import { CharCode } from 'vs/base/common/charCode'; -import { Iterator } from './iterator'; +import { Iterator, IteratorResult, FIN } from './iterator'; export function values(set: Set): V[]; export function values(map: Map): V[]; @@ -139,11 +139,11 @@ export class PathIterator implements IKeyIterator { class TernarySearchTreeNode { segment: string; - value: E; + value: E | undefined; key: string; - left: TernarySearchTreeNode; - mid: TernarySearchTreeNode; - right: TernarySearchTreeNode; + left: TernarySearchTreeNode | undefined; + mid: TernarySearchTreeNode | undefined; + right: TernarySearchTreeNode | undefined; isEmpty(): boolean { return !this.left && !this.mid && !this.right && !this.value; @@ -161,7 +161,7 @@ export class TernarySearchTree { } private _iter: IKeyIterator; - private _root: TernarySearchTreeNode; + private _root: TernarySearchTreeNode | undefined; constructor(segments: IKeyIterator) { this._iter = segments; @@ -171,7 +171,7 @@ export class TernarySearchTree { this._root = undefined; } - set(key: string, element: E): E { + set(key: string, element: E): E | undefined { let iter = this._iter.reset(key); let node: TernarySearchTreeNode; @@ -217,7 +217,7 @@ export class TernarySearchTree { return oldElement; } - get(key: string): E { + get(key: string): E | undefined { let iter = this._iter.reset(key); let node = this._root; while (node) { @@ -267,7 +267,7 @@ export class TernarySearchTree { // clean up empty nodes while (stack.length > 0 && node.isEmpty()) { - let [dir, parent] = stack.pop(); + let [dir, parent] = stack.pop()!; switch (dir) { case 1: parent.left = undefined; break; case 0: parent.mid = undefined; break; @@ -280,10 +280,10 @@ export class TernarySearchTree { } } - findSubstr(key: string): E { + findSubstr(key: string): E | undefined { let iter = this._iter.reset(key); let node = this._root; - let candidate: E; + let candidate: E | undefined = undefined; while (node) { let val = iter.cmp(node.segment); if (val > 0) { @@ -304,7 +304,7 @@ export class TernarySearchTree { return node && node.value || candidate; } - findSuperstr(key: string): Iterator { + findSuperstr(key: string): Iterator | undefined { let iter = this._iter.reset(key); let node = this._root; while (node) { @@ -332,13 +332,10 @@ export class TernarySearchTree { } private _nodeIterator(node: TernarySearchTreeNode): Iterator { - let res = { - done: false, - value: undefined - }; + let res: { done: false; value: E; }; let idx: number; let data: E[]; - let next = () => { + let next = (): IteratorResult => { if (!data) { // lazy till first invocation data = []; @@ -346,10 +343,12 @@ export class TernarySearchTree { this._forEach(node, value => data.push(value)); } if (idx >= data.length) { - res.done = true; - res.value = undefined; + return FIN; + } + + if (!res) { + res = { done: false, value: data[idx++] }; } else { - res.done = false; res.value = data[idx++]; } return res; @@ -361,7 +360,7 @@ export class TernarySearchTree { this._forEach(this._root, callback); } - private _forEach(node: TernarySearchTreeNode, callback: (value: E, index: string) => any) { + private _forEach(node: TernarySearchTreeNode | undefined, callback: (value: E, index: string) => any) { if (node) { // left this._forEach(node.left, callback); @@ -649,7 +648,9 @@ export class LinkedMap { } this._head = current; this._size = currentSize; - current.previous = void 0; + if (current) { + current.previous = void 0; + } } private addItemFirst(item: Item): void { diff --git a/src/vs/base/common/objects.ts b/src/vs/base/common/objects.ts index 2cc8e033d2b..5e90f440f07 100644 --- a/src/vs/base/common/objects.ts +++ b/src/vs/base/common/objects.ts @@ -218,7 +218,7 @@ export function safeStringify(obj: any): string { }); } -export function getOrDefault(obj: T, fn: (obj: T) => R, defaultValue: R = null): R { +export function getOrDefault(obj: T, fn: (obj: T) => R, defaultValue: R | null = null): R | null { const result = fn(obj); return typeof result === 'undefined' ? defaultValue : result; } diff --git a/src/vs/base/common/paths.ts b/src/vs/base/common/paths.ts index f1a63a8d5b0..b2b255b0f1b 100644 --- a/src/vs/base/common/paths.ts +++ b/src/vs/base/common/paths.ts @@ -83,7 +83,7 @@ export function normalize(path: string, toOSPath?: boolean): string { return '.'; } - const wantsBackslash = isWindows && toOSPath; + const wantsBackslash = !!(isWindows && toOSPath); if (_isNormal(path, wantsBackslash)) { return path; } @@ -398,5 +398,5 @@ export function isAbsolute_win32(path: string): boolean { } export function isAbsolute_posix(path: string): boolean { - return path && path.charCodeAt(0) === CharCode.Slash; + return !!(path && path.charCodeAt(0) === CharCode.Slash); } diff --git a/src/vs/base/common/platform.ts b/src/vs/base/common/platform.ts index 9e3496c8160..4b703fc900a 100644 --- a/src/vs/base/common/platform.ts +++ b/src/vs/base/common/platform.ts @@ -8,9 +8,9 @@ let _isMacintosh = false; let _isLinux = false; let _isNative = false; let _isWeb = false; -let _locale: string = undefined; -let _language: string = undefined; -let _translationsConfigFile: string = undefined; +let _locale: string | undefined = undefined; +let _language: string | undefined = undefined; +let _translationsConfigFile: string | undefined = undefined; interface NLSConfig { locale: string; @@ -129,7 +129,7 @@ export const translationsConfigFile = _translationsConfigFile; const _globals = (typeof self === 'object' ? self : typeof global === 'object' ? global : {} as any); export const globals: any = _globals; -let _setImmediate: (callback: (...args: any[]) => void) => number = null; +let _setImmediate: ((callback: (...args: any[]) => void) => number) | null = null; export function setImmediate(callback: (...args: any[]) => void): number { if (_setImmediate === null) { if (globals.setImmediate) { @@ -140,7 +140,7 @@ export function setImmediate(callback: (...args: any[]) => void): number { _setImmediate = globals.setTimeout.bind(globals); } } - return _setImmediate(callback); + return _setImmediate!(callback); } export const enum OperatingSystem { diff --git a/src/vs/base/common/resources.ts b/src/vs/base/common/resources.ts index 811d2f38d79..7df851fa3db 100644 --- a/src/vs/base/common/resources.ts +++ b/src/vs/base/common/resources.ts @@ -72,7 +72,7 @@ export function basename(resource: URI): string { * @param resource The input URI. * @returns The URI representing the directory of the input URI. */ -export function dirname(resource: URI): URI { +export function dirname(resource: URI): URI | null { let dirname = paths.dirname(resource.path, '/'); if (resource.authority && dirname.length && dirname.charCodeAt(0) !== CharCode.Slash) { return null; // If a URI contains an authority component, then the path component must either be empty or begin with a CharCode.Slash ("/") character diff --git a/src/vs/base/common/scrollable.ts b/src/vs/base/common/scrollable.ts index 398ced04031..b31cc9f5223 100644 --- a/src/vs/base/common/scrollable.ts +++ b/src/vs/base/common/scrollable.ts @@ -182,7 +182,7 @@ export class Scrollable extends Disposable { private _smoothScrollDuration: number; private readonly _scheduleAtNextAnimationFrame: (callback: () => void) => IDisposable; private _state: ScrollState; - private _smoothScrolling: SmoothScrollingOperation; + private _smoothScrolling: SmoothScrollingOperation | null; private _onScroll = this._register(new Emitter()); public readonly onScroll: Event = this._onScroll.event; @@ -300,6 +300,9 @@ export class Scrollable extends Disposable { } private _performSmoothScrolling(): void { + if (!this._smoothScrolling) { + return; + } const update = this._smoothScrolling.tick(); const newState = this._state.withScrollPosition(update); @@ -372,7 +375,7 @@ export class SmoothScrollingOperation { public to: ISmoothScrollPosition; public readonly duration: number; private readonly _startTime: number; - public animationFrameDisposable: IDisposable; + public animationFrameDisposable: IDisposable | null; private scrollLeft: IAnimation; private scrollTop: IAnimation; diff --git a/src/vs/base/common/strings.ts b/src/vs/base/common/strings.ts index 40f273531a6..7c6a9820fbe 100644 --- a/src/vs/base/common/strings.ts +++ b/src/vs/base/common/strings.ts @@ -78,7 +78,7 @@ export function escapeRegExpCharacters(value: string): string { * @param haystack string to trim * @param needle the thing to trim (default is a blank) */ -export function trim(haystack: string, needle: string = ' '): string { +export function trim(haystack: string, needle: string = ' '): string | undefined { let trimmed = ltrim(haystack, needle); return rtrim(trimmed, needle); } @@ -88,7 +88,7 @@ export function trim(haystack: string, needle: string = ' '): string { * @param haystack string to trim * @param needle the thing to trim */ -export function ltrim(haystack?: string, needle?: string): string { +export function ltrim(haystack: string, needle: string): string { if (!haystack || !needle) { return haystack; } @@ -111,7 +111,7 @@ export function ltrim(haystack?: string, needle?: string): string { * @param haystack string to trim * @param needle the thing to trim */ -export function rtrim(haystack?: string, needle?: string): string { +export function rtrim(haystack: string, needle: string): string { if (!haystack || !needle) { return haystack; } @@ -229,7 +229,7 @@ export function regExpLeadsToEndlessLoop(regexp: RegExp): boolean { // We check against an empty string. If the regular expression doesn't advance // (e.g. ends in an endless loop) it will match an empty string. let match = regexp.exec(''); - return (match && regexp.lastIndex === 0); + return !!(match && regexp.lastIndex === 0); } export function regExpContainsBackreference(regexpValue: string): boolean { @@ -621,7 +621,7 @@ export function removeAnsiEscapeCodes(str: string): string { export const UTF8_BOM_CHARACTER = String.fromCharCode(CharCode.UTF8_BOM); export function startsWithUTF8BOM(str: string): boolean { - return (str && str.length > 0 && str.charCodeAt(0) === CharCode.UTF8_BOM); + return !!(str && str.length > 0 && str.charCodeAt(0) === CharCode.UTF8_BOM); } export function stripUTF8BOM(str: string): string { diff --git a/src/vs/base/common/types.ts b/src/vs/base/common/types.ts index 865c7f0e0bf..31591c49df1 100644 --- a/src/vs/base/common/types.ts +++ b/src/vs/base/common/types.ts @@ -129,14 +129,14 @@ export function areFunctions(...objects: any[]): boolean { export type TypeConstraint = string | Function; -export function validateConstraints(args: any[], constraints: TypeConstraint[]): void { +export function validateConstraints(args: any[], constraints: (TypeConstraint | undefined)[]): void { const len = Math.min(args.length, constraints.length); for (let i = 0; i < len; i++) { validateConstraint(args[i], constraints[i]); } } -export function validateConstraint(arg: any, constraint: TypeConstraint): void { +export function validateConstraint(arg: any, constraint: TypeConstraint | undefined): void { if (isString(constraint)) { if (typeof arg !== constraint) { diff --git a/src/vs/base/common/uri.ts b/src/vs/base/common/uri.ts index 3ce4b48c95b..c0d3423e240 100644 --- a/src/vs/base/common/uri.ts +++ b/src/vs/base/common/uri.ts @@ -141,7 +141,7 @@ export class URI implements UriComponents { /** * @internal */ - protected constructor(scheme: string, authority: string, path: string, query: string, fragment: string); + protected constructor(scheme: string, authority?: string, path?: string, query?: string, fragment?: string); /** * @internal @@ -386,8 +386,8 @@ interface UriState extends UriComponents { // tslint:disable-next-line:class-name class _URI extends URI { - _formatted: string = null; - _fsPath: string = null; + _formatted: string | null = null; + _fsPath: string | null = null; get fsPath(): string { if (!this._fsPath) { @@ -465,7 +465,7 @@ const encodeTable: { [ch: number]: string } = { }; function encodeURIComponentFast(uriComponent: string, allowSlash: boolean, firstPos: number = 0): string { - let res: string = undefined; + let res: string | undefined = undefined; let nativeEncodePos = -1; for (let pos = firstPos; pos < uriComponent.length; pos++) { @@ -526,7 +526,7 @@ function encodeURIComponentFast(uriComponent: string, allowSlash: boolean, first } function encodeURIComponentMinimal(path: string): string { - let res: string = undefined; + let res: string | undefined = undefined; for (let pos = 0; pos < path.length; pos++) { let code = path.charCodeAt(pos); if (code === CharCode.Hash || code === CharCode.QuestionMark) { diff --git a/src/vs/base/common/worker/simpleWorker.ts b/src/vs/base/common/worker/simpleWorker.ts index c55e76ee6f1..08531cd3459 100644 --- a/src/vs/base/common/worker/simpleWorker.ts +++ b/src/vs/base/common/worker/simpleWorker.ts @@ -84,24 +84,18 @@ class SimpleWorkerProtocol { public sendMessage(method: string, args: any[]): Promise { let req = String(++this._lastSentReq); - let reply: IMessageReply = { - resolve: null, - reject: null - }; - let result = new Promise((resolve, reject) => { - reply.resolve = resolve; - reply.reject = reject; + return new Promise((resolve, reject) => { + this._pendingReplies[req] = { + resolve: resolve, + reject: reject + }; + this._send({ + vsWorker: this._workerId, + req: req, + method: method, + args: args + }); }); - this._pendingReplies[req] = reply; - - this._send({ - vsWorker: this._workerId, - req: req, - method: method, - args: args - }); - - return result; } public handleMessage(serializedMessage: string): void { @@ -110,6 +104,7 @@ class SimpleWorkerProtocol { message = JSON.parse(serializedMessage); } catch (e) { // nothing + return; } if (!message || !message.vsWorker) { return; @@ -191,8 +186,7 @@ export class SimpleWorkerClient extends Disposable { constructor(workerFactory: IWorkerFactory, moduleId: string) { super(); - let lazyProxyResolve: (v: T) => void = null; - let lazyProxyReject: (err: any) => void = null; + let lazyProxyReject: ((err: any) => void) | null = null; this._worker = this._register(workerFactory.create( 'vs/base/common/worker/simpleWorker', @@ -202,7 +196,9 @@ export class SimpleWorkerClient extends Disposable { (err: any) => { // in Firefox, web workers fail lazily :( // we will reject the proxy - lazyProxyReject(err); + if (lazyProxyReject) { + lazyProxyReject(err); + } } )); @@ -227,26 +223,25 @@ export class SimpleWorkerClient extends Disposable { loaderConfiguration = (self).requirejs.s.contexts._.config; } - this._lazyProxy = new Promise((resolve, reject) => { - lazyProxyResolve = resolve; - lazyProxyReject = reject; - }); - // Send initialize message this._onModuleLoaded = this._protocol.sendMessage(INITIALIZE, [ this._worker.getId(), moduleId, loaderConfiguration ]); - this._onModuleLoaded.then((availableMethods: string[]) => { - let proxy = {}; - for (let i = 0; i < availableMethods.length; i++) { - (proxy as any)[availableMethods[i]] = createProxyMethod(availableMethods[i], proxyMethodRequest); - } - lazyProxyResolve(proxy); - }, (e) => { - lazyProxyReject(e); - this._onError('Worker failed to load ' + moduleId, e); + + this._lazyProxy = new Promise((resolve, reject) => { + lazyProxyReject = reject; + this._onModuleLoaded.then((availableMethods: string[]) => { + let proxy = {}; + for (let i = 0; i < availableMethods.length; i++) { + (proxy as any)[availableMethods[i]] = createProxyMethod(availableMethods[i], proxyMethodRequest); + } + resolve(proxy); + }, (e) => { + reject(e); + this._onError('Worker failed to load ' + moduleId, e); + }); }); // Create proxy to loaded code @@ -290,10 +285,10 @@ export interface IRequestHandler { */ export class SimpleWorkerServer { - private _requestHandler: IRequestHandler; + private _requestHandler: IRequestHandler | null; private _protocol: SimpleWorkerProtocol; - constructor(postSerializedMessage: (msg: string) => void, requestHandler: IRequestHandler) { + constructor(postSerializedMessage: (msg: string) => void, requestHandler: IRequestHandler | null) { this._requestHandler = requestHandler; this._protocol = new SimpleWorkerProtocol({ sendMessage: (msg: string): void => { @@ -353,29 +348,27 @@ export class SimpleWorkerServer { (self).require.config(loaderConfig); } - let resolve: (value?: string[]) => void; - let reject: (error?: any) => void; - let r = new Promise((_resolve, _reject) => { - resolve = _resolve; - reject = _reject; - }); + return new Promise((resolve, reject) => { + // Use the global require to be sure to get the global config + (self).require([moduleId], (...result: any[]) => { + let handlerModule = result[0]; + this._requestHandler = handlerModule.create(); - // Use the global require to be sure to get the global config - (self).require([moduleId], (...result: any[]) => { - let handlerModule = result[0]; - this._requestHandler = handlerModule.create(); - - let methods: string[] = []; - for (let prop in this._requestHandler) { - if (typeof this._requestHandler[prop] === 'function') { - methods.push(prop); + if (!this._requestHandler) { + reject(new Error(`No RequestHandler!`)); + return; } - } - resolve(methods); - }, reject); + let methods: string[] = []; + for (let prop in this._requestHandler) { + if (typeof this._requestHandler[prop] === 'function') { + methods.push(prop); + } + } - return r; + resolve(methods); + }, reject); + }); } } diff --git a/src/vs/base/node/decoder.ts b/src/vs/base/node/decoder.ts index 8d5c85906b2..5ef4abf19f7 100644 --- a/src/vs/base/node/decoder.ts +++ b/src/vs/base/node/decoder.ts @@ -16,7 +16,7 @@ import { CharCode } from 'vs/base/common/charCode'; */ export class LineDecoder { private stringDecoder: sd.NodeStringDecoder; - private remaining: string; + private remaining: string | null; constructor(encoding: string = 'utf8') { this.stringDecoder = new sd.StringDecoder(encoding); @@ -56,7 +56,7 @@ export class LineDecoder { return result; } - public end(): string { + public end(): string | null { return this.remaining; } } \ No newline at end of file diff --git a/src/vs/base/node/extfs.ts b/src/vs/base/node/extfs.ts index a68494a325d..2ac37d7e9cc 100644 --- a/src/vs/base/node/extfs.ts +++ b/src/vs/base/node/extfs.ts @@ -252,7 +252,7 @@ function rmRecursive(path: string, callback: (error: Error) => void): void { } else if (children.length === 0) { fs.rmdir(path, callback); } else { - let firstError: Error = null; + let firstError: Error | null = null; let childrenLeft = children.length; children.forEach(child => { rmRecursive(paths.join(path, child), (err: Error) => { @@ -643,7 +643,7 @@ export function watch(path: string, onChange: (type: string, path?: string) => v const watcher = fs.watch(path); watcher.on('change', (type, raw) => { - let file: string = null; + let file: string | null = null; if (raw) { // https://github.com/Microsoft/vscode/issues/38191 file = raw.toString(); if (platform.isMacintosh) { diff --git a/src/vs/base/node/id.ts b/src/vs/base/node/id.ts index 4bb03b40ec3..2ee6601aad0 100644 --- a/src/vs/base/node/id.ts +++ b/src/vs/base/node/id.ts @@ -45,7 +45,7 @@ export const virtualMachineHint: { value(): number } = new class { this._virtualMachineOUIs.set('00:16:3E', true); this._virtualMachineOUIs.set('08:00:27', true); } - return this._virtualMachineOUIs.findSubstr(mac); + return !!this._virtualMachineOUIs.findSubstr(mac); } value(): number { diff --git a/src/vs/base/node/pfs.ts b/src/vs/base/node/pfs.ts index 153b1c300fb..f559e86c97c 100644 --- a/src/vs/base/node/pfs.ts +++ b/src/vs/base/node/pfs.ts @@ -157,7 +157,7 @@ export function fileExists(path: string): Promise { /** * Deletes a path from disk. */ -let _tmpDir: string = null; +let _tmpDir: string | null = null; function getTmpDir(): string { if (!_tmpDir) { _tmpDir = os.tmpdir(); diff --git a/src/vs/base/parts/quickopen/browser/quickOpenModel.ts b/src/vs/base/parts/quickopen/browser/quickOpenModel.ts index 141a41e5990..4855968e00a 100644 --- a/src/vs/base/parts/quickopen/browser/quickOpenModel.ts +++ b/src/vs/base/parts/quickopen/browser/quickOpenModel.ts @@ -328,7 +328,7 @@ class Renderer implements IRenderer { private actionProvider: IActionProvider; private actionRunner: IActionRunner; - constructor(actionProvider: IActionProvider = new NoActionProvider(), actionRunner: IActionRunner = null) { + constructor(actionProvider: IActionProvider = new NoActionProvider(), actionRunner: IActionRunner | null = null) { this.actionProvider = actionProvider; this.actionRunner = actionRunner; } diff --git a/src/vs/base/parts/tree/browser/treeImpl.ts b/src/vs/base/parts/tree/browser/treeImpl.ts index db01cf9b38a..63f217de9ec 100644 --- a/src/vs/base/parts/tree/browser/treeImpl.ts +++ b/src/vs/base/parts/tree/browser/treeImpl.ts @@ -179,7 +179,7 @@ export class Tree implements _.ITree { return this.model.collapse(element, recursive); } - public collapseAll(elements: any[] = null, recursive: boolean = false): WinJS.Promise { + public collapseAll(elements: any[] | null = null, recursive: boolean = false): WinJS.Promise { return this.model.collapseAll(elements, recursive); } @@ -199,7 +199,7 @@ export class Tree implements _.ITree { return this.model.getExpandedElements(); } - public reveal(element: any, relativeTop: number = null): WinJS.Promise { + public reveal(element: any, relativeTop: number | null = null): WinJS.Promise { return this.model.reveal(element, relativeTop); } diff --git a/src/vs/base/parts/tree/browser/treeModel.ts b/src/vs/base/parts/tree/browser/treeModel.ts index 097b8b2b9bf..9b4049178bb 100644 --- a/src/vs/base/parts/tree/browser/treeModel.ts +++ b/src/vs/base/parts/tree/browser/treeModel.ts @@ -346,7 +346,7 @@ export class Item { this.expanded = value; } - public reveal(relativeTop: number = null): void { + public reveal(relativeTop: number | null = null): void { var eventData: IItemRevealEvent = { item: this, relativeTop: relativeTop }; this._onDidReveal.fire(eventData); } @@ -838,8 +838,8 @@ function getRange(one: Item, other: Item): Item[] { var item = oneHierarchy[length - 1]; var nav = item.getNavigator(); - var oneIndex: number = null; - var otherIndex: number = null; + var oneIndex: number | null = null; + var otherIndex: number | null = null; var index = 0; var result: Item[] = []; @@ -1030,7 +1030,7 @@ export class TreeModel { return item.collapse(recursive); } - public collapseAll(elements: any[] = null, recursive: boolean = false): WinJS.Promise { + public collapseAll(elements: any[] | null = null, recursive: boolean = false): WinJS.Promise { if (!elements) { elements = [this.input]; recursive = true; @@ -1078,7 +1078,7 @@ export class TreeModel { return result; } - public reveal(element: any, relativeTop: number = null): WinJS.Promise { + public reveal(element: any, relativeTop: number | null = null): WinJS.Promise { return this.resolveUnknownParentChain(element).then((chain: any[]) => { var result = WinJS.TPromise.as(null); @@ -1221,8 +1221,8 @@ export class TreeModel { public selectPrevious(count: number = 1, clearSelection: boolean = true, eventPayload?: any): void { var selection = this.getSelection(), - item: Item = null, - previousItem: Item = null; + item: Item | null = null, + previousItem: Item | null = null; if (selection.length === 0) { let nav = this.getNavigator(this.input); diff --git a/src/vs/base/parts/tree/browser/treeView.ts b/src/vs/base/parts/tree/browser/treeView.ts index 392aa4c7bc4..47431675779 100644 --- a/src/vs/base/parts/tree/browser/treeView.ts +++ b/src/vs/base/parts/tree/browser/treeView.ts @@ -1657,7 +1657,7 @@ export class TreeView extends HeightMap { // DOM changes private insertItemInDOM(item: ViewItem): void { - var elementAfter: HTMLElement = null; + var elementAfter: HTMLElement | null = null; var itemAfter = this.itemAfter(item); if (itemAfter && itemAfter.element) { diff --git a/src/vs/base/parts/tree/browser/treeViewModel.ts b/src/vs/base/parts/tree/browser/treeViewModel.ts index 0238c16102f..ee14736039f 100644 --- a/src/vs/base/parts/tree/browser/treeViewModel.ts +++ b/src/vs/base/parts/tree/browser/treeViewModel.ts @@ -28,7 +28,7 @@ export class HeightMap { return !last ? 0 : last.top + last.height; } - public onInsertItems(iterator: INextIterator, afterItemId: string = null): number { + public onInsertItems(iterator: INextIterator, afterItemId: string | null = null): number { var item: Item; var viewItem: IViewItem; var i: number, j: number; @@ -90,7 +90,7 @@ export class HeightMap { public onRemoveItems(iterator: INextIterator): void { var itemId: string; var viewItem: IViewItem; - var startIndex: number = null; + var startIndex: number | null = null; var i: number; var sizeDiff = 0; @@ -140,7 +140,7 @@ export class HeightMap { var item: Item; var viewItem: IViewItem; var newHeight: number; - var i: number, j: number = null; + var i: number, j: number | null = null; var cummDiff = 0; while (item = iterator.next()) { diff --git a/src/vs/base/worker/defaultWorkerFactory.ts b/src/vs/base/worker/defaultWorkerFactory.ts index d14213cb98a..a089a443094 100644 --- a/src/vs/base/worker/defaultWorkerFactory.ts +++ b/src/vs/base/worker/defaultWorkerFactory.ts @@ -31,7 +31,7 @@ function getWorker(workerId: string, label: string): Worker { class WebWorker implements IWorker { private id: number; - private worker: Worker; + private worker: Worker | null; constructor(moduleId: string, id: number, label: string, onMessageCallback: IWorkerCallback, onErrorCallback: (err: any) => void) { this.id = id; @@ -56,7 +56,9 @@ class WebWorker implements IWorker { } public dispose(): void { - this.worker.terminate(); + if (this.worker) { + this.worker.terminate(); + } this.worker = null; } } diff --git a/src/vs/base/worker/workerMain.ts b/src/vs/base/worker/workerMain.ts index 9bf45f0b202..986e3ea4da9 100644 --- a/src/vs/base/worker/workerMain.ts +++ b/src/vs/base/worker/workerMain.ts @@ -27,7 +27,7 @@ self.onmessage = (e) => messageHandler.onmessage(e.data); while (beforeReadyMessages.length > 0) { - self.onmessage(beforeReadyMessages.shift()); + self.onmessage(beforeReadyMessages.shift()!); } }, 0); }); diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts index 7ef2e0704bb..5b574e3f341 100644 --- a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts @@ -99,7 +99,7 @@ function main(server: Server, initData: ISharedProcessInitData, configuration: I telemetryLogService.info('The below are logs for every telemetry event sent from VS Code once the log level is set to trace.'); telemetryLogService.info('==========================================================='); - let appInsightsAppender: ITelemetryAppender = NullAppender; + let appInsightsAppender: ITelemetryAppender | null = NullAppender; if (product.aiConfig && product.aiConfig.asimovKey && isBuilt) { appInsightsAppender = new AppInsightsAppender(eventPrefix, null, product.aiConfig.asimovKey, telemetryLogService); disposables.push(appInsightsAppender); // Ensure the AI appender is disposed so that it flushes remaining data diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 2c048bdec2d..44464ac8044 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -556,7 +556,7 @@ export class CodeApplication { private afterWindowOpen(accessor: ServicesAccessor): void { const windowsMainService = accessor.get(IWindowsMainService); - let windowsMutex: Mutex = null; + let windowsMutex: Mutex | null = null; if (platform.isWindows) { // Setup Windows mutex diff --git a/src/vs/code/electron-main/theme.ts b/src/vs/code/electron-main/theme.ts index 17617cce010..cd0f4bf02f4 100644 --- a/src/vs/code/electron-main/theme.ts +++ b/src/vs/code/electron-main/theme.ts @@ -19,7 +19,7 @@ export function getBackgroundColor(stateService: IStateService): string { return DEFAULT_BG_HC_BLACK; } - let background = stateService.getItem(THEME_BG_STORAGE_KEY, null); + let background = stateService.getItem(THEME_BG_STORAGE_KEY, null); if (!background) { let baseTheme: string; if (isWindows && systemPreferences.isInvertedColorScheme()) { diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index d1eb97bfe9f..95cd7498c28 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -57,6 +57,8 @@ export class CodeWindow implements ICodeWindow { private static readonly MIN_WIDTH = 200; private static readonly MIN_HEIGHT = 120; + private static readonly MAX_URL_LENGTH = 2 * 1024 * 1024; // https://cs.chromium.org/chromium/src/url/url_constants.cc?l=32 + private hiddenTitleBarStyle: boolean; private showTimeoutHandle: any; private _id: number; @@ -605,11 +607,30 @@ export class CodeWindow implements ICodeWindow { const environment = parseArgs(process.argv); const config = objects.assign(environment, windowConfiguration); for (let key in config) { - if (config[key] === void 0 || config[key] === null || config[key] === '') { + if (config[key] === void 0 || config[key] === null || config[key] === '' || config[key] === false) { delete config[key]; // only send over properties that have a true value } } + // In the unlikely event of the URL becoming larger than 2MB, remove parts of + // it that are not under our control. Mainly, the user environment can be very + // large depending on user configuration, so we can only remove it in that case. + let configUrl = this.doGetUrl(config); + if (configUrl.length > CodeWindow.MAX_URL_LENGTH) { + delete config.userEnv; + this.logService.warn('Application URL exceeds maximum of 2MB and was shortened.'); + + configUrl = this.doGetUrl(config); + + if (configUrl.length > CodeWindow.MAX_URL_LENGTH) { + this.logService.error('Application URL exceeds maximum of 2MB and cannot be loaded.'); + } + } + + return configUrl; + } + + private doGetUrl(config: object): string { return `${require.toUrl('vs/code/electron-browser/workbench/workbench.html')}?config=${encodeURIComponent(JSON.stringify(config))}`; } diff --git a/src/vs/code/node/paths.ts b/src/vs/code/node/paths.ts index cdc14af2197..5774c6b6265 100644 --- a/src/vs/code/node/paths.ts +++ b/src/vs/code/node/paths.ts @@ -99,8 +99,8 @@ export function parseLineAndColumnAware(rawPath: string): IPathWithLineAndColumn const segments = rawPath.split(':'); // C:\file.txt:: let path: string; - let line: number = null; - let column: number = null; + let line: number | null = null; + let column: number | null = null; segments.forEach(segment => { const segmentAsNumber = Number(segment); diff --git a/src/vs/code/node/shellEnv.ts b/src/vs/code/node/shellEnv.ts index 0ad8d4040f0..5ea15be5ecf 100644 --- a/src/vs/code/node/shellEnv.ts +++ b/src/vs/code/node/shellEnv.ts @@ -21,7 +21,7 @@ function getUnixShellEnvironment(): Promise { }); const command = `'${process.execPath}' -p '"${mark}" + JSON.stringify(process.env) + "${mark}"'`; - const child = cp.spawn(process.env.SHELL, ['-ilc', command], { + const child = cp.spawn(process.env.SHELL!, ['-ilc', command], { detached: true, stdio: ['ignore', 'pipe', process.stderr], env @@ -66,7 +66,7 @@ function getUnixShellEnvironment(): Promise { }); // swallow errors - return promise.then(null, () => ({})); + return promise.then(undefined, () => ({})); } diff --git a/src/vs/editor/browser/config/charWidthReader.ts b/src/vs/editor/browser/config/charWidthReader.ts index 3d92f7a4ba3..9f35141df60 100644 --- a/src/vs/editor/browser/config/charWidthReader.ts +++ b/src/vs/editor/browser/config/charWidthReader.ts @@ -33,8 +33,8 @@ class DomCharWidthReader { private readonly _bareFontInfo: BareFontInfo; private readonly _requests: CharWidthRequest[]; - private _container: HTMLElement; - private _testElements: HTMLSpanElement[]; + private _container: HTMLElement | null; + private _testElements: HTMLSpanElement[] | null; constructor(bareFontInfo: BareFontInfo, requests: CharWidthRequest[]) { this._bareFontInfo = bareFontInfo; @@ -49,13 +49,13 @@ class DomCharWidthReader { this._createDomElements(); // Add the container to the DOM - document.body.appendChild(this._container); + document.body.appendChild(this._container!); // Read character widths this._readFromDomElements(); // Remove the container from the DOM - document.body.removeChild(this._container); + document.body.removeChild(this._container!); this._container = null; this._testElements = null; @@ -107,11 +107,11 @@ class DomCharWidthReader { parent = italicDomNode; } - parent.appendChild(document.createElement('br')); + parent!.appendChild(document.createElement('br')); let testElement = document.createElement('span'); DomCharWidthReader._render(testElement, request); - parent.appendChild(testElement); + parent!.appendChild(testElement); testElements[i] = testElement; } @@ -141,7 +141,7 @@ class DomCharWidthReader { private _readFromDomElements(): void { for (let i = 0, len = this._requests.length; i < len; i++) { const request = this._requests[i]; - const testElement = this._testElements[i]; + const testElement = this._testElements![i]; request.fulfill(testElement.offsetWidth / 256); } diff --git a/src/vs/editor/browser/config/configuration.ts b/src/vs/editor/browser/config/configuration.ts index 6714a598967..8fcec327df1 100644 --- a/src/vs/editor/browser/config/configuration.ts +++ b/src/vs/editor/browser/config/configuration.ts @@ -62,7 +62,7 @@ export function restoreFontInfo(nextStorage2Service: INextStorage2Service): void if (typeof strStoredFontInfo !== 'string') { return; } - let storedFontInfo: ISerializedFontInfo[] = null; + let storedFontInfo: ISerializedFontInfo[] | null = null; try { storedFontInfo = JSON.parse(strStoredFontInfo); } catch (err) { @@ -321,7 +321,7 @@ export class Configuration extends CommonEditorConfiguration { private readonly _elementSizeObserver: ElementSizeObserver; - constructor(options: IEditorOptions, referenceDomElement: HTMLElement = null) { + constructor(options: IEditorOptions, referenceDomElement: HTMLElement | null = null) { super(options); this._elementSizeObserver = this._register(new ElementSizeObserver(referenceDomElement, () => this._onReferenceDomElementSizeChanged())); diff --git a/src/vs/editor/browser/controller/coreCommands.ts b/src/vs/editor/browser/controller/coreCommands.ts index 9a6b68ffe5d..dd0be15c2dd 100644 --- a/src/vs/editor/browser/controller/coreCommands.ts +++ b/src/vs/editor/browser/controller/coreCommands.ts @@ -7,7 +7,7 @@ import * as nls from 'vs/nls'; import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; -import { CursorState, ICursors, RevealTarget, IColumnSelectData, CursorContext, EditOperationType } from 'vs/editor/common/controller/cursorCommon'; +import { CursorState, ICursors, RevealTarget, IColumnSelectData, CursorContext, EditOperationType, PartialCursorState } from 'vs/editor/common/controller/cursorCommon'; import { CursorChangeReason } from 'vs/editor/common/controller/cursorEvents'; import { CursorMoveCommands, CursorMove as CursorMove_ } from 'vs/editor/common/controller/cursorMoveCommands'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; @@ -703,14 +703,14 @@ export namespace CoreNavigationCommands { public runCoreEditorCommand(cursors: ICursors, args: any): void { const context = cursors.context; - let newState: CursorState; + let newState: PartialCursorState; if (args.wholeLine) { newState = CursorMoveCommands.line(context, cursors.getPrimaryCursor(), false, args.position, args.viewPosition); } else { newState = CursorMoveCommands.moveTo(context, cursors.getPrimaryCursor(), false, args.position, args.viewPosition); } - const states = cursors.getAll(); + const states: PartialCursorState[] = cursors.getAll(); // Check if we should remove a cursor (sort of like a toggle) if (states.length > 1) { @@ -766,8 +766,9 @@ export namespace CoreNavigationCommands { const lastAddedCursorIndex = cursors.getLastAddedCursorIndex(); - let newStates = cursors.getAll().slice(0); - newStates[lastAddedCursorIndex] = CursorMoveCommands.moveTo(context, newStates[lastAddedCursorIndex], true, args.position, args.viewPosition); + const states = cursors.getAll(); + let newStates: PartialCursorState[] = states.slice(0); + newStates[lastAddedCursorIndex] = CursorMoveCommands.moveTo(context, states[lastAddedCursorIndex], true, args.position, args.viewPosition); cursors.context.model.pushStackElement(); cursors.setStates( @@ -846,8 +847,8 @@ export namespace CoreNavigationCommands { cursors.reveal(true, RevealTarget.Primary, editorCommon.ScrollType.Smooth); } - private _exec(context: CursorContext, cursors: CursorState[]): CursorState[] { - let result: CursorState[] = []; + private _exec(context: CursorContext, cursors: CursorState[]): PartialCursorState[] { + let result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; const lineNumber = cursor.modelState.position.lineNumber; @@ -925,8 +926,8 @@ export namespace CoreNavigationCommands { cursors.reveal(true, RevealTarget.Primary, editorCommon.ScrollType.Smooth); } - private _exec(context: CursorContext, cursors: CursorState[]): CursorState[] { - let result: CursorState[] = []; + private _exec(context: CursorContext, cursors: CursorState[]): PartialCursorState[] { + let result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; const lineNumber = cursor.modelState.position.lineNumber; @@ -1245,8 +1246,9 @@ export namespace CoreNavigationCommands { const lastAddedCursorIndex = cursors.getLastAddedCursorIndex(); - let newStates = cursors.getAll().slice(0); - let lastAddedState = newStates[lastAddedCursorIndex]; + const states = cursors.getAll(); + let newStates: PartialCursorState[] = states.slice(0); + let lastAddedState = states[lastAddedCursorIndex]; newStates[lastAddedCursorIndex] = CursorMoveCommands.word(context, lastAddedState, lastAddedState.modelState.hasSelection(), args.position); context.model.pushStackElement(); @@ -1302,8 +1304,9 @@ export namespace CoreNavigationCommands { public runCoreEditorCommand(cursors: ICursors, args: any): void { const lastAddedCursorIndex = cursors.getLastAddedCursorIndex(); - let newStates = cursors.getAll().slice(0); - newStates[lastAddedCursorIndex] = CursorMoveCommands.line(cursors.context, newStates[lastAddedCursorIndex], this._inSelectionMode, args.position, args.viewPosition); + const states = cursors.getAll(); + let newStates: PartialCursorState[] = states.slice(0); + newStates[lastAddedCursorIndex] = CursorMoveCommands.line(cursors.context, states[lastAddedCursorIndex], this._inSelectionMode, args.position, args.viewPosition); cursors.context.model.pushStackElement(); cursors.setStates( diff --git a/src/vs/editor/browser/controller/mouseTarget.ts b/src/vs/editor/browser/controller/mouseTarget.ts index 943643ac49b..159fcfbdc34 100644 --- a/src/vs/editor/browser/controller/mouseTarget.ts +++ b/src/vs/editor/browser/controller/mouseTarget.ts @@ -97,7 +97,7 @@ export class MouseTarget implements IMouseTarget { public readonly range: EditorRange; public readonly detail: any; - constructor(element: Element, type: MouseTargetType, mouseColumn: number = 0, position: Position = null, range: EditorRange = null, detail: any = null) { + constructor(element: Element, type: MouseTargetType, mouseColumn: number = 0, position: Position | null = null, range: EditorRange | null = null, detail: any = null) { this.element = element; this.type = type; this.mouseColumn = mouseColumn; @@ -258,9 +258,9 @@ export class HitTestContext { if (viewZoneWhitespace) { let viewZoneMiddle = viewZoneWhitespace.verticalOffset + viewZoneWhitespace.height / 2, lineCount = context.model.getLineCount(), - positionBefore: Position = null, + positionBefore: Position | null = null, position: Position, - positionAfter: Position = null; + positionAfter: Position | null = null; if (viewZoneWhitespace.afterLineNumber !== lineCount) { // There are more lines after this view zone @@ -406,7 +406,7 @@ class HitTestRequest extends BareHitTestRequest { return `pos(${this.pos.x},${this.pos.y}), editorPos(${this.editorPos.x},${this.editorPos.y}), mouseVerticalOffset: ${this.mouseVerticalOffset}, mouseContentHorizontalOffset: ${this.mouseContentHorizontalOffset}\n\ttarget: ${this.target ? (this.target).outerHTML : null}`; } - public fulfill(type: MouseTargetType, position: Position = null, range: EditorRange = null, detail: any = null): MouseTarget { + public fulfill(type: MouseTargetType, position: Position | null = null, range: EditorRange | null = null, detail: any = null): MouseTarget { return new MouseTarget(this.target, type, this.mouseColumn, position, range, detail); } @@ -484,7 +484,7 @@ export class MouseTargetFactory { return this._createMouseTarget(ctx, request.withTarget(hitTestResult.hitTarget), true); } - let result: MouseTarget = null; + let result: MouseTarget | null = null; result = result || MouseTargetFactory._hitTestContentWidget(ctx, request); result = result || MouseTargetFactory._hitTestOverlayWidget(ctx, request); @@ -895,8 +895,8 @@ export class MouseTargetFactory { * Most probably IE */ private static _doHitTestWithMoveToPoint(ctx: HitTestContext, coords: ClientCoordinates): IHitTestResult { - let resultPosition: Position = null; - let resultHitTarget: Element = null; + let resultPosition: Position | null = null; + let resultHitTarget: Element | null = null; let textRange: IETextRange = (document.body).createTextRange(); try { diff --git a/src/vs/editor/browser/controller/textAreaHandler.ts b/src/vs/editor/browser/controller/textAreaHandler.ts index 5626d51f04d..b8fb25c0914 100644 --- a/src/vs/editor/browser/controller/textAreaHandler.ts +++ b/src/vs/editor/browser/controller/textAreaHandler.ts @@ -172,7 +172,7 @@ export class TextAreaHandler extends ViewPart { const multicursorText = (Array.isArray(rawWhatToCopy) ? rawWhatToCopy : null); const whatToCopy = (Array.isArray(rawWhatToCopy) ? rawWhatToCopy.join(newLineCharacter) : rawWhatToCopy); - let metadata: LocalClipboardMetadata = null; + let metadata: LocalClipboardMetadata | null = null; if (isFromEmptySelection || multicursorText) { // Only store the non-default metadata @@ -250,7 +250,7 @@ export class TextAreaHandler extends ViewPart { const metadata = LocalClipboardMetadataManager.INSTANCE.get(e.text); let pasteOnNewLine = false; - let multicursorText: string[] = null; + let multicursorText: string[] | null = null; if (metadata) { pasteOnNewLine = (this._emptySelectionClipboard && metadata.isFromEmptySelection); multicursorText = metadata.multicursorText; @@ -442,7 +442,7 @@ export class TextAreaHandler extends ViewPart { // --- end view API - private _primaryCursorVisibleRange: HorizontalRange = null; + private _primaryCursorVisibleRange: HorizontalRange | null = null; public prepareRender(ctx: RenderingContext): void { if (this._accessibilitySupport === platform.AccessibilitySupport.Enabled) { diff --git a/src/vs/editor/browser/controller/textAreaInput.ts b/src/vs/editor/browser/controller/textAreaInput.ts index 1e28ba6b950..d39dbf29792 100644 --- a/src/vs/editor/browser/controller/textAreaInput.ts +++ b/src/vs/editor/browser/controller/textAreaInput.ts @@ -479,7 +479,7 @@ export class TextAreaInput extends Disposable { return; } - let copyHTML: string = null; + let copyHTML: string | null = null; if (browser.hasClipboardSupport() && (copyPlainText.length < 65536 || CopyOptions.forceCopyWithSyntaxHighlighting)) { copyHTML = this._host.getHTMLToCopy(); } diff --git a/src/vs/editor/browser/controller/textAreaState.ts b/src/vs/editor/browser/controller/textAreaState.ts index aacee92053d..4f1dc67db86 100644 --- a/src/vs/editor/browser/controller/textAreaState.ts +++ b/src/vs/editor/browser/controller/textAreaState.ts @@ -35,10 +35,10 @@ export class TextAreaState { public readonly value: string; public readonly selectionStart: number; public readonly selectionEnd: number; - public readonly selectionStartPosition: Position; - public readonly selectionEndPosition: Position; + public readonly selectionStartPosition: Position | null; + public readonly selectionEndPosition: Position | null; - constructor(value: string, selectionStart: number, selectionEnd: number, selectionStartPosition: Position, selectionEndPosition: Position) { + constructor(value: string, selectionStart: number, selectionEnd: number, selectionStartPosition: Position | null, selectionEndPosition: Position | null) { this.value = value; this.selectionStart = selectionStart; this.selectionEnd = selectionEnd; @@ -66,7 +66,7 @@ export class TextAreaState { } } - public deduceEditorPosition(offset: number): [Position, number, number] { + public deduceEditorPosition(offset: number): [Position | null, number, number] { if (offset <= this.selectionStart) { const str = this.value.substring(offset, this.selectionStart); return this._finishDeduceEditorPosition(this.selectionStartPosition, str, -1); @@ -83,7 +83,7 @@ export class TextAreaState { return this._finishDeduceEditorPosition(this.selectionEndPosition, str2, -1); } - private _finishDeduceEditorPosition(anchor: Position, deltaText: string, signum: number): [Position, number, number] { + private _finishDeduceEditorPosition(anchor: Position | null, deltaText: string, signum: number): [Position | null, number, number] { let lineFeedCnt = 0; let lastLineFeedIndex = -1; while ((lastLineFeedIndex = deltaText.indexOf('\n', lastLineFeedIndex + 1)) !== -1) { @@ -153,7 +153,7 @@ export class TextAreaState { // the only hints we can use is that the selection is immediately after the inserted emoji // and that none of the old text has been deleted - let potentialEmojiInput: string = null; + let potentialEmojiInput: string | null = null; if (currentSelectionStart === currentValue.length) { // emoji potentially inserted "somewhere" after the previous selection => it should appear at the end of `currentValue` @@ -247,21 +247,22 @@ export class PagedScreenReaderStrategy { let selectionEndPage = PagedScreenReaderStrategy._getPageOfLine(selection.endLineNumber); let selectionEndPageRange = PagedScreenReaderStrategy._getRangeForPage(selectionEndPage); - let pretextRange = selectionStartPageRange.intersectRanges(new Range(1, 1, selection.startLineNumber, selection.startColumn)); + let pretextRange = selectionStartPageRange.intersectRanges(new Range(1, 1, selection.startLineNumber, selection.startColumn))!; let pretext = model.getValueInRange(pretextRange, EndOfLinePreference.LF); let lastLine = model.getLineCount(); let lastLineMaxColumn = model.getLineMaxColumn(lastLine); - let posttextRange = selectionEndPageRange.intersectRanges(new Range(selection.endLineNumber, selection.endColumn, lastLine, lastLineMaxColumn)); + let posttextRange = selectionEndPageRange.intersectRanges(new Range(selection.endLineNumber, selection.endColumn, lastLine, lastLineMaxColumn))!; let posttext = model.getValueInRange(posttextRange, EndOfLinePreference.LF); - let text: string = null; + + let text: string; if (selectionStartPage === selectionEndPage || selectionStartPage + 1 === selectionEndPage) { // take full selection text = model.getValueInRange(selection, EndOfLinePreference.LF); } else { - let selectionRange1 = selectionStartPageRange.intersectRanges(selection); - let selectionRange2 = selectionEndPageRange.intersectRanges(selection); + let selectionRange1 = selectionStartPageRange.intersectRanges(selection)!; + let selectionRange2 = selectionEndPageRange.intersectRanges(selection)!; text = ( model.getValueInRange(selectionRange1, EndOfLinePreference.LF) + String.fromCharCode(8230) diff --git a/src/vs/editor/browser/core/editorState.ts b/src/vs/editor/browser/core/editorState.ts index ffa9991abb9..38d2df1be8a 100644 --- a/src/vs/editor/browser/core/editorState.ts +++ b/src/vs/editor/browser/core/editorState.ts @@ -74,7 +74,7 @@ export class EditorState { export class StableEditorScrollState { public static capture(editor: ICodeEditor): StableEditorScrollState { - let visiblePosition: Position = null; + let visiblePosition: Position | null = null; let visiblePositionScrollDelta = 0; if (editor.getScrollTop() !== 0) { const visibleRanges = editor.getVisibleRanges(); diff --git a/src/vs/editor/browser/services/abstractCodeEditorService.ts b/src/vs/editor/browser/services/abstractCodeEditorService.ts index 06c2d92afb4..646126850df 100644 --- a/src/vs/editor/browser/services/abstractCodeEditorService.ts +++ b/src/vs/editor/browser/services/abstractCodeEditorService.ts @@ -9,7 +9,6 @@ import { IModelDecorationOptions, ITextModel } from 'vs/editor/common/model'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser'; import { IResourceInput } from 'vs/platform/editor/common/editor'; -import { TPromise } from 'vs/base/common/winjs.base'; import { Disposable } from 'vs/base/common/lifecycle'; export abstract class AbstractCodeEditorService extends Disposable implements ICodeEditorService { @@ -72,7 +71,7 @@ export abstract class AbstractCodeEditorService extends Disposable implements IC } getFocusedCodeEditor(): ICodeEditor { - let editorWithWidgetFocus: ICodeEditor = null; + let editorWithWidgetFocus: ICodeEditor | null = null; let editors = this.listCodeEditors(); for (let i = 0; i < editors.length; i++) { @@ -127,7 +126,7 @@ export abstract class AbstractCodeEditorService extends Disposable implements IC } abstract getActiveCodeEditor(): ICodeEditor; - abstract openCodeEditor(input: IResourceInput, source: ICodeEditor, sideBySide?: boolean): TPromise; + abstract openCodeEditor(input: IResourceInput, source: ICodeEditor, sideBySide?: boolean): Thenable; } export class ModelTransientSettingWatcher { diff --git a/src/vs/editor/browser/services/codeEditorServiceImpl.ts b/src/vs/editor/browser/services/codeEditorServiceImpl.ts index 69bed90d22f..bed584b18d1 100644 --- a/src/vs/editor/browser/services/codeEditorServiceImpl.ts +++ b/src/vs/editor/browser/services/codeEditorServiceImpl.ts @@ -12,7 +12,6 @@ import { AbstractCodeEditorService } from 'vs/editor/browser/services/abstractCo import { IDisposable, dispose as disposeAll } from 'vs/base/common/lifecycle'; import { IThemeService, ITheme, ThemeColor } from 'vs/platform/theme/common/themeService'; import { IResourceInput } from 'vs/platform/editor/common/editor'; -import { TPromise } from 'vs/base/common/winjs.base'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; export abstract class CodeEditorServiceImpl extends AbstractCodeEditorService { @@ -68,7 +67,7 @@ export abstract class CodeEditorServiceImpl extends AbstractCodeEditorService { } abstract getActiveCodeEditor(): ICodeEditor; - abstract openCodeEditor(input: IResourceInput, source: ICodeEditor, sideBySide?: boolean): TPromise; + abstract openCodeEditor(input: IResourceInput, source: ICodeEditor, sideBySide?: boolean): Thenable; } interface IModelDecorationOptionsProvider extends IDisposable { diff --git a/src/vs/editor/browser/services/openerService.ts b/src/vs/editor/browser/services/openerService.ts index 5e08fadd765..f3f7687428c 100644 --- a/src/vs/editor/browser/services/openerService.ts +++ b/src/vs/editor/browser/services/openerService.ts @@ -22,7 +22,7 @@ export class OpenerService implements IOpenerService { constructor( @ICodeEditorService private readonly _editorService: ICodeEditorService, @ICommandService private readonly _commandService: ICommandService, - @optional(ITelemetryService) private _telemetryService: ITelemetryService = NullTelemetryService + @optional(ITelemetryService) private _telemetryService: ITelemetryService | null = NullTelemetryService ) { // } diff --git a/src/vs/editor/browser/view/viewOutgoingEvents.ts b/src/vs/editor/browser/view/viewOutgoingEvents.ts index 64677c2485e..8a337c11bb4 100644 --- a/src/vs/editor/browser/view/viewOutgoingEvents.ts +++ b/src/vs/editor/browser/view/viewOutgoingEvents.ts @@ -19,18 +19,18 @@ export interface EventCallback { export class ViewOutgoingEvents extends Disposable { - public onDidScroll: EventCallback = null; - public onDidGainFocus: EventCallback = null; - public onDidLoseFocus: EventCallback = null; - public onKeyDown: EventCallback = null; - public onKeyUp: EventCallback = null; - public onContextMenu: EventCallback = null; - public onMouseMove: EventCallback = null; - public onMouseLeave: EventCallback = null; - public onMouseUp: EventCallback = null; - public onMouseDown: EventCallback = null; - public onMouseDrag: EventCallback = null; - public onMouseDrop: EventCallback = null; + public onDidScroll: EventCallback | null = null; + public onDidGainFocus: EventCallback | null = null; + public onDidLoseFocus: EventCallback | null = null; + public onKeyDown: EventCallback | null = null; + public onKeyUp: EventCallback | null = null; + public onContextMenu: EventCallback | null = null; + public onMouseMove: EventCallback | null = null; + public onMouseLeave: EventCallback | null = null; + public onMouseUp: EventCallback | null = null; + public onMouseDown: EventCallback | null = null; + public onMouseDrag: EventCallback | null = null; + public onMouseDrop: EventCallback | null = null; private _viewModel: IViewModel; diff --git a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts index 2c2a475229b..ee7f3449a02 100644 --- a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts +++ b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts @@ -443,7 +443,7 @@ class Widget { return null; } - let placement: IBoxLayoutResult = null; + let placement: IBoxLayoutResult | null = null; let fetchPlacement = (): void => { if (placement) { return; diff --git a/src/vs/editor/browser/viewParts/decorations/decorations.ts b/src/vs/editor/browser/viewParts/decorations/decorations.ts index 77055d440d9..93e6d330d39 100644 --- a/src/vs/editor/browser/viewParts/decorations/decorations.ts +++ b/src/vs/editor/browser/viewParts/decorations/decorations.ts @@ -149,9 +149,9 @@ export class DecorationsOverlay extends DynamicViewOverlay { const lineHeight = String(this._lineHeight); const visibleStartLineNumber = ctx.visibleRange.startLineNumber; - let prevClassName: string = null; + let prevClassName: string | null = null; let prevShowIfCollapsed: boolean = false; - let prevRange: Range = null; + let prevRange: Range | null = null; for (let i = 0, lenI = decorations.length; i < lenI; i++) { const d = decorations[i]; diff --git a/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts b/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts index 9192bb5eb68..4bc3aa48849 100644 --- a/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts +++ b/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts @@ -47,7 +47,7 @@ export abstract class DedupOverlay extends DynamicViewOverlay { return (a.className < b.className ? -1 : 1); }); - let prevClassName: string = null; + let prevClassName: string | null = null; let prevEndLineIndex = 0; for (let i = 0, len = decorations.length; i < len; i++) { let d = decorations[i]; diff --git a/src/vs/editor/browser/viewParts/lines/viewLine.ts b/src/vs/editor/browser/viewParts/lines/viewLine.ts index f6664f47cee..7d2481d6dab 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLine.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLine.ts @@ -225,7 +225,7 @@ export class ViewLine implements IVisibleLine { sb.appendASCIIString(''); - let renderedViewLine: IRenderedViewLine = null; + let renderedViewLine: IRenderedViewLine | null = null; if (canUseFastRenderedViewLine && lineData.isBasicASCII && options.useMonospaceOptimizations && output.containsForeignElements === ForeignElementType.None) { if (lineData.content.length < 300 && renderLineInput.lineTokens.getCount() < 100) { // Browser rounding errors have been observed in Chrome and IE, so using the fast diff --git a/src/vs/editor/browser/viewParts/selections/selections.ts b/src/vs/editor/browser/viewParts/selections/selections.ts index c5253571d01..890dc425fa7 100644 --- a/src/vs/editor/browser/viewParts/selections/selections.ts +++ b/src/vs/editor/browser/viewParts/selections/selections.ts @@ -158,8 +158,8 @@ export class SelectionsOverlay extends DynamicViewOverlay { private _enrichVisibleRangesWithStyle(viewport: Range, linesVisibleRanges: LineVisibleRangesWithStyle[], previousFrame: LineVisibleRangesWithStyle[]): void { const epsilon = this._typicalHalfwidthCharacterWidth / 4; - let previousFrameTop: HorizontalRangeWithStyle = null; - let previousFrameBottom: HorizontalRangeWithStyle = null; + let previousFrameTop: HorizontalRangeWithStyle | null = null; + let previousFrameBottom: HorizontalRangeWithStyle | null = null; if (previousFrame && previousFrame.length > 0 && linesVisibleRanges.length > 0) { diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts index 67bc8a7d23c..71fedb09e9b 100644 --- a/src/vs/editor/browser/widget/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditorWidget.ts @@ -10,7 +10,6 @@ import * as dom from 'vs/base/browser/dom'; import { onUnexpectedError } from 'vs/base/common/errors'; import { Event, Emitter } from 'vs/base/common/event'; import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { TPromise } from 'vs/base/common/winjs.base'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; @@ -377,7 +376,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE return this.model; } - public setModel(model: ITextModel = null): void { + public setModel(model: ITextModel | null = null): void { if (this.model === model) { // Current model is the new model return; @@ -911,7 +910,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE const action = this.getAction(handlerId); if (action) { - TPromise.as(action.run()).then(null, onUnexpectedError); + Promise.resolve(action.run()).then(null, onUnexpectedError); return; } @@ -931,7 +930,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE if (command) { payload = payload || {}; payload.source = source; - TPromise.as(command.runEditorCommand(null, this, payload)).then(null, onUnexpectedError); + Promise.resolve(command.runEditorCommand(null, this, payload)).then(null, onUnexpectedError); return true; } @@ -1463,7 +1462,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE } private _detachModel(): ITextModel { - let removeDomNode: HTMLElement = null; + let removeDomNode: HTMLElement | null = null; if (this._view) { this._view.dispose(); diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index 86f20ba3d29..951c28430e8 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -847,8 +847,8 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE this._beginUpdateDecorationsTimeout = window.setTimeout(() => this._beginUpdateDecorations(), DiffEditorWidget.UPDATE_DIFF_DECORATIONS_DELAY); } - private _lastOriginalWarning: URI = null; - private _lastModifiedWarning: URI = null; + private _lastOriginalWarning: URI | null = null; + private _lastModifiedWarning: URI | null = null; private static _equals(a: URI, b: URI): boolean { if (!a && !b) { @@ -1334,7 +1334,7 @@ abstract class ViewZonesComputer { viewZoneLineNumber = originalEndEquivalentLineNumber; } - let marginDomNode: HTMLDivElement = null; + let marginDomNode: HTMLDivElement | null = null; if (lineChange && lineChange.modifiedStartLineNumber <= modifiedForeignVZ.current.afterLineNumber && modifiedForeignVZ.current.afterLineNumber <= lineChange.modifiedEndLineNumber) { marginDomNode = this._createOriginalMarginDomNodeForModifiedForeignViewZoneInAddedRegion(); } diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index f7d9fa0c404..bda346b4448 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -834,7 +834,7 @@ export function cursorStyleToString(cursorStyle: TextEditorCursorStyle): string } } -function _cursorStyleFromString(cursorStyle: string, defaultValue: TextEditorCursorStyle): TextEditorCursorStyle { +function _cursorStyleFromString(cursorStyle: string | undefined, defaultValue: TextEditorCursorStyle): TextEditorCursorStyle { if (typeof cursorStyle !== 'string') { return defaultValue; } @@ -930,7 +930,7 @@ export interface InternalEditorViewOptions { readonly rulers: number[]; readonly ariaLabel: string; readonly renderLineNumbers: RenderLineNumbersType; - readonly renderCustomLineNumbers: (lineNumber: number) => string; + readonly renderCustomLineNumbers: ((lineNumber: number) => string) | null; readonly selectOnLineNumbers: boolean; readonly glyphMargin: boolean; readonly revealHorizontalRightPadding: number; @@ -1597,7 +1597,7 @@ function _boolean(value: any, defaultValue: T): boolean | T { return Boolean(value); } -function _booleanMap(value: { [key: string]: boolean }, defaultValue: { [key: string]: boolean }): { [key: string]: boolean } { +function _booleanMap(value: { [key: string]: boolean } | undefined, defaultValue: { [key: string]: boolean }): { [key: string]: boolean } { if (!value) { return defaultValue; } @@ -1619,7 +1619,7 @@ function _string(value: any, defaultValue: string): string { return value; } -function _stringSet(value: T, defaultValue: T, allowedValues: T[]): T { +function _stringSet(value: T | undefined, defaultValue: T, allowedValues: T[]): T { if (typeof value !== 'string') { return defaultValue; } @@ -1652,7 +1652,7 @@ function _float(value: any, defaultValue: number): number { return r; } -function _wrappingIndentFromString(wrappingIndent: string, defaultValue: WrappingIndent): WrappingIndent { +function _wrappingIndentFromString(wrappingIndent: string | undefined, defaultValue: WrappingIndent): WrappingIndent { if (typeof wrappingIndent !== 'string') { return defaultValue; } @@ -1667,7 +1667,7 @@ function _wrappingIndentFromString(wrappingIndent: string, defaultValue: Wrappin } } -function _cursorBlinkingStyleFromString(cursorBlinkingStyle: string, defaultValue: TextEditorCursorBlinkingStyle): TextEditorCursorBlinkingStyle { +function _cursorBlinkingStyleFromString(cursorBlinkingStyle: string | undefined, defaultValue: TextEditorCursorBlinkingStyle): TextEditorCursorBlinkingStyle { if (typeof cursorBlinkingStyle !== 'string') { return defaultValue; } @@ -1687,7 +1687,7 @@ function _cursorBlinkingStyleFromString(cursorBlinkingStyle: string, defaultValu return TextEditorCursorBlinkingStyle.Blink; } -function _scrollbarVisibilityFromString(visibility: string, defaultValue: ScrollbarVisibility): ScrollbarVisibility { +function _scrollbarVisibilityFromString(visibility: string | undefined, defaultValue: ScrollbarVisibility): ScrollbarVisibility { if (typeof visibility !== 'string') { return defaultValue; } @@ -1726,7 +1726,7 @@ export class EditorOptionsValidator { const viewInfo = this._sanitizeViewInfo(opts, defaults.viewInfo); const contribInfo = this._sanitizeContribInfo(opts, defaults.contribInfo); - let configuredMulticursorModifier: 'altKey' | 'metaKey' | 'ctrlKey'; + let configuredMulticursorModifier: 'altKey' | 'metaKey' | 'ctrlKey' | undefined = undefined; if (typeof opts.multiCursorModifier === 'string') { if (opts.multiCursorModifier === 'ctrlCmd') { configuredMulticursorModifier = platform.isMacintosh ? 'metaKey' : 'ctrlKey'; @@ -1783,7 +1783,7 @@ export class EditorOptionsValidator { }; } - private static _sanitizeScrollbarOpts(opts: IEditorScrollbarOptions, defaults: InternalEditorScrollbarOptions, mouseWheelScrollSensitivity: number): InternalEditorScrollbarOptions { + private static _sanitizeScrollbarOpts(opts: IEditorScrollbarOptions | undefined, defaults: InternalEditorScrollbarOptions, mouseWheelScrollSensitivity: number): InternalEditorScrollbarOptions { if (typeof opts !== 'object') { return defaults; } @@ -1810,7 +1810,7 @@ export class EditorOptionsValidator { }; } - private static _sanitizeMinimapOpts(opts: IEditorMinimapOptions, defaults: InternalEditorMinimapOptions): InternalEditorMinimapOptions { + private static _sanitizeMinimapOpts(opts: IEditorMinimapOptions | undefined, defaults: InternalEditorMinimapOptions): InternalEditorMinimapOptions { if (typeof opts !== 'object') { return defaults; } @@ -1823,7 +1823,7 @@ export class EditorOptionsValidator { }; } - private static _santizeFindOpts(opts: IEditorFindOptions, defaults: InternalEditorFindOptions): InternalEditorFindOptions { + private static _santizeFindOpts(opts: IEditorFindOptions | undefined, defaults: InternalEditorFindOptions): InternalEditorFindOptions { if (typeof opts !== 'object') { return defaults; } @@ -1835,7 +1835,7 @@ export class EditorOptionsValidator { }; } - private static _sanitizeParameterHintOpts(opts: IEditorParameterHintOptions, defaults: InternalParameterHintOptions): InternalParameterHintOptions { + private static _sanitizeParameterHintOpts(opts: IEditorParameterHintOptions | undefined, defaults: InternalParameterHintOptions): InternalParameterHintOptions { if (typeof opts !== 'object') { return defaults; } @@ -1846,7 +1846,7 @@ export class EditorOptionsValidator { }; } - private static _santizeHoverOpts(_opts: boolean | IEditorHoverOptions, defaults: InternalEditorHoverOptions): InternalEditorHoverOptions { + private static _santizeHoverOpts(_opts: boolean | IEditorHoverOptions | undefined, defaults: InternalEditorHoverOptions): InternalEditorHoverOptions { let opts: IEditorHoverOptions; if (typeof _opts === 'boolean') { opts = { @@ -1875,7 +1875,7 @@ export class EditorOptionsValidator { }; } - private static _sanitizeTabCompletionOpts(opts: boolean | 'on' | 'off' | 'onlySnippets', defaults: 'on' | 'off' | 'onlySnippets'): 'on' | 'off' | 'onlySnippets' { + private static _sanitizeTabCompletionOpts(opts: boolean | 'on' | 'off' | 'onlySnippets' | undefined, defaults: 'on' | 'off' | 'onlySnippets'): 'on' | 'off' | 'onlySnippets' { if (opts === false) { return 'off'; } else if (opts === true) { @@ -1896,7 +1896,7 @@ export class EditorOptionsValidator { } let renderLineNumbers: RenderLineNumbersType = defaults.renderLineNumbers; - let renderCustomLineNumbers: (lineNumber: number) => string = defaults.renderCustomLineNumbers; + let renderCustomLineNumbers: ((lineNumber: number) => string) | null = defaults.renderCustomLineNumbers; if (typeof opts.lineNumbers !== 'undefined') { let lineNumbers = opts.lineNumbers; @@ -2198,7 +2198,7 @@ export class InternalEditorOptionsFactory { pixelRatio: env.pixelRatio }); - let bareWrappingInfo: { isWordWrapMinified: boolean; isViewportWrapping: boolean; wrappingColumn: number; } = null; + let bareWrappingInfo: { isWordWrapMinified: boolean; isViewportWrapping: boolean; wrappingColumn: number; } | null = null; { const wordWrap = opts.wordWrap; const wordWrapColumn = opts.wordWrapColumn; diff --git a/src/vs/editor/common/config/fontInfo.ts b/src/vs/editor/common/config/fontInfo.ts index b0b5b84369d..652ddb81350 100644 --- a/src/vs/editor/common/config/fontInfo.ts +++ b/src/vs/editor/common/config/fontInfo.ts @@ -23,10 +23,13 @@ const MAXIMUM_LINE_HEIGHT = 150; const MINIMUM_LETTER_SPACING = -5; const MAXIMUM_LETTER_SPACING = 20; -function safeParseFloat(n: number | string, defaultValue: number): number { +function safeParseFloat(n: number | string | undefined, defaultValue: number): number { if (typeof n === 'number') { return n; } + if (typeof n === 'undefined') { + return defaultValue; + } let r = parseFloat(n); if (isNaN(r)) { return defaultValue; @@ -34,10 +37,13 @@ function safeParseFloat(n: number | string, defaultValue: number): number { return r; } -function safeParseInt(n: number | string, defaultValue: number): number { +function safeParseInt(n: number | string | undefined, defaultValue: number): number { if (typeof n === 'number') { return Math.round(n); } + if (typeof n === 'undefined') { + return defaultValue; + } let r = parseInt(n); if (isNaN(r)) { return defaultValue; diff --git a/src/vs/editor/common/controller/cursor.ts b/src/vs/editor/common/controller/cursor.ts index 3aaa6ac8a87..629a737d5e2 100644 --- a/src/vs/editor/common/controller/cursor.ts +++ b/src/vs/editor/common/controller/cursor.ts @@ -11,7 +11,7 @@ import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { Selection, SelectionDirection, ISelection } from 'vs/editor/common/core/selection'; import * as editorCommon from 'vs/editor/common/editorCommon'; -import { CursorColumns, CursorConfiguration, EditOperationResult, CursorContext, CursorState, RevealTarget, IColumnSelectData, ICursors, EditOperationType } from 'vs/editor/common/controller/cursorCommon'; +import { CursorColumns, CursorConfiguration, EditOperationResult, CursorContext, CursorState, RevealTarget, IColumnSelectData, ICursors, EditOperationType, PartialCursorState } from 'vs/editor/common/controller/cursorCommon'; import { DeleteOperations } from 'vs/editor/common/controller/cursorDeleteOperations'; import { TypeOperations } from 'vs/editor/common/controller/cursorTypeOperations'; import { RawContentChangedType } from 'vs/editor/common/model/textModelEvents'; @@ -191,7 +191,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { return this._cursors.getAll(); } - public setStates(source: string, reason: CursorChangeReason, states: CursorState[]): void { + public setStates(source: string, reason: CursorChangeReason, states: PartialCursorState[]): void { if (states.length > Cursor.MAX_CURSOR_COUNT) { states = states.slice(0, Cursor.MAX_CURSOR_COUNT); this._onDidReachMaxCursorCount.fire(void 0); @@ -764,7 +764,7 @@ class CommandExecutor { let operations: IIdentifiedSingleEditOperation[] = []; let operationMinor = 0; - const addEditOperation = (selection: Range, text: string) => { + const addEditOperation = (selection: Range, text: string | null) => { if (selection.isEmpty() && text === '') { // This command wants to add a no-op => no thank you return; diff --git a/src/vs/editor/common/controller/cursorCollection.ts b/src/vs/editor/common/controller/cursorCollection.ts index e9a95685fa6..68b5ef1c279 100644 --- a/src/vs/editor/common/controller/cursorCollection.ts +++ b/src/vs/editor/common/controller/cursorCollection.ts @@ -6,7 +6,7 @@ import { OneCursor } from 'vs/editor/common/controller/oneCursor'; import { Selection, ISelection } from 'vs/editor/common/core/selection'; import { Position } from 'vs/editor/common/core/position'; -import { CursorState, CursorContext } from 'vs/editor/common/controller/cursorCommon'; +import { CursorState, CursorContext, PartialCursorState } from 'vs/editor/common/controller/cursorCommon'; export class CursorCollection { @@ -108,7 +108,7 @@ export class CursorCollection { return this.primaryCursor.asCursorState(); } - public setStates(states: CursorState[]): void { + public setStates(states: PartialCursorState[]): void { if (states === null) { return; } @@ -119,7 +119,7 @@ export class CursorCollection { /** * Creates or disposes secondary cursors as necessary to match the number of `secondarySelections`. */ - private _setSecondaryStates(secondaryStates: CursorState[]): void { + private _setSecondaryStates(secondaryStates: PartialCursorState[]): void { const secondaryCursorsLength = this.secondaryCursors.length; const secondaryStatesLength = secondaryStates.length; diff --git a/src/vs/editor/common/controller/cursorCommon.ts b/src/vs/editor/common/controller/cursorCommon.ts index 6761ce120b0..c324bf27a4f 100644 --- a/src/vs/editor/common/controller/cursorCommon.ts +++ b/src/vs/editor/common/controller/cursorCommon.ts @@ -51,7 +51,7 @@ export interface ICursors { getColumnSelectData(): IColumnSelectData; setColumnSelectData(columnSelectData: IColumnSelectData): void; - setStates(source: string, reason: CursorChangeReason, states: CursorState[]): void; + setStates(source: string, reason: CursorChangeReason, states: PartialCursorState[]): void; reveal(horizontal: boolean, target: RevealTarget, scrollType: ScrollType): void; revealRange(revealHorizontal: boolean, viewRange: Range, verticalType: VerticalRevealType, scrollType: ScrollType): void; @@ -93,7 +93,7 @@ export class CursorConfiguration { public readonly shouldAutoCloseBefore: { quote: (ch: string) => boolean, bracket: (ch: string) => boolean }; private readonly _languageIdentifier: LanguageIdentifier; - private _electricChars: { [key: string]: boolean; }; + private _electricChars: { [key: string]: boolean; } | null; public static shouldRecreate(e: IConfigurationChangedEvent): boolean { return ( @@ -179,7 +179,7 @@ export class CursorConfiguration { return TextModel.normalizeIndentation(str, this.tabSize, this.insertSpaces); } - private static _getElectricCharacters(languageIdentifier: LanguageIdentifier): string[] { + private static _getElectricCharacters(languageIdentifier: LanguageIdentifier): string[] | null { try { return LanguageConfigurationRegistry.getElectricCharacters(languageIdentifier.id); } catch (e) { @@ -188,7 +188,7 @@ export class CursorConfiguration { } } - private static _getAutoClosingPairs(languageIdentifier: LanguageIdentifier): IAutoClosingPair[] { + private static _getAutoClosingPairs(languageIdentifier: LanguageIdentifier): IAutoClosingPair[] | null { try { return LanguageConfigurationRegistry.getAutoClosingPairs(languageIdentifier.id); } catch (e) { @@ -220,7 +220,7 @@ export class CursorConfiguration { } } - private static _getSurroundingPairs(languageIdentifier: LanguageIdentifier): IAutoClosingPair[] { + private static _getSurroundingPairs(languageIdentifier: LanguageIdentifier): IAutoClosingPair[] | null { try { return LanguageConfigurationRegistry.getSurroundingPairs(languageIdentifier.id); } catch (e) { @@ -394,18 +394,40 @@ export class CursorContext { } } +export class PartialModelCursorState { + readonly modelState: SingleCursorState; + readonly viewState: null; + + constructor(modelState: SingleCursorState) { + this.modelState = modelState; + this.viewState = null; + } +} + +export class PartialViewCursorState { + readonly modelState: null; + readonly viewState: SingleCursorState; + + constructor(viewState: SingleCursorState) { + this.modelState = null; + this.viewState = viewState; + } +} + +export type PartialCursorState = CursorState | PartialModelCursorState | PartialViewCursorState; + export class CursorState { _cursorStateBrand: void; - public static fromModelState(modelState: SingleCursorState): CursorState { - return new CursorState(modelState, null); + public static fromModelState(modelState: SingleCursorState): PartialModelCursorState { + return new PartialModelCursorState(modelState); } - public static fromViewState(viewState: SingleCursorState): CursorState { - return new CursorState(null, viewState); + public static fromViewState(viewState: SingleCursorState): PartialViewCursorState { + return new PartialViewCursorState(viewState); } - public static fromModelSelection(modelSelection: ISelection): CursorState { + public static fromModelSelection(modelSelection: ISelection): PartialModelCursorState { const selectionStartLineNumber = modelSelection.selectionStartLineNumber; const selectionStartColumn = modelSelection.selectionStartColumn; const positionLineNumber = modelSelection.positionLineNumber; @@ -417,8 +439,8 @@ export class CursorState { return CursorState.fromModelState(modelState); } - public static fromModelSelections(modelSelections: ISelection[]): CursorState[] { - let states: CursorState[] = []; + public static fromModelSelections(modelSelections: ISelection[]): PartialModelCursorState[] { + let states: PartialModelCursorState[] = []; for (let i = 0, len = modelSelections.length; i < len; i++) { states[i] = this.fromModelSelection(modelSelections[i]); } diff --git a/src/vs/editor/common/controller/cursorMoveCommands.ts b/src/vs/editor/common/controller/cursorMoveCommands.ts index fac40969243..23c088e3193 100644 --- a/src/vs/editor/common/controller/cursorMoveCommands.ts +++ b/src/vs/editor/common/controller/cursorMoveCommands.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SingleCursorState, ICursorSimpleModel, CursorState, CursorContext } from 'vs/editor/common/controller/cursorCommon'; +import { SingleCursorState, ICursorSimpleModel, CursorState, CursorContext, PartialCursorState } from 'vs/editor/common/controller/cursorCommon'; import { Position, IPosition } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { MoveOperations } from 'vs/editor/common/controller/cursorMoveOperations'; @@ -13,8 +13,8 @@ import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands export class CursorMoveCommands { - public static addCursorDown(context: CursorContext, cursors: CursorState[], useLogicalLine: boolean): CursorState[] { - let result: CursorState[] = [], resultLen = 0; + public static addCursorDown(context: CursorContext, cursors: CursorState[], useLogicalLine: boolean): PartialCursorState[] { + let result: PartialCursorState[] = [], resultLen = 0; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; result[resultLen++] = new CursorState(cursor.modelState, cursor.viewState); @@ -27,8 +27,8 @@ export class CursorMoveCommands { return result; } - public static addCursorUp(context: CursorContext, cursors: CursorState[], useLogicalLine: boolean): CursorState[] { - let result: CursorState[] = [], resultLen = 0; + public static addCursorUp(context: CursorContext, cursors: CursorState[], useLogicalLine: boolean): PartialCursorState[] { + let result: PartialCursorState[] = [], resultLen = 0; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; result[resultLen++] = new CursorState(cursor.modelState, cursor.viewState); @@ -41,8 +41,8 @@ export class CursorMoveCommands { return result; } - public static moveToBeginningOfLine(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean): CursorState[] { - let result: CursorState[] = []; + public static moveToBeginningOfLine(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean): PartialCursorState[] { + let result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; result[i] = this._moveToLineStart(context, cursor, inSelectionMode); @@ -51,7 +51,7 @@ export class CursorMoveCommands { return result; } - private static _moveToLineStart(context: CursorContext, cursor: CursorState, inSelectionMode: boolean): CursorState { + private static _moveToLineStart(context: CursorContext, cursor: CursorState, inSelectionMode: boolean): PartialCursorState { const currentViewStateColumn = cursor.viewState.position.column; const currentModelStateColumn = cursor.modelState.position.column; const isFirstLineOfWrappedLine = currentViewStateColumn === currentModelStateColumn; @@ -67,20 +67,20 @@ export class CursorMoveCommands { } } - private static _moveToLineStartByView(context: CursorContext, cursor: CursorState, inSelectionMode: boolean): CursorState { + private static _moveToLineStartByView(context: CursorContext, cursor: CursorState, inSelectionMode: boolean): PartialCursorState { return CursorState.fromViewState( MoveOperations.moveToBeginningOfLine(context.config, context.viewModel, cursor.viewState, inSelectionMode) ); } - private static _moveToLineStartByModel(context: CursorContext, cursor: CursorState, inSelectionMode: boolean): CursorState { + private static _moveToLineStartByModel(context: CursorContext, cursor: CursorState, inSelectionMode: boolean): PartialCursorState { return CursorState.fromModelState( MoveOperations.moveToBeginningOfLine(context.config, context.model, cursor.modelState, inSelectionMode) ); } - public static moveToEndOfLine(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean): CursorState[] { - let result: CursorState[] = []; + public static moveToEndOfLine(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean): PartialCursorState[] { + let result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; result[i] = this._moveToLineEnd(context, cursor, inSelectionMode); @@ -89,7 +89,7 @@ export class CursorMoveCommands { return result; } - private static _moveToLineEnd(context: CursorContext, cursor: CursorState, inSelectionMode: boolean): CursorState { + private static _moveToLineEnd(context: CursorContext, cursor: CursorState, inSelectionMode: boolean): PartialCursorState { const viewStatePosition = cursor.viewState.position; const viewModelMaxColumn = context.viewModel.getLineMaxColumn(viewStatePosition.lineNumber); const isEndOfViewLine = viewStatePosition.column === viewModelMaxColumn; @@ -105,20 +105,20 @@ export class CursorMoveCommands { } } - private static _moveToLineEndByView(context: CursorContext, cursor: CursorState, inSelectionMode: boolean): CursorState { + private static _moveToLineEndByView(context: CursorContext, cursor: CursorState, inSelectionMode: boolean): PartialCursorState { return CursorState.fromViewState( MoveOperations.moveToEndOfLine(context.config, context.viewModel, cursor.viewState, inSelectionMode) ); } - private static _moveToLineEndByModel(context: CursorContext, cursor: CursorState, inSelectionMode: boolean): CursorState { + private static _moveToLineEndByModel(context: CursorContext, cursor: CursorState, inSelectionMode: boolean): PartialCursorState { return CursorState.fromModelState( MoveOperations.moveToEndOfLine(context.config, context.model, cursor.modelState, inSelectionMode) ); } - public static expandLineSelection(context: CursorContext, cursors: CursorState[]): CursorState[] { - let result: CursorState[] = []; + public static expandLineSelection(context: CursorContext, cursors: CursorState[]): PartialCursorState[] { + let result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; @@ -143,8 +143,8 @@ export class CursorMoveCommands { return result; } - public static moveToBeginningOfBuffer(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean): CursorState[] { - let result: CursorState[] = []; + public static moveToBeginningOfBuffer(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean): PartialCursorState[] { + let result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; result[i] = CursorState.fromModelState(MoveOperations.moveToBeginningOfBuffer(context.config, context.model, cursor.modelState, inSelectionMode)); @@ -152,8 +152,8 @@ export class CursorMoveCommands { return result; } - public static moveToEndOfBuffer(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean): CursorState[] { - let result: CursorState[] = []; + public static moveToEndOfBuffer(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean): PartialCursorState[] { + let result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; result[i] = CursorState.fromModelState(MoveOperations.moveToEndOfBuffer(context.config, context.model, cursor.modelState, inSelectionMode)); @@ -161,7 +161,7 @@ export class CursorMoveCommands { return result; } - public static selectAll(context: CursorContext, cursor: CursorState): CursorState { + public static selectAll(context: CursorContext, cursor: CursorState): PartialCursorState { const lineCount = context.model.getLineCount(); const maxColumn = context.model.getLineMaxColumn(lineCount); @@ -171,7 +171,7 @@ export class CursorMoveCommands { )); } - public static line(context: CursorContext, cursor: CursorState, inSelectionMode: boolean, _position: IPosition, _viewPosition: IPosition): CursorState { + public static line(context: CursorContext, cursor: CursorState, inSelectionMode: boolean, _position: IPosition, _viewPosition: IPosition): PartialCursorState { const position = context.model.validatePosition(_position); const viewPosition = ( _viewPosition @@ -230,12 +230,12 @@ export class CursorMoveCommands { } } - public static word(context: CursorContext, cursor: CursorState, inSelectionMode: boolean, _position: IPosition): CursorState { + public static word(context: CursorContext, cursor: CursorState, inSelectionMode: boolean, _position: IPosition): PartialCursorState { const position = context.model.validatePosition(_position); return CursorState.fromModelState(WordOperations.word(context.config, context.model, cursor.modelState, inSelectionMode, position)); } - public static cancelSelection(context: CursorContext, cursor: CursorState): CursorState { + public static cancelSelection(context: CursorContext, cursor: CursorState): PartialCursorState { if (!cursor.modelState.hasSelection()) { return new CursorState(cursor.modelState, cursor.viewState); } @@ -249,7 +249,7 @@ export class CursorMoveCommands { )); } - public static moveTo(context: CursorContext, cursor: CursorState, inSelectionMode: boolean, _position: IPosition, _viewPosition: IPosition): CursorState { + public static moveTo(context: CursorContext, cursor: CursorState, inSelectionMode: boolean, _position: IPosition, _viewPosition: IPosition): PartialCursorState { const position = context.model.validatePosition(_position); const viewPosition = ( _viewPosition @@ -259,7 +259,7 @@ export class CursorMoveCommands { return CursorState.fromViewState(cursor.viewState.move(inSelectionMode, viewPosition.lineNumber, viewPosition.column, 0)); } - public static move(context: CursorContext, cursors: CursorState[], args: CursorMove.ParsedArguments): CursorState[] { + public static move(context: CursorContext, cursors: CursorState[], args: CursorMove.ParsedArguments): PartialCursorState[] { const inSelectionMode = args.select; const value = args.value; @@ -347,7 +347,7 @@ export class CursorMoveCommands { case CursorMove.Direction.ViewPortIfOutside: { // Move to a position inside the viewport const visibleViewRange = context.getCompletelyVisibleViewRange(); - let result: CursorState[] = []; + let result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; result[i] = this.findPositionInViewportIfOutside(context, cursor, visibleViewRange, inSelectionMode); @@ -360,7 +360,7 @@ export class CursorMoveCommands { } - public static findPositionInViewportIfOutside(context: CursorContext, cursor: CursorState, visibleViewRange: Range, inSelectionMode: boolean): CursorState { + public static findPositionInViewportIfOutside(context: CursorContext, cursor: CursorState, visibleViewRange: Range, inSelectionMode: boolean): PartialCursorState { let viewLineNumber = cursor.viewState.position.lineNumber; if (visibleViewRange.startLineNumber <= viewLineNumber && viewLineNumber <= visibleViewRange.endLineNumber - 1) { @@ -405,8 +405,8 @@ export class CursorMoveCommands { return Math.max(startLineNumber, range.endLineNumber - count + 1); } - private static _moveLeft(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean, noOfColumns: number): CursorState[] { - let result: CursorState[] = []; + private static _moveLeft(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean, noOfColumns: number): PartialCursorState[] { + let result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; @@ -426,8 +426,8 @@ export class CursorMoveCommands { return result; } - private static _moveHalfLineLeft(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean): CursorState[] { - let result: CursorState[] = []; + private static _moveHalfLineLeft(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean): PartialCursorState[] { + let result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; const viewLineNumber = cursor.viewState.position.lineNumber; @@ -437,8 +437,8 @@ export class CursorMoveCommands { return result; } - private static _moveRight(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean, noOfColumns: number): CursorState[] { - let result: CursorState[] = []; + private static _moveRight(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean, noOfColumns: number): PartialCursorState[] { + let result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; let newViewState = MoveOperations.moveRight(context.config, context.viewModel, cursor.viewState, inSelectionMode, noOfColumns); @@ -457,8 +457,8 @@ export class CursorMoveCommands { return result; } - private static _moveHalfLineRight(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean): CursorState[] { - let result: CursorState[] = []; + private static _moveHalfLineRight(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean): PartialCursorState[] { + let result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; const viewLineNumber = cursor.viewState.position.lineNumber; @@ -468,8 +468,8 @@ export class CursorMoveCommands { return result; } - private static _moveDownByViewLines(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean, linesCount: number): CursorState[] { - let result: CursorState[] = []; + private static _moveDownByViewLines(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean, linesCount: number): PartialCursorState[] { + let result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; result[i] = CursorState.fromViewState(MoveOperations.moveDown(context.config, context.viewModel, cursor.viewState, inSelectionMode, linesCount)); @@ -477,8 +477,8 @@ export class CursorMoveCommands { return result; } - private static _moveDownByModelLines(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean, linesCount: number): CursorState[] { - let result: CursorState[] = []; + private static _moveDownByModelLines(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean, linesCount: number): PartialCursorState[] { + let result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; result[i] = CursorState.fromModelState(MoveOperations.moveDown(context.config, context.model, cursor.modelState, inSelectionMode, linesCount)); @@ -486,8 +486,8 @@ export class CursorMoveCommands { return result; } - private static _moveUpByViewLines(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean, linesCount: number): CursorState[] { - let result: CursorState[] = []; + private static _moveUpByViewLines(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean, linesCount: number): PartialCursorState[] { + let result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; result[i] = CursorState.fromViewState(MoveOperations.moveUp(context.config, context.viewModel, cursor.viewState, inSelectionMode, linesCount)); @@ -495,8 +495,8 @@ export class CursorMoveCommands { return result; } - private static _moveUpByModelLines(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean, linesCount: number): CursorState[] { - let result: CursorState[] = []; + private static _moveUpByModelLines(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean, linesCount: number): PartialCursorState[] { + let result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; result[i] = CursorState.fromModelState(MoveOperations.moveUp(context.config, context.model, cursor.modelState, inSelectionMode, linesCount)); @@ -504,16 +504,16 @@ export class CursorMoveCommands { return result; } - private static _moveToViewPosition(context: CursorContext, cursor: CursorState, inSelectionMode: boolean, toViewLineNumber: number, toViewColumn: number): CursorState { + private static _moveToViewPosition(context: CursorContext, cursor: CursorState, inSelectionMode: boolean, toViewLineNumber: number, toViewColumn: number): PartialCursorState { return CursorState.fromViewState(cursor.viewState.move(inSelectionMode, toViewLineNumber, toViewColumn, 0)); } - private static _moveToModelPosition(context: CursorContext, cursor: CursorState, inSelectionMode: boolean, toModelLineNumber: number, toModelColumn: number): CursorState { + private static _moveToModelPosition(context: CursorContext, cursor: CursorState, inSelectionMode: boolean, toModelLineNumber: number, toModelColumn: number): PartialCursorState { return CursorState.fromModelState(cursor.modelState.move(inSelectionMode, toModelLineNumber, toModelColumn, 0)); } - private static _moveToViewMinColumn(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean): CursorState[] { - let result: CursorState[] = []; + private static _moveToViewMinColumn(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean): PartialCursorState[] { + let result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; const viewLineNumber = cursor.viewState.position.lineNumber; @@ -523,8 +523,8 @@ export class CursorMoveCommands { return result; } - private static _moveToViewFirstNonWhitespaceColumn(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean): CursorState[] { - let result: CursorState[] = []; + private static _moveToViewFirstNonWhitespaceColumn(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean): PartialCursorState[] { + let result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; const viewLineNumber = cursor.viewState.position.lineNumber; @@ -534,8 +534,8 @@ export class CursorMoveCommands { return result; } - private static _moveToViewCenterColumn(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean): CursorState[] { - let result: CursorState[] = []; + private static _moveToViewCenterColumn(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean): PartialCursorState[] { + let result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; const viewLineNumber = cursor.viewState.position.lineNumber; @@ -545,8 +545,8 @@ export class CursorMoveCommands { return result; } - private static _moveToViewMaxColumn(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean): CursorState[] { - let result: CursorState[] = []; + private static _moveToViewMaxColumn(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean): PartialCursorState[] { + let result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; const viewLineNumber = cursor.viewState.position.lineNumber; @@ -556,8 +556,8 @@ export class CursorMoveCommands { return result; } - private static _moveToViewLastNonWhitespaceColumn(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean): CursorState[] { - let result: CursorState[] = []; + private static _moveToViewLastNonWhitespaceColumn(context: CursorContext, cursors: CursorState[], inSelectionMode: boolean): PartialCursorState[] { + let result: PartialCursorState[] = []; for (let i = 0, len = cursors.length; i < len; i++) { const cursor = cursors[i]; const viewLineNumber = cursor.viewState.position.lineNumber; diff --git a/src/vs/editor/common/controller/cursorWordOperations.ts b/src/vs/editor/common/controller/cursorWordOperations.ts index c6969fd6937..ccda783109d 100644 --- a/src/vs/editor/common/controller/cursorWordOperations.ts +++ b/src/vs/editor/common/controller/cursorWordOperations.ts @@ -49,12 +49,12 @@ export class WordOperations { return { start: start, end: end, wordType: wordType, nextCharClass: nextCharClass }; } - private static _findPreviousWordOnLine(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, position: Position): IFindWordResult { + private static _findPreviousWordOnLine(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, position: Position): IFindWordResult | null { let lineContent = model.getLineContent(position.lineNumber); return this._doFindPreviousWordOnLine(lineContent, wordSeparators, position); } - private static _doFindPreviousWordOnLine(lineContent: string, wordSeparators: WordCharacterClassifier, position: Position): IFindWordResult { + private static _doFindPreviousWordOnLine(lineContent: string, wordSeparators: WordCharacterClassifier, position: Position): IFindWordResult | null { let wordType = WordType.None; for (let chIndex = position.column - 2; chIndex >= 0; chIndex--) { let chCode = lineContent.charCodeAt(chIndex); @@ -103,12 +103,12 @@ export class WordOperations { return len; } - private static _findNextWordOnLine(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, position: Position): IFindWordResult { + private static _findNextWordOnLine(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, position: Position): IFindWordResult | null { let lineContent = model.getLineContent(position.lineNumber); return this._doFindNextWordOnLine(lineContent, wordSeparators, position); } - private static _doFindNextWordOnLine(lineContent: string, wordSeparators: WordCharacterClassifier, position: Position): IFindWordResult { + private static _doFindNextWordOnLine(lineContent: string, wordSeparators: WordCharacterClassifier, position: Position): IFindWordResult | null { let wordType = WordType.None; let len = lineContent.length; @@ -324,7 +324,7 @@ export class WordOperations { return new Position(lineNumber, maxColumn); } - protected static _deleteWordLeftWhitespace(model: ICursorSimpleModel, position: Position): Range { + protected static _deleteWordLeftWhitespace(model: ICursorSimpleModel, position: Position): Range | null { const lineContent = model.getLineContent(position.lineNumber); const startIndex = position.column - 2; const lastNonWhitespace = strings.lastNonWhitespaceIndex(lineContent, startIndex); @@ -334,7 +334,7 @@ export class WordOperations { return null; } - public static deleteWordLeft(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, selection: Selection, whitespaceHeuristics: boolean, wordNavigationType: WordNavigationType): Range { + public static deleteWordLeft(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, selection: Selection, whitespaceHeuristics: boolean, wordNavigationType: WordNavigationType): Range | null { if (!selection.isEmpty()) { return selection; } @@ -409,7 +409,7 @@ export class WordOperations { return len; } - protected static _deleteWordRightWhitespace(model: ICursorSimpleModel, position: Position): Range { + protected static _deleteWordRightWhitespace(model: ICursorSimpleModel, position: Position): Range | null { const lineContent = model.getLineContent(position.lineNumber); const startIndex = position.column - 1; const firstNonWhitespace = this._findFirstNonWhitespaceChar(lineContent, startIndex); @@ -420,7 +420,7 @@ export class WordOperations { return null; } - public static deleteWordRight(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, selection: Selection, whitespaceHeuristics: boolean, wordNavigationType: WordNavigationType): Range { + public static deleteWordRight(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, selection: Selection, whitespaceHeuristics: boolean, wordNavigationType: WordNavigationType): Range | null { if (!selection.isEmpty()) { return selection; } @@ -503,16 +503,15 @@ export class WordOperations { if (!inSelectionMode) { // Entering word selection for the first time - const isTouchingPrevWord = (prevWord && prevWord.wordType === WordType.Regular && prevWord.start <= position.column - 1 && position.column - 1 <= prevWord.end); - const isTouchingNextWord = (nextWord && nextWord.wordType === WordType.Regular && nextWord.start <= position.column - 1 && position.column - 1 <= nextWord.end); - let startColumn: number; let endColumn: number; - if (isTouchingPrevWord) { + if (prevWord && prevWord.wordType === WordType.Regular && prevWord.start <= position.column - 1 && position.column - 1 <= prevWord.end) { + // isTouchingPrevWord startColumn = prevWord.start + 1; endColumn = prevWord.end + 1; - } else if (isTouchingNextWord) { + } else if (nextWord && nextWord.wordType === WordType.Regular && nextWord.start <= position.column - 1 && position.column - 1 <= nextWord.end) { + // isTouchingNextWord startColumn = nextWord.start + 1; endColumn = nextWord.end + 1; } else { @@ -534,16 +533,15 @@ export class WordOperations { ); } - const isInsidePrevWord = (prevWord && prevWord.wordType === WordType.Regular && prevWord.start < position.column - 1 && position.column - 1 < prevWord.end); - const isInsideNextWord = (nextWord && nextWord.wordType === WordType.Regular && nextWord.start < position.column - 1 && position.column - 1 < nextWord.end); - let startColumn: number; let endColumn: number; - if (isInsidePrevWord) { + if (prevWord && prevWord.wordType === WordType.Regular && prevWord.start < position.column - 1 && position.column - 1 < prevWord.end) { + // isInsidePrevWord startColumn = prevWord.start + 1; endColumn = prevWord.end + 1; - } else if (isInsideNextWord) { + } else if (nextWord && nextWord.wordType === WordType.Regular && nextWord.start < position.column - 1 && position.column - 1 < nextWord.end) { + // isInsideNextWord startColumn = nextWord.start + 1; endColumn = nextWord.end + 1; } else { @@ -575,42 +573,46 @@ export class WordOperations { export class WordPartOperations extends WordOperations { public static deleteWordPartLeft(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, selection: Selection, whitespaceHeuristics: boolean): Range { - const candidates = [ + const candidates = enforceDefined([ WordOperations.deleteWordLeft(wordSeparators, model, selection, whitespaceHeuristics, WordNavigationType.WordStart), WordOperations.deleteWordLeft(wordSeparators, model, selection, whitespaceHeuristics, WordNavigationType.WordEnd), WordOperations._deleteWordPartLeft(model, selection) - ]; + ]); candidates.sort(Range.compareRangesUsingEnds); return candidates[2]; } public static deleteWordPartRight(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, selection: Selection, whitespaceHeuristics: boolean): Range { - const candidates = [ + const candidates = enforceDefined([ WordOperations.deleteWordRight(wordSeparators, model, selection, whitespaceHeuristics, WordNavigationType.WordStart), WordOperations.deleteWordRight(wordSeparators, model, selection, whitespaceHeuristics, WordNavigationType.WordEnd), WordOperations._deleteWordPartRight(model, selection) - ]; + ]); candidates.sort(Range.compareRangesUsingStarts); return candidates[0]; } public static moveWordPartLeft(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, position: Position): Position { - const candidates = [ + const candidates = enforceDefined([ WordOperations.moveWordLeft(wordSeparators, model, position, WordNavigationType.WordStart), WordOperations.moveWordLeft(wordSeparators, model, position, WordNavigationType.WordEnd), WordOperations._moveWordPartLeft(model, position) - ]; + ]); candidates.sort(Position.compare); return candidates[2]; } public static moveWordPartRight(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, position: Position): Position { - const candidates = [ + const candidates = enforceDefined([ WordOperations.moveWordRight(wordSeparators, model, position, WordNavigationType.WordStart), WordOperations.moveWordRight(wordSeparators, model, position, WordNavigationType.WordEnd), WordOperations._moveWordPartRight(model, position) - ]; + ]); candidates.sort(Position.compare); return candidates[0]; } } + +function enforceDefined(arr: (T | undefined | null)[]): T[] { + return arr.filter(el => Boolean(el)); +} \ No newline at end of file diff --git a/src/vs/editor/common/controller/oneCursor.ts b/src/vs/editor/common/controller/oneCursor.ts index bd5a79933d7..0a75e44cd4a 100644 --- a/src/vs/editor/common/controller/oneCursor.ts +++ b/src/vs/editor/common/controller/oneCursor.ts @@ -14,13 +14,10 @@ export class OneCursor { public modelState: SingleCursorState; public viewState: SingleCursorState; - private _selTrackedRange: string; + private _selTrackedRange: string | null; private _trackSelection: boolean; constructor(context: CursorContext) { - this.modelState = null; - this.viewState = null; - this._selTrackedRange = null; this._trackSelection = true; @@ -62,7 +59,7 @@ export class OneCursor { } public readSelectionFromMarkers(context: CursorContext): Selection { - const range = context.model._getTrackedRange(this._selTrackedRange); + const range = context.model._getTrackedRange(this._selTrackedRange!)!; if (this.modelState.selection.getDirection() === SelectionDirection.LTR) { return new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn); } diff --git a/src/vs/editor/common/core/range.ts b/src/vs/editor/common/core/range.ts index ba250db1856..864cc041bca 100644 --- a/src/vs/editor/common/core/range.ts +++ b/src/vs/editor/common/core/range.ts @@ -172,14 +172,14 @@ export class Range { /** * A intersection of the two ranges. */ - public intersectRanges(range: IRange): Range { + public intersectRanges(range: IRange): Range | null { return Range.intersectRanges(this, range); } /** * A intersection of the two ranges. */ - public static intersectRanges(a: IRange, b: IRange): Range { + public static intersectRanges(a: IRange, b: IRange): Range | null { let resultStartLineNumber = a.startLineNumber; let resultStartColumn = a.startColumn; let resultEndLineNumber = a.endLineNumber; @@ -223,7 +223,7 @@ export class Range { /** * Test if range `a` equals `b`. */ - public static equalsRange(a: IRange, b: IRange): boolean { + public static equalsRange(a: IRange | null, b: IRange | null): boolean { return ( !!a && !!b && @@ -292,7 +292,9 @@ export class Range { /** * Create a `Range` from an `IRange`. */ - public static lift(range: IRange): Range { + public static lift(range: undefined | null): null; + public static lift(range: IRange): Range; + public static lift(range: IRange | undefined | null): Range | null { if (!range) { return null; } diff --git a/src/vs/editor/common/core/rgba.ts b/src/vs/editor/common/core/rgba.ts index 07c5edcb3bd..0ce94359f31 100644 --- a/src/vs/editor/common/core/rgba.ts +++ b/src/vs/editor/common/core/rgba.ts @@ -10,6 +10,8 @@ export class RGBA8 { _rgba8Brand: void; + static Empty = new RGBA8(0, 0, 0, 0); + /** * Red: integer in [0-255] */ diff --git a/src/vs/editor/common/core/stringBuilder.ts b/src/vs/editor/common/core/stringBuilder.ts index 3f2eae63fbb..36cbe87f54e 100644 --- a/src/vs/editor/common/core/stringBuilder.ts +++ b/src/vs/editor/common/core/stringBuilder.ts @@ -32,7 +32,7 @@ class StringBuilder implements IStringBuilder { private readonly _capacity: number; private readonly _buffer: Uint16Array; - private _completedStrings: string[]; + private _completedStrings: string[] | null; private _bufferLength: number; constructor(capacity: number) { @@ -104,7 +104,7 @@ class StringBuilder implements IStringBuilder { // This string does not fit in the remaining buffer space this._flushBuffer(); - this._completedStrings[this._completedStrings.length] = str; + this._completedStrings![this._completedStrings!.length] = str; return; } diff --git a/src/vs/editor/common/diff/diffComputer.ts b/src/vs/editor/common/diff/diffComputer.ts index 0ad0f1dfd75..be2d727328a 100644 --- a/src/vs/editor/common/diff/diffComputer.ts +++ b/src/vs/editor/common/diff/diffComputer.ts @@ -238,14 +238,14 @@ class LineChange implements ILineChange { public originalEndLineNumber: number; public modifiedStartLineNumber: number; public modifiedEndLineNumber: number; - public charChanges: CharChange[]; + public charChanges: CharChange[] | undefined; constructor( originalStartLineNumber: number, originalEndLineNumber: number, modifiedStartLineNumber: number, modifiedEndLineNumber: number, - charChanges: CharChange[] + charChanges: CharChange[] | undefined ) { this.originalStartLineNumber = originalStartLineNumber; this.originalEndLineNumber = originalEndLineNumber; @@ -259,7 +259,7 @@ class LineChange implements ILineChange { let originalEndLineNumber: number; let modifiedStartLineNumber: number; let modifiedEndLineNumber: number; - let charChanges: CharChange[]; + let charChanges: CharChange[] | undefined = undefined; if (diffChange.originalLength === 0) { originalStartLineNumber = originalLineSequence.getStartLineNumber(diffChange.originalStart) - 1; @@ -477,7 +477,7 @@ export class DiffComputer { return; } - let charChanges: CharChange[]; + let charChanges: CharChange[] | undefined = undefined; if (this.shouldComputeCharChanges) { charChanges = [new CharChange( originalLineNumber, originalStartColumn, originalLineNumber, originalEndColumn, @@ -512,7 +512,7 @@ export class DiffComputer { prevChange.originalEndLineNumber = originalLineNumber; prevChange.modifiedEndLineNumber = modifiedLineNumber; if (this.shouldComputeCharChanges) { - prevChange.charChanges.push(new CharChange( + prevChange.charChanges!.push(new CharChange( originalLineNumber, originalStartColumn, originalLineNumber, originalEndColumn, modifiedLineNumber, modifiedStartColumn, modifiedLineNumber, modifiedEndColumn )); diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index 78829d1fe2b..8beff0159df 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -22,7 +22,7 @@ export interface IEditOperationBuilder { * @param range The range to replace (delete). May be empty to represent a simple insert. * @param text The text to replace with. May be null to represent a simple delete. */ - addEditOperation(range: Range, text: string): void; + addEditOperation(range: Range, text: string | null): void; /** * Add a new edit operation (a replace operation). @@ -142,7 +142,7 @@ export interface ICharChange extends IChange { * A line change */ export interface ILineChange extends IChange { - readonly charChanges: ICharChange[]; + readonly charChanges: ICharChange[] | undefined; } /** diff --git a/src/vs/editor/common/editorContextKeys.ts b/src/vs/editor/common/editorContextKeys.ts index 3b642840f75..a4f010814de 100644 --- a/src/vs/editor/common/editorContextKeys.ts +++ b/src/vs/editor/common/editorContextKeys.ts @@ -28,24 +28,24 @@ export namespace EditorContextKeys { export const hasSingleSelection: ContextKeyExpr = hasMultipleSelections.toNegated(); export const tabMovesFocus = new RawContextKey('editorTabMovesFocus', false); export const tabDoesNotMoveFocus: ContextKeyExpr = tabMovesFocus.toNegated(); - export const isInEmbeddedEditor = new RawContextKey('isInEmbeddedEditor', undefined); + export const isInEmbeddedEditor = new RawContextKey('isInEmbeddedEditor', false); export const canUndo = new RawContextKey('canUndo', false); export const canRedo = new RawContextKey('canRedo', false); // -- mode context keys - export const languageId = new RawContextKey('editorLangId', undefined); - export const hasCompletionItemProvider = new RawContextKey('editorHasCompletionItemProvider', undefined); - export const hasCodeActionsProvider = new RawContextKey('editorHasCodeActionsProvider', undefined); - export const hasCodeLensProvider = new RawContextKey('editorHasCodeLensProvider', undefined); - export const hasDefinitionProvider = new RawContextKey('editorHasDefinitionProvider', undefined); - export const hasImplementationProvider = new RawContextKey('editorHasImplementationProvider', undefined); - export const hasTypeDefinitionProvider = new RawContextKey('editorHasTypeDefinitionProvider', undefined); - export const hasHoverProvider = new RawContextKey('editorHasHoverProvider', undefined); - export const hasDocumentHighlightProvider = new RawContextKey('editorHasDocumentHighlightProvider', undefined); - export const hasDocumentSymbolProvider = new RawContextKey('editorHasDocumentSymbolProvider', undefined); - export const hasReferenceProvider = new RawContextKey('editorHasReferenceProvider', undefined); - export const hasRenameProvider = new RawContextKey('editorHasRenameProvider', undefined); - export const hasDocumentFormattingProvider = new RawContextKey('editorHasDocumentFormattingProvider', undefined); - export const hasDocumentSelectionFormattingProvider = new RawContextKey('editorHasDocumentSelectionFormattingProvider', undefined); - export const hasSignatureHelpProvider = new RawContextKey('editorHasSignatureHelpProvider', undefined); + export const languageId = new RawContextKey('editorLangId', ''); + export const hasCompletionItemProvider = new RawContextKey('editorHasCompletionItemProvider', false); + export const hasCodeActionsProvider = new RawContextKey('editorHasCodeActionsProvider', false); + export const hasCodeLensProvider = new RawContextKey('editorHasCodeLensProvider', false); + export const hasDefinitionProvider = new RawContextKey('editorHasDefinitionProvider', false); + export const hasImplementationProvider = new RawContextKey('editorHasImplementationProvider', false); + export const hasTypeDefinitionProvider = new RawContextKey('editorHasTypeDefinitionProvider', false); + export const hasHoverProvider = new RawContextKey('editorHasHoverProvider', false); + export const hasDocumentHighlightProvider = new RawContextKey('editorHasDocumentHighlightProvider', false); + export const hasDocumentSymbolProvider = new RawContextKey('editorHasDocumentSymbolProvider', false); + export const hasReferenceProvider = new RawContextKey('editorHasReferenceProvider', false); + export const hasRenameProvider = new RawContextKey('editorHasRenameProvider', false); + export const hasDocumentFormattingProvider = new RawContextKey('editorHasDocumentFormattingProvider', false); + export const hasDocumentSelectionFormattingProvider = new RawContextKey('editorHasDocumentSelectionFormattingProvider', false); + export const hasSignatureHelpProvider = new RawContextKey('editorHasSignatureHelpProvider', false); } diff --git a/src/vs/editor/common/model.ts b/src/vs/editor/common/model.ts index 382372cb583..f38ef53e4cb 100644 --- a/src/vs/editor/common/model.ts +++ b/src/vs/editor/common/model.ts @@ -58,15 +58,15 @@ export interface IModelDecorationOptions { /** * CSS class name describing the decoration. */ - className?: string; + className?: string | null; /** * Message to be rendered when hovering over the glyph margin decoration. */ - glyphMarginHoverMessage?: IMarkdownString | IMarkdownString[]; + glyphMarginHoverMessage?: IMarkdownString | IMarkdownString[] | null; /** * Array of MarkdownString to render as the decoration message. */ - hoverMessage?: IMarkdownString | IMarkdownString[]; + hoverMessage?: IMarkdownString | IMarkdownString[] | null; /** * Should the decoration expand to encompass a whole line. */ @@ -89,25 +89,25 @@ export interface IModelDecorationOptions { /** * If set, render this decoration in the overview ruler. */ - overviewRuler?: IModelDecorationOverviewRulerOptions; + overviewRuler?: IModelDecorationOverviewRulerOptions | null; /** * If set, the decoration will be rendered in the glyph margin with this CSS class name. */ - glyphMarginClassName?: string; + glyphMarginClassName?: string | null; /** * If set, the decoration will be rendered in the lines decorations with this CSS class name. */ - linesDecorationsClassName?: string; + linesDecorationsClassName?: string | null; /** * If set, the decoration will be rendered in the margin (covering its full width) with this CSS class name. */ - marginClassName?: string; + marginClassName?: string | null; /** * If set, the decoration will be rendered inline with the text with this CSS class name. * Please use this only for CSS rules that must impact the text. For example, use `className` * to have a background color decoration. */ - inlineClassName?: string; + inlineClassName?: string | null; /** * If there is an `inlineClassName` which affects letter spacing. */ @@ -115,11 +115,11 @@ export interface IModelDecorationOptions { /** * If set, the decoration will be rendered before the text with this CSS class name. */ - beforeContentClassName?: string; + beforeContentClassName?: string | null; /** * If set, the decoration will be rendered after the text with this CSS class name. */ - afterContentClassName?: string; + afterContentClassName?: string | null; } /** @@ -305,7 +305,7 @@ export interface IIdentifiedSingleEditOperation { * An identifier associated with this single edit operation. * @internal */ - identifier?: ISingleEditOperationIdentifier; + identifier?: ISingleEditOperationIdentifier | null; /** * The range to replace. This can be empty to emulate a simple insert. */ @@ -313,7 +313,7 @@ export interface IIdentifiedSingleEditOperation { /** * The text to replace with. This can be null to emulate a simple delete. */ - text: string; + text: string | null; /** * This indicates that this operation has "insert" semantics. * i.e. forceMoveMarkers = true => if `range` is collapsed, all markers at the position will be moved. @@ -412,12 +412,12 @@ export class FindMatch { _findMatchBrand: void; public readonly range: Range; - public readonly matches: string[]; + public readonly matches: string[] | null; /** * @internal */ - constructor(range: Range, matches: string[]) { + constructor(range: Range, matches: string[] | null) { this.range = range; this.matches = matches; } @@ -719,7 +719,7 @@ export interface ITextModel { * @param captureMatches The result will contain the captured groups. * @return The range where the next match is. It is null if no next match has been found. */ - findNextMatch(searchString: string, searchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string | null, captureMatches: boolean): FindMatch; + findNextMatch(searchString: string, searchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string | null, captureMatches: boolean): FindMatch | null; /** * Search the model for the previous match. Loops to the end of the model if needed. * @param searchString The string used to search. If it is a regular expression, set `isRegex` to true. @@ -730,7 +730,7 @@ export interface ITextModel { * @param captureMatches The result will contain the captured groups. * @return The range where the previous match is. It is null if no previous match has been found. */ - findPreviousMatch(searchString: string, searchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string | null, captureMatches: boolean): FindMatch; + findPreviousMatch(searchString: string, searchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string | null, captureMatches: boolean): FindMatch | null; /** * Force tokenization information for `lineNumber` to be accurate. @@ -788,7 +788,7 @@ export interface ITextModel { * @param position The position to look for a word. * @return The word under or besides `position`. Might be null. */ - getWordAtPosition(position: IPosition): IWordAtPosition; + getWordAtPosition(position: IPosition): IWordAtPosition | null; /** * Get the word under or besides `position` trimmed to `position`.column @@ -804,7 +804,7 @@ export interface ITextModel { * @return The range of the matching bracket, or null if the bracket match was not found. * @internal */ - findMatchingBracketUp(bracket: string, position: IPosition): Range; + findMatchingBracketUp(bracket: string, position: IPosition): Range | null; /** * Find the first bracket in the model before `position`. @@ -812,7 +812,7 @@ export interface ITextModel { * @return The info for the first bracket before `position`, or null if there are no more brackets before `positions`. * @internal */ - findPrevBracket(position: IPosition): IFoundBracket; + findPrevBracket(position: IPosition): IFoundBracket | null; /** * Find the first bracket in the model after `position`. @@ -820,7 +820,7 @@ export interface ITextModel { * @return The info for the first bracket after `position`, or null if there are no more brackets after `positions`. * @internal */ - findNextBracket(position: IPosition): IFoundBracket; + findNextBracket(position: IPosition): IFoundBracket | null; /** * Given a `position`, if the position is on top or near a bracket, @@ -828,7 +828,7 @@ export interface ITextModel { * @param position The position at which to look for a bracket. * @internal */ - matchBracket(position: IPosition): [Range, Range]; + matchBracket(position: IPosition): [Range, Range] | null; /** * @internal @@ -848,7 +848,7 @@ export interface ITextModel { * @param ownerId Identifies the editor id in which these decorations should appear. If no `ownerId` is provided, the decorations will appear in all editors that attach this model. * @internal */ - changeDecorations(callback: (changeAccessor: IModelDecorationsChangeAccessor) => T, ownerId?: number): T; + changeDecorations(callback: (changeAccessor: IModelDecorationsChangeAccessor) => T, ownerId?: number): T | null; /** * Perform a minimum ammount of operations, in order to transform the decorations @@ -874,14 +874,14 @@ export interface ITextModel { * @param id The decoration id. * @return The decoration options or null if the decoration was not found. */ - getDecorationOptions(id: string): IModelDecorationOptions; + getDecorationOptions(id: string): IModelDecorationOptions | null; /** * Get the range associated with a decoration. * @param id The decoration id. * @return The decoration range or null if the decoration was not found. */ - getDecorationRange(id: string): Range; + getDecorationRange(id: string): Range | null; /** * Gets all the decorations for the line `lineNumber` as an array. @@ -929,12 +929,12 @@ export interface ITextModel { /** * @internal */ - _getTrackedRange(id: string): Range; + _getTrackedRange(id: string): Range | null; /** * @internal */ - _setTrackedRange(id: string, newRange: Range, newStickiness: TrackedRangeStickiness): string; + _setTrackedRange(id: string | null, newRange: Range | null, newStickiness: TrackedRangeStickiness): string | null; /** * Normalize a string containing whitespace according to indentation rules (converts to spaces or to tabs). @@ -971,7 +971,7 @@ export interface ITextModel { * @param cursorStateComputer A callback that can compute the resulting cursors state after the edit operations have been executed. * @return The cursor state returned by the `cursorStateComputer`. */ - pushEditOperations(beforeCursorState: Selection[], editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer): Selection[]; + pushEditOperations(beforeCursorState: Selection[], editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer): Selection[] | null; /** * Change the end of line sequence. This is the preferred way of @@ -998,7 +998,7 @@ export interface ITextModel { * The inverse edit operations will be pushed on the redo stack. * @internal */ - undo(): Selection[]; + undo(): Selection[] | null; /** * Is there anything in the undo stack? @@ -1011,7 +1011,7 @@ export interface ITextModel { * The inverse edit operations will be pushed on the undo stack. * @internal */ - redo(): Selection[]; + redo(): Selection[] | null; /** * Is there anything in the redo stack? @@ -1143,7 +1143,7 @@ export interface ITextBuffer { setEOL(newEOL: '\r\n' | '\n'): void; applyEdits(rawOperations: IIdentifiedSingleEditOperation[], recordTrimAutoWhitespace: boolean): ApplyEditsResult; - findMatchesLineByLine?(searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): FindMatch[]; + findMatchesLineByLine(searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): FindMatch[]; } /** @@ -1154,7 +1154,7 @@ export class ApplyEditsResult { constructor( public readonly reverseEdits: IIdentifiedSingleEditOperation[], public readonly changes: IInternalModelContentChange[], - public readonly trimAutoWhitespaceLineNumbers: number[] + public readonly trimAutoWhitespaceLineNumbers: number[] | null ) { } } diff --git a/src/vs/editor/common/model/editStack.ts b/src/vs/editor/common/model/editStack.ts index 73c61e9d6d0..eda58f8d7b6 100644 --- a/src/vs/editor/common/model/editStack.ts +++ b/src/vs/editor/common/model/editStack.ts @@ -14,8 +14,8 @@ interface IEditOperation { interface IStackElement { readonly beforeVersionId: number; - readonly beforeCursorState: Selection[]; - readonly afterCursorState: Selection[]; + readonly beforeCursorState: Selection[] | null; + readonly afterCursorState: Selection[] | null; readonly afterVersionId: number; undo(model: TextModel): void; @@ -25,7 +25,7 @@ interface IStackElement { class EditStackElement implements IStackElement { public readonly beforeVersionId: number; public readonly beforeCursorState: Selection[]; - public afterCursorState: Selection[]; + public afterCursorState: Selection[] | null; public afterVersionId: number; public editOperations: IEditOperation[]; @@ -68,8 +68,8 @@ function getModelEOL(model: TextModel): EndOfLineSequence { class EOLStackElement implements IStackElement { public readonly beforeVersionId: number; - public readonly beforeCursorState: Selection[]; - public readonly afterCursorState: Selection[]; + public readonly beforeCursorState: Selection[] | null; + public readonly afterCursorState: Selection[] | null; public afterVersionId: number; public eol: EndOfLineSequence; @@ -96,14 +96,14 @@ class EOLStackElement implements IStackElement { } export interface IUndoRedoResult { - selections: Selection[]; + selections: Selection[] | null; recordedVersionId: number; } export class EditStack { private model: TextModel; - private currentOpenStackElement: IStackElement; + private currentOpenStackElement: IStackElement | null; private past: IStackElement[]; private future: IStackElement[]; @@ -145,11 +145,11 @@ export class EditStack { this.pushStackElement(); } - public pushEditOperation(beforeCursorState: Selection[], editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer): Selection[] { + public pushEditOperation(beforeCursorState: Selection[], editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer): Selection[] | null { // No support for parallel universes :( this.future = []; - let stackElement: EditStackElement = null; + let stackElement: EditStackElement | null = null; if (this.currentOpenStackElement) { if (this.currentOpenStackElement instanceof EditStackElement) { @@ -168,13 +168,13 @@ export class EditStack { operations: this.model.applyEdits(editOperations) }; - stackElement.editOperations.push(inverseEditOperation); - stackElement.afterCursorState = EditStack._computeCursorState(cursorStateComputer, inverseEditOperation.operations); - stackElement.afterVersionId = this.model.getVersionId(); - return stackElement.afterCursorState; + stackElement!.editOperations.push(inverseEditOperation); + stackElement!.afterCursorState = EditStack._computeCursorState(cursorStateComputer, inverseEditOperation.operations); + stackElement!.afterVersionId = this.model.getVersionId(); + return stackElement!.afterCursorState; } - private static _computeCursorState(cursorStateComputer: ICursorStateComputer, inverseEditOperations: IIdentifiedSingleEditOperation[]): Selection[] { + private static _computeCursorState(cursorStateComputer: ICursorStateComputer, inverseEditOperations: IIdentifiedSingleEditOperation[]): Selection[] | null { try { return cursorStateComputer ? cursorStateComputer(inverseEditOperations) : null; } catch (e) { @@ -183,12 +183,12 @@ export class EditStack { } } - public undo(): IUndoRedoResult { + public undo(): IUndoRedoResult | null { this.pushStackElement(); if (this.past.length > 0) { - const pastStackElement = this.past.pop(); + const pastStackElement = this.past.pop()!; try { pastStackElement.undo(this.model); @@ -213,10 +213,10 @@ export class EditStack { return (this.past.length > 0); } - public redo(): IUndoRedoResult { + public redo(): IUndoRedoResult | null { if (this.future.length > 0) { - const futureStackElement = this.future.pop(); + const futureStackElement = this.future.pop()!; try { futureStackElement.redo(this.model); diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index ec867864618..9a2723697c0 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -164,9 +164,9 @@ export class IntervalNode implements IModelDecoration { constructor(id: string, start: number, end: number) { this.metadata = 0; - this.parent = null; - this.left = null; - this.right = null; + this.parent = this; + this.left = this; + this.right = this; setNodeColor(this, NodeColor.Red); this.start = start; @@ -177,7 +177,7 @@ export class IntervalNode implements IModelDecoration { this.id = id; this.ownerId = 0; - this.options = null; + this.options = null!; setNodeIsForValidation(this, false); _setNodeStickiness(this, TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges); setNodeIsInOverviewRuler(this, false); @@ -186,7 +186,7 @@ export class IntervalNode implements IModelDecoration { this.cachedVersionId = 0; this.cachedAbsoluteStart = start; this.cachedAbsoluteEnd = end; - this.range = null; + this.range = null!; setNodeIsVisited(this, false); } @@ -216,7 +216,7 @@ export class IntervalNode implements IModelDecoration { public setCachedOffsets(absoluteStart: number, absoluteEnd: number, cachedVersionId: number): void { if (this.cachedVersionId !== cachedVersionId) { - this.range = null; + this.range = null!; } this.cachedVersionId = cachedVersionId; this.cachedAbsoluteStart = absoluteStart; @@ -224,13 +224,13 @@ export class IntervalNode implements IModelDecoration { } public detach(): void { - this.parent = null; - this.left = null; - this.right = null; + this.parent = null!; + this.left = null!; + this.right = null!; } } -export const SENTINEL: IntervalNode = new IntervalNode(null, 0, 0); +export const SENTINEL: IntervalNode = new IntervalNode(null!, 0, 0); SENTINEL.parent = SENTINEL; SENTINEL.left = SENTINEL; SENTINEL.right = SENTINEL; diff --git a/src/vs/editor/common/model/mirrorTextModel.ts b/src/vs/editor/common/model/mirrorTextModel.ts index 3356106b912..377c17d52b2 100644 --- a/src/vs/editor/common/model/mirrorTextModel.ts +++ b/src/vs/editor/common/model/mirrorTextModel.ts @@ -30,13 +30,14 @@ export class MirrorTextModel { protected _lines: string[]; protected _eol: string; protected _versionId: number; - protected _lineStarts: PrefixSumComputer; + protected _lineStarts: PrefixSumComputer | null; constructor(uri: URI, lines: string[], eol: string, versionId: number) { this._uri = uri; this._lines = lines; this._eol = eol; this._versionId = versionId; + this._lineStarts = null; } dispose(): void { diff --git a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts index 12455b6e408..99ada260453 100644 --- a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts +++ b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts @@ -177,7 +177,7 @@ class PieceTreeSnapshot implements ITextSnapshot { } } - read(): string { + read(): string | null { if (this._pieces.length === 0) { if (this._index === 0) { this._index++; @@ -198,16 +198,22 @@ class PieceTreeSnapshot implements ITextSnapshot { } } +interface CacheEntry { + node: TreeNode; + nodeStartOffset: number; + nodeStartLineNumber?: number; +} + class PieceTreeSearchCache { private _limit: number; - private _cache: { node: TreeNode, nodeStartOffset: number, nodeStartLineNumber?: number }[]; + private _cache: CacheEntry[]; constructor(limit: number) { this._limit = limit; this._cache = []; } - public get(offset: number): { node: TreeNode, nodeStartOffset: number, nodeStartLineNumber?: number } { + public get(offset: number): CacheEntry | null { for (let i = this._cache.length - 1; i >= 0; i--) { let nodePos = this._cache[i]; if (nodePos.nodeStartOffset <= offset && nodePos.nodeStartOffset + nodePos.node.piece.length >= offset) { @@ -217,17 +223,17 @@ class PieceTreeSearchCache { return null; } - public get2(lineNumber: number): { node: TreeNode, nodeStartOffset: number, nodeStartLineNumber?: number } { + public get2(lineNumber: number): { node: TreeNode, nodeStartOffset: number, nodeStartLineNumber: number } | null { for (let i = this._cache.length - 1; i >= 0; i--) { let nodePos = this._cache[i]; if (nodePos.nodeStartLineNumber && nodePos.nodeStartLineNumber < lineNumber && nodePos.nodeStartLineNumber + nodePos.node.piece.lineFeedCnt >= lineNumber) { - return nodePos; + return <{ node: TreeNode, nodeStartOffset: number, nodeStartLineNumber: number }>nodePos; } } return null; } - public set(nodePosition: { node: TreeNode, nodeStartOffset: number, nodeStartLineNumber?: number }) { + public set(nodePosition: CacheEntry) { if (this._cache.length >= this._limit) { this._cache.shift(); } @@ -236,20 +242,22 @@ class PieceTreeSearchCache { public valdiate(offset: number) { let hasInvalidVal = false; - for (let i = 0; i < this._cache.length; i++) { - let nodePos = this._cache[i]; + let tmp: (CacheEntry | null)[] = this._cache; + for (let i = 0; i < tmp.length; i++) { + let nodePos = tmp[i]!; if (nodePos.node.parent === null || nodePos.nodeStartOffset >= offset) { - this._cache[i] = null; + tmp[i] = null; hasInvalidVal = true; continue; } } if (hasInvalidVal) { - let newArr = []; - for (let i = 0; i < this._cache.length; i++) { - if (this._cache[i] !== null) { - newArr.push(this._cache[i]); + let newArr: CacheEntry[] = []; + for (let i = 0; i < tmp.length; i++) { + const entry = tmp[i]; + if (entry !== null) { + newArr.push(entry); } } @@ -268,7 +276,7 @@ export class PieceTreeBase { protected _EOLNormalized: boolean; private _lastChangeBufferPos: BufferCursor; private _searchCache: PieceTreeSearchCache; - private _lastVisitedLine: { lineNumber: number, value: string }; + private _lastVisitedLine: { lineNumber: number; value: string; }; constructor(chunks: StringBuffer[], eol: '\r\n' | '\n', eolNormalized: boolean) { this.create(chunks, eol, eolNormalized); @@ -286,7 +294,7 @@ export class PieceTreeBase { this._EOLLength = eol.length; this._EOLNormalized = eolNormalized; - let lastNode: TreeNode = null; + let lastNode: TreeNode | null = null; for (let i = 0, len = chunks.length; i < len; i++) { if (chunks[i].buffer.length > 0) { if (!chunks[i].lineStarts) { @@ -306,7 +314,7 @@ export class PieceTreeBase { } this._searchCache = new PieceTreeSearchCache(1); - this._lastVisitedLine = { lineNumber: 0, value: null }; + this._lastVisitedLine = { lineNumber: 0, value: '' }; this.computeBufferMetadata(); } @@ -569,7 +577,7 @@ export class PieceTreeBase { let start = this.offsetInBuffer(node.piece.bufferIndex, startCursor); let end = this.offsetInBuffer(node.piece.bufferIndex, endCursor); - let m: RegExpExecArray; + let m: RegExpExecArray | null; // Reset regex to search from the beginning searcher.reset(start); let ret: BufferCursor = { line: 0, column: 0 }; @@ -693,7 +701,7 @@ export class PieceTreeBase { return resultLen; } - let m: RegExpExecArray; + let m: RegExpExecArray | null; // Reset regex to search from the beginning searcher.reset(0); do { @@ -714,7 +722,7 @@ export class PieceTreeBase { insert(offset: number, value: string, eolNormalized: boolean = false): void { this._EOLNormalized = this._EOLNormalized && eolNormalized; this._lastVisitedLine.lineNumber = 0; - this._lastVisitedLine.value = null; + this._lastVisitedLine.value = ''; if (this.root !== SENTINEL) { let { node, remainder, nodeStartOffset } = this.nodeAt(offset); @@ -738,7 +746,7 @@ export class PieceTreeBase { this._searchCache.valdiate(offset); } else if (nodeStartOffset + node.piece.length > offset) { // we are inserting into the middle of a node. - let nodesToDel = []; + let nodesToDel: TreeNode[] = []; let newRightPiece = new Piece( piece.bufferIndex, insertPosInBuffer, @@ -811,7 +819,7 @@ export class PieceTreeBase { delete(offset: number, cnt: number): void { this._lastVisitedLine.lineNumber = 0; - this._lastVisitedLine.value = null; + this._lastVisitedLine.value = ''; if (cnt <= 0 || this.root === SENTINEL) { return; @@ -854,7 +862,7 @@ export class PieceTreeBase { return; } - let nodesToDel = []; + let nodesToDel: TreeNode[] = []; let startSplitPosInBuffer = this.positionInBuffer(startNode, startPosition.remainder); this.deleteNodeTail(startNode, startSplitPosInBuffer); @@ -884,7 +892,7 @@ export class PieceTreeBase { insertContentToNodeLeft(value: string, node: TreeNode) { // we are inserting content to the beginning of node - let nodesToDel = []; + let nodesToDel: TreeNode[] = []; if (this.shouldCheckCRLF() && this.endWithCR(value) && this.startWithLF(node)) { // move `\n` to new node. @@ -935,7 +943,9 @@ export class PieceTreeBase { this.validateCRLFWithPrevNode(newNode); } - positionInBuffer(node: TreeNode, remainder: number, ret?: BufferCursor): BufferCursor { + positionInBuffer(node: TreeNode, remainder: number): BufferCursor; + positionInBuffer(node: TreeNode, remainder: number, ret: BufferCursor): null; + positionInBuffer(node: TreeNode, remainder: number, ret?: BufferCursor): BufferCursor | null { let piece = node.piece; let bufferIndex = node.piece.bufferIndex; let lineStarts = this._buffers[bufferIndex].lineStarts; @@ -948,9 +958,9 @@ export class PieceTreeBase { let low = piece.start.line; let high = piece.end.line; - let mid: number; - let midStop: number; - let midStart: number; + let mid: number = 0; + let midStop: number = 0; + let midStart: number = 0; while (low <= high) { mid = low + ((high - low) / 2) | 0; @@ -1028,7 +1038,7 @@ export class PieceTreeBase { if (text.length > AverageBufferSize) { // the content is large, operations like substring, charCode becomes slow // so here we split it into smaller chunks, just like what we did for CR/LF normalization - let newPieces = []; + let newPieces: Piece[] = []; while (text.length > AverageBufferSize) { const lastChar = text.charCodeAt(AverageBufferSize - 1); let splitText; @@ -1387,7 +1397,7 @@ export class PieceTreeBase { } } - return null; + return null!; } nodeAt2(lineNumber: number, column: number): NodePosition { @@ -1454,7 +1464,7 @@ export class PieceTreeBase { x = x.next(); } - return null; + return null!; } nodeCharCodeAt(node: TreeNode, offset: number): number { @@ -1544,7 +1554,7 @@ export class PieceTreeBase { } fixCRLF(prev: TreeNode, next: TreeNode) { - let nodesToDel = []; + let nodesToDel: TreeNode[] = []; // update node let lineStarts = this._buffers[prev.piece.bufferIndex].lineStarts; let newEnd: BufferCursor; @@ -1676,7 +1686,7 @@ export class PieceTreeBase { * / * z */ - rbInsertRight(node: TreeNode, p: Piece): TreeNode { + rbInsertRight(node: TreeNode | null, p: Piece): TreeNode { let z = new TreeNode(p, NodeColor.Red); z.left = SENTINEL; z.right = SENTINEL; @@ -1688,11 +1698,11 @@ export class PieceTreeBase { if (x === SENTINEL) { this.root = z; z.color = NodeColor.Black; - } else if (node.right === SENTINEL) { - node.right = z; - z.parent = node; + } else if (node!.right === SENTINEL) { + node!.right = z; + z.parent = node!; } else { - let nextNode = leftest(node.right); + let nextNode = leftest(node!.right); nextNode.left = z; z.parent = nextNode; } @@ -1708,7 +1718,7 @@ export class PieceTreeBase { * \ * z */ - rbInsertLeft(node: TreeNode, p: Piece): TreeNode { + rbInsertLeft(node: TreeNode | null, p: Piece): TreeNode { let z = new TreeNode(p, NodeColor.Red); z.left = SENTINEL; z.right = SENTINEL; @@ -1716,15 +1726,14 @@ export class PieceTreeBase { z.size_left = 0; z.lf_left = 0; - let x = this.root; - if (x === SENTINEL) { + if (this.root === SENTINEL) { this.root = z; z.color = NodeColor.Black; - } else if (node.left === SENTINEL) { - node.left = z; - z.parent = node; + } else if (node!.left === SENTINEL) { + node!.left = z; + z.parent = node!; } else { - let prevNode = righttest(node.left); // a + let prevNode = righttest(node!.left); // a prevNode.right = z; z.parent = prevNode; } diff --git a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts index b60f1d90e3a..ee21a3311c9 100644 --- a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts +++ b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts @@ -13,11 +13,11 @@ import { SearchData } from 'vs/editor/common/model/textModelSearch'; export interface IValidatedEditOperation { sortIndex: number; - identifier: ISingleEditOperationIdentifier; + identifier: ISingleEditOperationIdentifier | null; range: Range; rangeOffset: number; rangeLength: number; - lines: string[]; + lines: string[] | null; forceMoveMarkers: boolean; isAutoWhitespaceEdit: boolean; } @@ -192,12 +192,12 @@ export class PieceTreeTextBuffer implements ITextBuffer { } operations[i] = { sortIndex: i, - identifier: op.identifier, + identifier: op.identifier || null, range: validatedRange, rangeOffset: this.getOffsetAt(validatedRange.startLineNumber, validatedRange.startColumn), rangeLength: this.getValueLengthInRange(validatedRange), lines: op.text ? op.text.split(/\r\n|\r|\n/) : null, - forceMoveMarkers: op.forceMoveMarkers, + forceMoveMarkers: Boolean(op.forceMoveMarkers), isAutoWhitespaceEdit: op.isAutoWhitespaceEdit || false }; } @@ -270,7 +270,7 @@ export class PieceTreeTextBuffer implements ITextBuffer { const contentChanges = this._doApplyEdits(operations); - let trimAutoWhitespaceLineNumbers: number[] = null; + let trimAutoWhitespaceLineNumbers: number[] | null = null; if (recordTrimAutoWhitespace && newTrimAutoWhitespaceCandidates.length > 0) { // sort line numbers auto whitespace removal candidates for next edit descending newTrimAutoWhitespaceCandidates.sort((a, b) => b.lineNumber - a.lineNumber); @@ -415,7 +415,7 @@ export class PieceTreeTextBuffer implements ITextBuffer { if (editingLinesCnt < insertingLinesCnt) { let newLinesContent: string[] = []; for (let j = editingLinesCnt + 1; j <= insertingLinesCnt; j++) { - newLinesContent.push(op.lines[j]); + newLinesContent.push(op.lines![j]); } newLinesContent[newLinesContent.length - 1] = this.getLineContent(startLineNumber + insertingLinesCnt - 1); @@ -450,9 +450,9 @@ export class PieceTreeTextBuffer implements ITextBuffer { public static _getInverseEditRanges(operations: IValidatedEditOperation[]): Range[] { let result: Range[] = []; - let prevOpEndLineNumber: number; - let prevOpEndColumn: number; - let prevOp: IValidatedEditOperation = null; + let prevOpEndLineNumber: number = 0; + let prevOpEndColumn: number = 0; + let prevOp: IValidatedEditOperation | null = null; for (let i = 0, len = operations.length; i < len; i++) { let op = operations[i]; diff --git a/src/vs/editor/common/model/pieceTreeTextBuffer/rbTreeBase.ts b/src/vs/editor/common/model/pieceTreeTextBuffer/rbTreeBase.ts index 69efbdb8802..ea9a7d043a5 100644 --- a/src/vs/editor/common/model/pieceTreeTextBuffer/rbTreeBase.ts +++ b/src/vs/editor/common/model/pieceTreeTextBuffer/rbTreeBase.ts @@ -21,9 +21,9 @@ export class TreeNode { this.color = color; this.size_left = 0; this.lf_left = 0; - this.parent = null; - this.left = null; - this.right = null; + this.parent = this; + this.left = this; + this.right = this; } public next(): TreeNode { @@ -71,9 +71,9 @@ export class TreeNode { } public detach(): void { - this.parent = null; - this.left = null; - this.right = null; + this.parent = null!; + this.left = null!; + this.right = null!; } } @@ -82,7 +82,7 @@ export const enum NodeColor { Red = 1, } -export const SENTINEL: TreeNode = new TreeNode(null, NodeColor.Black); +export const SENTINEL: TreeNode = new TreeNode(null!, NodeColor.Black); SENTINEL.parent = SENTINEL; SENTINEL.left = SENTINEL; SENTINEL.right = SENTINEL; diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index 8533d5951c6..1d82601e095 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -6,7 +6,7 @@ import { URI } from 'vs/base/common/uri'; import { Event, Emitter } from 'vs/base/common/event'; import * as model from 'vs/editor/common/model'; -import { LanguageIdentifier, TokenizationRegistry, LanguageId } from 'vs/editor/common/modes'; +import { LanguageIdentifier, TokenizationRegistry, LanguageId, IState } from 'vs/editor/common/modes'; import { EditStack } from 'vs/editor/common/model/editStack'; import { Range, IRange } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; @@ -78,7 +78,7 @@ export function createTextBufferFactoryFromStream(stream: IStringStream, filter? export function createTextBufferFactoryFromSnapshot(snapshot: ITextSnapshot): model.ITextBufferFactory { let builder = createTextBufferBuilder(); - let chunk: string; + let chunk: string | null; while (typeof (chunk = snapshot.read()) === 'string') { builder.acceptChunk(chunk); } @@ -121,7 +121,7 @@ class TextModelSnapshot implements ITextSnapshot { this._eos = false; } - public read(): string { + public read(): string | null { if (this._eos) { return null; } @@ -153,6 +153,24 @@ class TextModelSnapshot implements ITextSnapshot { } } +const invalidChangeAccessor: model.IModelDecorationsChangeAccessor = { + addDecoration: (range: IRange, options: model.IModelDecorationOptions): string => { + throw new Error(`Invalid change accessor`); + }, + changeDecoration: (id: string, newRange: IRange): void => { + throw new Error(`Invalid change accessor`); + }, + changeDecorationOptions: (id: string, options: model.IModelDecorationOptions) => { + throw new Error(`Invalid change accessor`); + }, + removeDecoration: (id: string): void => { + throw new Error(`Invalid change accessor`); + }, + deltaDecorations: (oldDecorations: string[], newDecorations: model.IModelDeltaDecoration[]): string[] => { + throw new Error(`Invalid change accessor`); + } +}; + export class TextModel extends Disposable implements model.ITextModel { private static readonly MODEL_SYNC_LIMIT = 50 * 1024 * 1024; // 50 MB @@ -169,7 +187,7 @@ export class TextModel extends Disposable implements model.ITextModel { largeFileOptimizations: EDITOR_MODEL_DEFAULTS.largeFileOptimizations, }; - public static createFromString(text: string, options: model.ITextModelCreationOptions = TextModel.DEFAULT_CREATION_OPTIONS, languageIdentifier: LanguageIdentifier = null, uri: URI = null): TextModel { + public static createFromString(text: string, options: model.ITextModelCreationOptions = TextModel.DEFAULT_CREATION_OPTIONS, languageIdentifier: LanguageIdentifier | null = null, uri: URI | null = null): TextModel { return new TextModel(text, options, languageIdentifier, uri); } @@ -245,7 +263,7 @@ export class TextModel extends Disposable implements model.ITextModel { private _commandManager: EditStack; private _isUndoing: boolean; private _isRedoing: boolean; - private _trimAutoWhitespaceLines: number[]; + private _trimAutoWhitespaceLines: number[] | null; //#endregion //#region Decorations @@ -267,7 +285,7 @@ export class TextModel extends Disposable implements model.ITextModel { /*private*/_tokens: ModelLinesTokens; //#endregion - constructor(source: string | model.ITextBufferFactory, creationOptions: model.ITextModelCreationOptions, languageIdentifier: LanguageIdentifier, associatedResource: URI = null) { + constructor(source: string | model.ITextBufferFactory, creationOptions: model.ITextModelCreationOptions, languageIdentifier: LanguageIdentifier | null, associatedResource: URI | null = null) { super(); // Generate a new unique model id @@ -346,16 +364,11 @@ export class TextModel extends Disposable implements model.ITextModel { public dispose(): void { this._isDisposing = true; this._onWillDispose.fire(); - this._commandManager = null; - this._decorations = null; - this._decorationsTree = null; this._tokenizationListener.dispose(); this._languageRegistryListener.dispose(); this._clearTimers(); - this._tokens = null; this._isDisposed = true; // Null out members, such that any use of a disposed model will throw exceptions sooner rather than later - this._buffer = null; super.dispose(); this._isDisposing = false; } @@ -1109,13 +1122,17 @@ export class TextModel extends Disposable implements model.ITextModel { return TextModelSearch.findMatches(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchRange, captureMatches, limitResultCount); } - public findNextMatch(searchString: string, rawSearchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string, captureMatches: boolean): model.FindMatch { + public findNextMatch(searchString: string, rawSearchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string, captureMatches: boolean): model.FindMatch | null { this._assertNotDisposed(); const searchStart = this.validatePosition(rawSearchStart); if (!isRegex && searchString.indexOf('\n') < 0) { const searchParams = new SearchParams(searchString, isRegex, matchCase, wordSeparators); const searchData = searchParams.parseSearchRequest(); + if (!searchData) { + return null; + } + const lineCount = this.getLineCount(); let searchRange = new Range(searchStart.lineNumber, searchStart.column, lineCount, this.getLineMaxColumn(lineCount)); let ret = this.findMatchesLineByLine(searchRange, searchData, captureMatches, 1); @@ -1137,7 +1154,7 @@ export class TextModel extends Disposable implements model.ITextModel { return TextModelSearch.findNextMatch(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchStart, captureMatches); } - public findPreviousMatch(searchString: string, rawSearchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string, captureMatches: boolean): model.FindMatch { + public findPreviousMatch(searchString: string, rawSearchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string, captureMatches: boolean): model.FindMatch | null { this._assertNotDisposed(); const searchStart = this.validatePosition(rawSearchStart); return TextModelSearch.findPreviousMatch(this, new SearchParams(searchString, isRegex, matchCase, wordSeparators), searchStart, captureMatches); @@ -1166,7 +1183,7 @@ export class TextModel extends Disposable implements model.ITextModel { } } - public pushEditOperations(beforeCursorState: Selection[], editOperations: model.IIdentifiedSingleEditOperation[], cursorStateComputer: model.ICursorStateComputer): Selection[] { + public pushEditOperations(beforeCursorState: Selection[], editOperations: model.IIdentifiedSingleEditOperation[], cursorStateComputer: model.ICursorStateComputer): Selection[] | null { try { this._onDidChangeDecorations.beginDeferredEmit(); this._eventEmitter.beginDeferredEmit(); @@ -1177,7 +1194,7 @@ export class TextModel extends Disposable implements model.ITextModel { } } - private _pushEditOperations(beforeCursorState: Selection[], editOperations: model.IIdentifiedSingleEditOperation[], cursorStateComputer: model.ICursorStateComputer): Selection[] { + private _pushEditOperations(beforeCursorState: Selection[], editOperations: model.IIdentifiedSingleEditOperation[], cursorStateComputer: model.ICursorStateComputer): Selection[] | null { if (this._options.trimAutoWhitespace && this._trimAutoWhitespaceLines) { // Go through each saved line number and insert a trim whitespace edit // if it is safe to do so (no conflicts with other edits). @@ -1397,7 +1414,7 @@ export class TextModel extends Disposable implements model.ITextModel { return result.reverseEdits; } - private _undo(): Selection[] { + private _undo(): Selection[] | null { this._isUndoing = true; let r = this._commandManager.undo(); this._isUndoing = false; @@ -1411,7 +1428,7 @@ export class TextModel extends Disposable implements model.ITextModel { return r.selections; } - public undo(): Selection[] { + public undo(): Selection[] | null { try { this._onDidChangeDecorations.beginDeferredEmit(); this._eventEmitter.beginDeferredEmit(); @@ -1426,7 +1443,7 @@ export class TextModel extends Disposable implements model.ITextModel { return this._commandManager.canUndo(); } - private _redo(): Selection[] { + private _redo(): Selection[] | null { this._isRedoing = true; let r = this._commandManager.redo(); this._isRedoing = false; @@ -1440,7 +1457,7 @@ export class TextModel extends Disposable implements model.ITextModel { return r.selections; } - public redo(): Selection[] { + public redo(): Selection[] | null { try { this._onDidChangeDecorations.beginDeferredEmit(); this._eventEmitter.beginDeferredEmit(); @@ -1459,7 +1476,7 @@ export class TextModel extends Disposable implements model.ITextModel { //#region Decorations - public changeDecorations(callback: (changeAccessor: model.IModelDecorationsChangeAccessor) => T, ownerId: number = 0): T { + public changeDecorations(callback: (changeAccessor: model.IModelDecorationsChangeAccessor) => T, ownerId: number = 0): T | null { this._assertNotDisposed(); try { @@ -1470,7 +1487,7 @@ export class TextModel extends Disposable implements model.ITextModel { } } - private _changeDecorations(ownerId: number, callback: (changeAccessor: model.IModelDecorationsChangeAccessor) => T): T { + private _changeDecorations(ownerId: number, callback: (changeAccessor: model.IModelDecorationsChangeAccessor) => T): T | null { let changeAccessor: model.IModelDecorationsChangeAccessor = { addDecoration: (range: IRange, options: model.IModelDecorationOptions): string => { this._onDidChangeDecorations.fire(); @@ -1497,17 +1514,18 @@ export class TextModel extends Disposable implements model.ITextModel { return this._deltaDecorationsImpl(ownerId, oldDecorations, newDecorations); } }; - let result: T = null; + let result: T | null = null; try { result = callback(changeAccessor); } catch (e) { onUnexpectedError(e); } // Invalidate change accessor - changeAccessor.addDecoration = null; - changeAccessor.changeDecoration = null; - changeAccessor.removeDecoration = null; - changeAccessor.deltaDecorations = null; + changeAccessor.addDecoration = invalidChangeAccessor.addDecoration; + changeAccessor.changeDecoration = invalidChangeAccessor.changeDecoration; + changeAccessor.changeDecorationOptions = invalidChangeAccessor.changeDecorationOptions; + changeAccessor.removeDecoration = invalidChangeAccessor.removeDecoration; + changeAccessor.deltaDecorations = invalidChangeAccessor.deltaDecorations; return result; } @@ -1530,11 +1548,11 @@ export class TextModel extends Disposable implements model.ITextModel { } } - _getTrackedRange(id: string): Range { + _getTrackedRange(id: string): Range | null { return this.getDecorationRange(id); } - _setTrackedRange(id: string, newRange: Range, newStickiness: model.TrackedRangeStickiness): string { + _setTrackedRange(id: string | null, newRange: Range | null, newStickiness: model.TrackedRangeStickiness): string | null { const node = (id ? this._decorations[id] : null); if (!node) { @@ -1577,7 +1595,7 @@ export class TextModel extends Disposable implements model.ITextModel { } } - public getDecorationOptions(decorationId: string): model.IModelDecorationOptions { + public getDecorationOptions(decorationId: string): model.IModelDecorationOptions | null { const node = this._decorations[decorationId]; if (!node) { return null; @@ -1585,7 +1603,7 @@ export class TextModel extends Disposable implements model.ITextModel { return node.options; } - public getDecorationRange(decorationId: string): Range { + public getDecorationRange(decorationId: string): Range | null { const node = this._decorations[decorationId]; if (!node) { return null; @@ -1702,7 +1720,7 @@ export class TextModel extends Disposable implements model.ITextModel { let result = new Array(newDecorationsLen); while (oldDecorationIndex < oldDecorationsLen || newDecorationIndex < newDecorationsLen) { - let node: IntervalNode = null; + let node: IntervalNode | null = null; if (oldDecorationIndex < oldDecorationsLen) { // (1) get ourselves an old node @@ -1771,9 +1789,9 @@ export class TextModel extends Disposable implements model.ITextModel { const eventBuilder = new ModelTokensChangedEventBuilder(); let nonWhitespaceColumn = this.getLineFirstNonWhitespaceColumn(startLineNumber); - let fakeLines = []; + let fakeLines: string[] = []; let i = startLineNumber - 1; - let initialState = null; + let initialState: IState | null = null; if (nonWhitespaceColumn > 0) { while (nonWhitespaceColumn > 0 && i >= 1) { let newNonWhitespaceIndex = this.getLineFirstNonWhitespaceColumn(i); @@ -1986,7 +2004,7 @@ export class TextModel extends Disposable implements model.ITextModel { // Having tokens allows implementing additional helper methods - public getWordAtPosition(_position: IPosition): model.IWordAtPosition { + public getWordAtPosition(_position: IPosition): model.IWordAtPosition | null { this._assertNotDisposed(); const position = this.validatePosition(_position); const lineContent = this.getLineContent(position.lineNumber); @@ -2027,13 +2045,13 @@ export class TextModel extends Disposable implements model.ITextModel { const languageId = lineTokens.getLanguageId(tokenIndex); // go left until a different language is hit - let startOffset: number; + let startOffset = 0; for (let i = tokenIndex; i >= 0 && lineTokens.getLanguageId(i) === languageId; i--) { startOffset = lineTokens.getStartOffset(i); } // go right until a different language is hit - let endOffset: number; + let endOffset = lineTokens.getLineContent().length; for (let i = tokenIndex, tokenCount = lineTokens.getCount(); i < tokenCount && lineTokens.getLanguageId(i) === languageId; i++) { endOffset = lineTokens.getEndOffset(i); } @@ -2057,7 +2075,7 @@ export class TextModel extends Disposable implements model.ITextModel { }; } - public findMatchingBracketUp(_bracket: string, _position: IPosition): Range { + public findMatchingBracketUp(_bracket: string, _position: IPosition): Range | null { let bracket = _bracket.toLowerCase(); let position = this.validatePosition(_position); @@ -2078,11 +2096,11 @@ export class TextModel extends Disposable implements model.ITextModel { return this._findMatchingBracketUp(data, position); } - public matchBracket(position: IPosition): [Range, Range] { + public matchBracket(position: IPosition): [Range, Range] | null { return this._matchBracket(this.validatePosition(position)); } - private _matchBracket(position: Position): [Range, Range] { + private _matchBracket(position: Position): [Range, Range] | null { const lineNumber = position.lineNumber; const lineTokens = this._getLineTokens(lineNumber); const lineText = this._buffer.getLineContent(lineNumber); @@ -2102,7 +2120,7 @@ export class TextModel extends Disposable implements model.ITextModel { // it might be the case that [currentTokenStart -> currentTokenEnd] contains multiple brackets // `bestResult` will contain the most right-side result - let bestResult: [Range, Range] = null; + let bestResult: [Range, Range] | null = null; while (true) { let foundBracket = BracketsUtils.findNextBracketInToken(currentModeBrackets.forwardRegex, lineNumber, lineText, searchStartOffset, searchEndOffset); if (!foundBracket) { @@ -2161,7 +2179,7 @@ export class TextModel extends Disposable implements model.ITextModel { return null; } - private _matchFoundBracket(foundBracket: Range, data: RichEditBracket, isOpen: boolean): [Range, Range] { + private _matchFoundBracket(foundBracket: Range, data: RichEditBracket, isOpen: boolean): [Range, Range] | null { if (!data) { return null; } @@ -2181,7 +2199,7 @@ export class TextModel extends Disposable implements model.ITextModel { return null; } - private _findMatchingBracketUp(bracket: RichEditBracket, position: Position): Range { + private _findMatchingBracketUp(bracket: RichEditBracket, position: Position): Range | null { // console.log('_findMatchingBracketUp: ', 'bracket: ', JSON.stringify(bracket), 'startPosition: ', String(position)); const languageId = bracket.languageIdentifier.id; @@ -2242,7 +2260,7 @@ export class TextModel extends Disposable implements model.ITextModel { return null; } - private _findMatchingBracketDown(bracket: RichEditBracket, position: Position): Range { + private _findMatchingBracketDown(bracket: RichEditBracket, position: Position): Range | null { // console.log('_findMatchingBracketDown: ', 'bracket: ', JSON.stringify(bracket), 'startPosition: ', String(position)); const languageId = bracket.languageIdentifier.id; @@ -2302,11 +2320,11 @@ export class TextModel extends Disposable implements model.ITextModel { return null; } - public findPrevBracket(_position: IPosition): model.IFoundBracket { + public findPrevBracket(_position: IPosition): model.IFoundBracket | null { const position = this.validatePosition(_position); let languageId: LanguageId = -1; - let modeBrackets: RichEditBrackets = null; + let modeBrackets: RichEditBrackets | null = null; for (let lineNumber = position.lineNumber; lineNumber >= 1; lineNumber--) { const lineTokens = this._getLineTokens(lineNumber); const tokenCount = lineTokens.getCount(); @@ -2346,11 +2364,11 @@ export class TextModel extends Disposable implements model.ITextModel { return null; } - public findNextBracket(_position: IPosition): model.IFoundBracket { + public findNextBracket(_position: IPosition): model.IFoundBracket | null { const position = this.validatePosition(_position); let languageId: LanguageId = -1; - let modeBrackets: RichEditBrackets = null; + let modeBrackets: RichEditBrackets | null = null; for (let lineNumber = position.lineNumber, lineCount = this.getLineCount(); lineNumber <= lineCount; lineNumber++) { const lineTokens = this._getLineTokens(lineNumber); const tokenCount = lineTokens.getCount(); @@ -2391,7 +2409,7 @@ export class TextModel extends Disposable implements model.ITextModel { return null; } - private _toFoundBracket(modeBrackets: RichEditBrackets, r: Range): model.IFoundBracket { + private _toFoundBracket(modeBrackets: RichEditBrackets, r: Range): model.IFoundBracket | null { if (!r) { return null; } @@ -2454,7 +2472,7 @@ export class TextModel extends Disposable implements model.ITextModel { } const foldingRules = LanguageConfigurationRegistry.getFoldingRules(this._languageIdentifier.id); - const offSide = foldingRules && foldingRules.offSide; + const offSide = Boolean(foldingRules && foldingRules.offSide); let up_aboveContentLineIndex = -2; /* -2 is a marker for not having computed it */ let up_aboveContentLineIndent = -1; @@ -2624,7 +2642,7 @@ export class TextModel extends Disposable implements model.ITextModel { } const foldingRules = LanguageConfigurationRegistry.getFoldingRules(this._languageIdentifier.id); - const offSide = foldingRules && foldingRules.offSide; + const offSide = Boolean(foldingRules && foldingRules.offSide); let result: number[] = new Array(endLineNumber - startLineNumber + 1); @@ -2797,7 +2815,7 @@ export class ModelDecorationOverviewRulerOptions implements model.IModelDecorati readonly color: string | ThemeColor; readonly darkColor: string | ThemeColor; readonly position: model.OverviewRulerLane; - private _resolvedColor: string; + private _resolvedColor: string | null; constructor(options: model.IModelDecorationOverviewRulerOptions) { this.color = options.color || strings.empty; @@ -2847,20 +2865,20 @@ export class ModelDecorationOptions implements model.IModelDecorationOptions { readonly stickiness: model.TrackedRangeStickiness; readonly zIndex: number; - readonly className: string; - readonly hoverMessage: IMarkdownString | IMarkdownString[]; - readonly glyphMarginHoverMessage: IMarkdownString | IMarkdownString[]; + readonly className: string | null; + readonly hoverMessage: IMarkdownString | IMarkdownString[] | null; + readonly glyphMarginHoverMessage: IMarkdownString | IMarkdownString[] | null; readonly isWholeLine: boolean; readonly showIfCollapsed: boolean; readonly collapseOnReplaceEdit: boolean; - readonly overviewRuler: ModelDecorationOverviewRulerOptions; - readonly glyphMarginClassName: string; - readonly linesDecorationsClassName: string; - readonly marginClassName: string; - readonly inlineClassName: string; + readonly overviewRuler: ModelDecorationOverviewRulerOptions | null; + readonly glyphMarginClassName: string | null; + readonly linesDecorationsClassName: string | null; + readonly marginClassName: string | null; + readonly inlineClassName: string | null; readonly inlineClassNameAffectsLetterSpacing: boolean; - readonly beforeContentClassName: string; - readonly afterContentClassName: string; + readonly beforeContentClassName: string | null; + readonly afterContentClassName: string | null; private constructor(options: model.IModelDecorationOptions) { this.stickiness = options.stickiness || model.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges; @@ -2946,7 +2964,7 @@ export class DidChangeContentEmitter extends Disposable { public readonly slowEvent: Event = this._slowEmitter.event; private _deferredCnt: number; - private _deferredEvent: InternalModelContentChangeEvent; + private _deferredEvent: InternalModelContentChangeEvent | null; constructor() { super(); diff --git a/src/vs/editor/common/model/textModelEvents.ts b/src/vs/editor/common/model/textModelEvents.ts index 820ec2ea045..64f5d53e127 100644 --- a/src/vs/editor/common/model/textModelEvents.ts +++ b/src/vs/editor/common/model/textModelEvents.ts @@ -238,7 +238,7 @@ export class ModelRawContentChangedEvent { } public static merge(a: ModelRawContentChangedEvent, b: ModelRawContentChangedEvent): ModelRawContentChangedEvent { - const changes = [].concat(a.changes).concat(b.changes); + const changes = ([] as ModelRawChange[]).concat(a.changes).concat(b.changes); const versionId = b.versionId; const isUndoing = (a.isUndoing || b.isUndoing); const isRedoing = (a.isRedoing || b.isRedoing); @@ -262,7 +262,7 @@ export class InternalModelContentChangeEvent { } private static _mergeChangeEvents(a: IModelContentChangedEvent, b: IModelContentChangedEvent): IModelContentChangedEvent { - const changes = [].concat(a.changes).concat(b.changes); + const changes = ([] as IModelContentChange[]).concat(a.changes).concat(b.changes); const eol = b.eol; const versionId = b.versionId; const isUndoing = (a.isUndoing || b.isUndoing); diff --git a/src/vs/editor/common/model/textModelSearch.ts b/src/vs/editor/common/model/textModelSearch.ts index c75b008b120..d523c8de262 100644 --- a/src/vs/editor/common/model/textModelSearch.ts +++ b/src/vs/editor/common/model/textModelSearch.ts @@ -26,7 +26,7 @@ export class SearchParams { this.wordSeparators = wordSeparators; } - public parseSearchRequest(): SearchData { + public parseSearchRequest(): SearchData | null { if (this.searchString === '') { return null; } @@ -39,7 +39,7 @@ export class SearchParams { multiline = (this.searchString.indexOf('\n') >= 0); } - let regex: RegExp = null; + let regex: RegExp | null = null; try { regex = strings.createRegExp(this.searchString, this.isRegex, { matchCase: this.matchCase, @@ -102,13 +102,13 @@ export class SearchData { /** * The word separator classifier. */ - public readonly wordSeparators: WordCharacterClassifier; + public readonly wordSeparators: WordCharacterClassifier | null; /** * The simple string to search for (if possible). */ - public readonly simpleSearch: string; + public readonly simpleSearch: string | null; - constructor(regex: RegExp, wordSeparators: WordCharacterClassifier, simpleSearch: string) { + constructor(regex: RegExp, wordSeparators: WordCharacterClassifier | null, simpleSearch: string | null) { this.regex = regex; this.wordSeparators = wordSeparators; this.simpleSearch = simpleSearch; @@ -193,10 +193,10 @@ export class TextModelSearch { * Multiline search always executes on the lines concatenated with \n. * We must therefore compensate for the count of \n in case the model is CRLF */ - private static _getMultilineMatchRange(model: TextModel, deltaOffset: number, text: string, lfCounter: LineFeedCounter, matchIndex: number, match0: string): Range { + private static _getMultilineMatchRange(model: TextModel, deltaOffset: number, text: string, lfCounter: LineFeedCounter | null, matchIndex: number, match0: string): Range { let startOffset: number; let lineFeedCountBeforeMatch = 0; - if (model.getEOL() === '\r\n') { + if (lfCounter) { lineFeedCountBeforeMatch = lfCounter.findLineFeedCountBeforeOffset(matchIndex); startOffset = deltaOffset + matchIndex + lineFeedCountBeforeMatch /* add as many \r as there were \n */; } else { @@ -204,7 +204,7 @@ export class TextModelSearch { } let endOffset: number; - if (model.getEOL() === '\r\n') { + if (lfCounter) { let lineFeedCountBeforeEndOfMatch = lfCounter.findLineFeedCountBeforeOffset(matchIndex + match0.length); let lineFeedCountInMatch = lineFeedCountBeforeEndOfMatch - lineFeedCountBeforeMatch; endOffset = startOffset + match0.length + lineFeedCountInMatch /* add as many \r as there were \n */; @@ -228,7 +228,7 @@ export class TextModelSearch { const result: FindMatch[] = []; let counter = 0; - let m: RegExpExecArray; + let m: RegExpExecArray | null; searcher.reset(0); while ((m = searcher.next(text))) { result[counter++] = createFindMatch(this._getMultilineMatchRange(model, deltaOffset, text, lfCounter, m.index, m[0]), m, captureMatches); @@ -289,7 +289,7 @@ export class TextModelSearch { } const searcher = new Searcher(searchData.wordSeparators, searchData.regex); - let m: RegExpExecArray; + let m: RegExpExecArray | null; // Reset regex to search from the beginning searcher.reset(0); do { @@ -304,7 +304,7 @@ export class TextModelSearch { return resultLen; } - public static findNextMatch(model: TextModel, searchParams: SearchParams, searchStart: Position, captureMatches: boolean): FindMatch { + public static findNextMatch(model: TextModel, searchParams: SearchParams, searchStart: Position, captureMatches: boolean): FindMatch | null { const searchData = searchParams.parseSearchRequest(); if (!searchData) { return null; @@ -318,7 +318,7 @@ export class TextModelSearch { return this._doFindNextMatchLineByLine(model, searchStart, searcher, captureMatches); } - private static _doFindNextMatchMultiline(model: TextModel, searchStart: Position, searcher: Searcher, captureMatches: boolean): FindMatch { + private static _doFindNextMatchMultiline(model: TextModel, searchStart: Position, searcher: Searcher, captureMatches: boolean): FindMatch | null { const searchTextStart = new Position(searchStart.lineNumber, 1); const deltaOffset = model.getOffsetAt(searchTextStart); const lineCount = model.getLineCount(); @@ -345,7 +345,7 @@ export class TextModelSearch { return null; } - private static _doFindNextMatchLineByLine(model: TextModel, searchStart: Position, searcher: Searcher, captureMatches: boolean): FindMatch { + private static _doFindNextMatchLineByLine(model: TextModel, searchStart: Position, searcher: Searcher, captureMatches: boolean): FindMatch | null { const lineCount = model.getLineCount(); const startLineNumber = searchStart.lineNumber; @@ -368,10 +368,10 @@ export class TextModelSearch { return null; } - private static _findFirstMatchInLine(searcher: Searcher, text: string, lineNumber: number, fromColumn: number, captureMatches: boolean): FindMatch { + private static _findFirstMatchInLine(searcher: Searcher, text: string, lineNumber: number, fromColumn: number, captureMatches: boolean): FindMatch | null { // Set regex to search from column searcher.reset(fromColumn - 1); - const m: RegExpExecArray = searcher.next(text); + const m: RegExpExecArray | null = searcher.next(text); if (m) { return createFindMatch( new Range(lineNumber, m.index + 1, lineNumber, m.index + 1 + m[0].length), @@ -382,7 +382,7 @@ export class TextModelSearch { return null; } - public static findPreviousMatch(model: TextModel, searchParams: SearchParams, searchStart: Position, captureMatches: boolean): FindMatch { + public static findPreviousMatch(model: TextModel, searchParams: SearchParams, searchStart: Position, captureMatches: boolean): FindMatch | null { const searchData = searchParams.parseSearchRequest(); if (!searchData) { return null; @@ -396,7 +396,7 @@ export class TextModelSearch { return this._doFindPreviousMatchLineByLine(model, searchStart, searcher, captureMatches); } - private static _doFindPreviousMatchMultiline(model: TextModel, searchStart: Position, searcher: Searcher, captureMatches: boolean): FindMatch { + private static _doFindPreviousMatchMultiline(model: TextModel, searchStart: Position, searcher: Searcher, captureMatches: boolean): FindMatch | null { const matches = this._doFindMatchesMultiline(model, new Range(1, 1, searchStart.lineNumber, searchStart.column), searcher, captureMatches, 10 * LIMIT_FIND_COUNT); if (matches.length > 0) { return matches[matches.length - 1]; @@ -411,7 +411,7 @@ export class TextModelSearch { return null; } - private static _doFindPreviousMatchLineByLine(model: TextModel, searchStart: Position, searcher: Searcher, captureMatches: boolean): FindMatch { + private static _doFindPreviousMatchLineByLine(model: TextModel, searchStart: Position, searcher: Searcher, captureMatches: boolean): FindMatch | null { const lineCount = model.getLineCount(); const startLineNumber = searchStart.lineNumber; @@ -434,9 +434,9 @@ export class TextModelSearch { return null; } - private static _findLastMatchInLine(searcher: Searcher, text: string, lineNumber: number, captureMatches: boolean): FindMatch { - let bestResult: FindMatch = null; - let m: RegExpExecArray; + private static _findLastMatchInLine(searcher: Searcher, text: string, lineNumber: number, captureMatches: boolean): FindMatch | null { + let bestResult: FindMatch | null = null; + let m: RegExpExecArray | null; searcher.reset(0); while ((m = searcher.next(text))) { bestResult = createFindMatch(new Range(lineNumber, m.index + 1, lineNumber, m.index + 1 + m[0].length), m, captureMatches); @@ -509,12 +509,12 @@ export function isValidMatch(wordSeparators: WordCharacterClassifier, text: stri } export class Searcher { - private _wordSeparators: WordCharacterClassifier; + private _wordSeparators: WordCharacterClassifier | null; private _searchRegex: RegExp; private _prevMatchStartIndex: number; private _prevMatchLength: number; - constructor(wordSeparators: WordCharacterClassifier, searchRegex: RegExp, ) { + constructor(wordSeparators: WordCharacterClassifier | null, searchRegex: RegExp, ) { this._wordSeparators = wordSeparators; this._searchRegex = searchRegex; this._prevMatchStartIndex = -1; @@ -527,10 +527,10 @@ export class Searcher { this._prevMatchLength = 0; } - public next(text: string): RegExpExecArray { + public next(text: string): RegExpExecArray | null { const textLength = text.length; - let m: RegExpExecArray; + let m: RegExpExecArray | null; do { if (this._prevMatchStartIndex + this._prevMatchLength === textLength) { // Reached the end of the line diff --git a/src/vs/editor/common/model/textModelTokens.ts b/src/vs/editor/common/model/textModelTokens.ts index 45f9c85fd2c..8144fead98c 100644 --- a/src/vs/editor/common/model/textModelTokens.ts +++ b/src/vs/editor/common/model/textModelTokens.ts @@ -27,11 +27,11 @@ function getDefaultMetadata(topLevelLanguageId: LanguageId): number { const EMPTY_LINE_TOKENS = (new Uint32Array(0)).buffer; class ModelLineTokens { - _state: IState; - _lineTokens: ArrayBuffer; + _state: IState | null; + _lineTokens: ArrayBuffer | null; _invalid: boolean; - constructor(state: IState) { + constructor(state: IState | null) { this._state = state; this._lineTokens = null; this._invalid = true; @@ -112,7 +112,7 @@ class ModelLineTokens { this._lineTokens = tmp.buffer; } - public append(_otherTokens: ArrayBuffer): void { + public append(_otherTokens: ArrayBuffer | null): void { if (_otherTokens === EMPTY_LINE_TOKENS) { return; } @@ -168,17 +168,17 @@ class ModelLineTokens { export class ModelLinesTokens { public readonly languageIdentifier: LanguageIdentifier; - public readonly tokenizationSupport: ITokenizationSupport; + public readonly tokenizationSupport: ITokenizationSupport | null; private _tokens: ModelLineTokens[]; private _invalidLineStartIndex: number; - private _lastState: IState; + private _lastState: IState | null; - constructor(languageIdentifier: LanguageIdentifier, tokenizationSupport: ITokenizationSupport) { + constructor(languageIdentifier: LanguageIdentifier, tokenizationSupport: ITokenizationSupport | null) { this.languageIdentifier = languageIdentifier; this.tokenizationSupport = tokenizationSupport; this._tokens = []; if (this.tokenizationSupport) { - let initialState: IState = null; + let initialState: IState | null = null; try { initialState = this.tokenizationSupport.getInitialState(); } catch (e) { @@ -200,7 +200,7 @@ export class ModelLinesTokens { } public getTokens(topLevelLanguageId: LanguageId, lineIndex: number, lineText: string): LineTokens { - let rawLineTokens: ArrayBuffer = null; + let rawLineTokens: ArrayBuffer | null = null; if (lineIndex < this._tokens.length && this._tokens[lineIndex]) { rawLineTokens = this._tokens[lineIndex]._lineTokens; } @@ -245,7 +245,7 @@ export class ModelLinesTokens { return true; } - _getState(lineIndex: number): IState { + _getState(lineIndex: number): IState | null { if (lineIndex < this._tokens.length && this._tokens[lineIndex]) { return this._tokens[lineIndex]._state; } @@ -323,7 +323,7 @@ export class ModelLinesTokens { firstLine.deleteEnding(range.startColumn - 1); const lastLineIndex = range.endLineNumber - 1; - let lastLineTokens: ArrayBuffer = null; + let lastLineTokens: ArrayBuffer | null = null; if (lastLineIndex < this._tokens.length) { const lastLine = this._tokens[lastLineIndex]; lastLine.deleteBeginning(range.endColumn - 1); @@ -380,12 +380,14 @@ export class ModelLinesTokens { } public _tokenizeText(buffer: ITextBuffer, text: string, state: IState): TokenizationResult2 { - let r: TokenizationResult2 = null; + let r: TokenizationResult2 | null = null; - try { - r = this.tokenizationSupport.tokenize2(text, state, 0); - } catch (e) { - onUnexpectedError(e); + if (this.tokenizationSupport) { + try { + r = this.tokenizationSupport.tokenize2(text, state, 0); + } catch (e) { + onUnexpectedError(e); + } } if (!r) { @@ -406,26 +408,29 @@ export class ModelLinesTokens { // Validate all states up to and including endLineIndex for (let lineIndex = this._invalidLineStartIndex; lineIndex <= endLineIndex; lineIndex++) { const endStateIndex = lineIndex + 1; - let r: TokenizationResult2 = null; const text = buffer.getLineContent(lineIndex + 1); + const lineStartState = this._getState(lineIndex); + + let r: TokenizationResult2 | null = null; try { // Tokenize only the first X characters - let freshState = this._getState(lineIndex).clone(); + let freshState = lineStartState!.clone(); r = this.tokenizationSupport.tokenize2(text, freshState, 0); } catch (e) { onUnexpectedError(e); } if (!r) { - r = nullTokenize2(this.languageIdentifier.id, text, this._getState(lineIndex), 0); + r = nullTokenize2(this.languageIdentifier.id, text, lineStartState, 0); } this._setTokens(this.languageIdentifier.id, lineIndex, text.length, r.tokens); eventBuilder.registerChangedTokens(lineIndex + 1); this._setIsInvalid(lineIndex, false); if (endStateIndex < linesLength) { - if (this._getState(endStateIndex) !== null && r.endState.equals(this._getState(endStateIndex))) { + const previousEndState = this._getState(endStateIndex); + if (previousEndState !== null && r.endState.equals(previousEndState)) { // The end state of this line remains the same let nextInvalidLineIndex = lineIndex + 1; while (nextInvalidLineIndex < linesLength) { @@ -483,7 +488,7 @@ export class ModelTokensChangedEventBuilder { } } - public build(): IModelTokensChangedEvent { + public build(): IModelTokensChangedEvent | null { if (this._ranges.length === 0) { return null; } diff --git a/src/vs/editor/common/model/wordHelper.ts b/src/vs/editor/common/model/wordHelper.ts index f238d3d1c73..46d2a719310 100644 --- a/src/vs/editor/common/model/wordHelper.ts +++ b/src/vs/editor/common/model/wordHelper.ts @@ -29,7 +29,7 @@ function createWordRegExp(allowInWords: string = ''): RegExp { // catches numbers (including floating numbers) in the first group, and alphanum in the second export const DEFAULT_WORD_REGEXP = createWordRegExp(); -export function ensureValidWordDefinition(wordDefinition?: RegExp): RegExp { +export function ensureValidWordDefinition(wordDefinition?: RegExp | null): RegExp { let result: RegExp = DEFAULT_WORD_REGEXP; if (wordDefinition && (wordDefinition instanceof RegExp)) { @@ -52,7 +52,7 @@ export function ensureValidWordDefinition(wordDefinition?: RegExp): RegExp { return result; } -function getWordAtPosFast(column: number, wordDefinition: RegExp, text: string, textOffset: number): IWordAtPosition { +function getWordAtPosFast(column: number, wordDefinition: RegExp, text: string, textOffset: number): IWordAtPosition | null { // find whitespace enclosed text around column and match from there let pos = column - 1 - textOffset; @@ -63,12 +63,13 @@ function getWordAtPosFast(column: number, wordDefinition: RegExp, text: string, } wordDefinition.lastIndex = start; - let match: RegExpMatchArray; + let match: RegExpMatchArray | null; while (match = wordDefinition.exec(text)) { - if (match.index <= pos && wordDefinition.lastIndex >= pos) { + const matchIndex = match.index || 0; + if (matchIndex <= pos && wordDefinition.lastIndex >= pos) { return { word: match[0], - startColumn: textOffset + 1 + match.index, + startColumn: textOffset + 1 + matchIndex, endColumn: textOffset + 1 + wordDefinition.lastIndex }; } @@ -78,7 +79,7 @@ function getWordAtPosFast(column: number, wordDefinition: RegExp, text: string, } -function getWordAtPosSlow(column: number, wordDefinition: RegExp, text: string, textOffset: number): IWordAtPosition { +function getWordAtPosSlow(column: number, wordDefinition: RegExp, text: string, textOffset: number): IWordAtPosition | null { // matches all words starting at the beginning // of the input until it finds a match that encloses // the desired column. slow but correct @@ -86,10 +87,10 @@ function getWordAtPosSlow(column: number, wordDefinition: RegExp, text: string, let pos = column - 1 - textOffset; wordDefinition.lastIndex = 0; - let match: RegExpMatchArray; + let match: RegExpMatchArray | null; while (match = wordDefinition.exec(text)) { - - if (match.index > pos) { + const matchIndex = match.index || 0; + if (matchIndex > pos) { // |nW -> matched only after the pos return null; @@ -97,7 +98,7 @@ function getWordAtPosSlow(column: number, wordDefinition: RegExp, text: string, // W|W -> match encloses pos return { word: match[0], - startColumn: textOffset + 1 + match.index, + startColumn: textOffset + 1 + matchIndex, endColumn: textOffset + 1 + wordDefinition.lastIndex }; } @@ -106,7 +107,7 @@ function getWordAtPosSlow(column: number, wordDefinition: RegExp, text: string, return null; } -export function getWordAtText(column: number, wordDefinition: RegExp, text: string, textOffset: number): IWordAtPosition { +export function getWordAtText(column: number, wordDefinition: RegExp, text: string, textOffset: number): IWordAtPosition | null { // if `words` can contain whitespace character we have to use the slow variant // otherwise we use the fast variant of finding a word diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index 4a26b10086a..7c62ab125e5 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -200,7 +200,7 @@ export interface ITokenizationSupport { getInitialState(): IState; // add offsetDelta to each of the returned indices - tokenize(line: string, state: IState, offsetDelta: number): TokenizationResult; + tokenize?(line: string, state: IState, offsetDelta: number): TokenizationResult; tokenize2(line: string, state: IState, offsetDelta: number): TokenizationResult2; } @@ -1366,16 +1366,16 @@ export interface ITokenizationRegistry { * Get the promise of a tokenization support for a language. * `null` is returned if no support is available and no promise for the support has been registered yet. */ - getPromise(language: string): Thenable; + getPromise(language: string): Thenable | null; /** * Set the new color map that all tokens will use in their ColorId binary encoded bits for foreground and background. */ setColorMap(colorMap: Color[]): void; - getColorMap(): Color[]; + getColorMap(): Color[] | null; - getDefaultBackground(): Color; + getDefaultBackground(): Color | null; } /** diff --git a/src/vs/editor/common/modes/languageConfigurationRegistry.ts b/src/vs/editor/common/modes/languageConfigurationRegistry.ts index 08693dddfe1..eafbd9290e6 100644 --- a/src/vs/editor/common/modes/languageConfigurationRegistry.ts +++ b/src/vs/editor/common/modes/languageConfigurationRegistry.ts @@ -37,8 +37,8 @@ export interface IVirtualModel { } export interface IIndentConverter { - shiftIndent?(indentation: string): string; - unshiftIndent?(indentation: string): string; + shiftIndent(indentation: string): string; + unshiftIndent(indentation: string): string; normalizeIndentation?(indentation: string): string; } @@ -46,15 +46,15 @@ export class RichEditSupport { private readonly _conf: LanguageConfiguration; private readonly _languageIdentifier: LanguageIdentifier; - private _brackets: RichEditBrackets; - private _electricCharacter: BracketElectricCharacterSupport; + private _brackets: RichEditBrackets | null; + private _electricCharacter: BracketElectricCharacterSupport | null; - public readonly comments: ICommentsConfiguration; + public readonly comments: ICommentsConfiguration | null; public readonly characterPair: CharacterPairSupport; public readonly wordDefinition: RegExp; - public readonly onEnter: OnEnterSupport; + public readonly onEnter: OnEnterSupport | null; public readonly indentRulesSupport: IndentRulesSupport; - public readonly indentationRules: IndentationRule; + public readonly indentationRules: IndentationRule | undefined; public readonly foldingRules: FoldingRules; constructor(languageIdentifier: LanguageIdentifier, previous: RichEditSupport, rawConf: LanguageConfiguration) { @@ -63,7 +63,7 @@ export class RichEditSupport { this._brackets = null; this._electricCharacter = null; - let prev: LanguageConfiguration = null; + let prev: LanguageConfiguration | null = null; if (previous) { prev = previous._conf; } @@ -86,14 +86,14 @@ export class RichEditSupport { this.foldingRules = this._conf.folding || {}; } - public get brackets(): RichEditBrackets { + public get brackets(): RichEditBrackets | null { if (!this._brackets && this._conf.brackets) { this._brackets = new RichEditBrackets(this._languageIdentifier, this._conf.brackets); } return this._brackets; } - public get electricCharacter(): BracketElectricCharacterSupport { + public get electricCharacter(): BracketElectricCharacterSupport | null { if (!this._electricCharacter) { let autoClosingPairs: IAutoClosingPairConditional[] = []; if (this._conf.autoClosingPairs) { @@ -109,7 +109,7 @@ export class RichEditSupport { return this._electricCharacter; } - private static _mergeConf(prev: LanguageConfiguration, current: LanguageConfiguration): LanguageConfiguration { + private static _mergeConf(prev: LanguageConfiguration | null, current: LanguageConfiguration): LanguageConfiguration { return { comments: (prev ? current.comments || prev.comments : current.comments), brackets: (prev ? current.brackets || prev.brackets : current.brackets), @@ -124,7 +124,7 @@ export class RichEditSupport { }; } - private static _handleOnEnter(conf: LanguageConfiguration): OnEnterSupport { + private static _handleOnEnter(conf: LanguageConfiguration): OnEnterSupport | null { // on enter let onEnter: IOnEnterSupportOptions = {}; let empty = true; @@ -147,7 +147,7 @@ export class RichEditSupport { return null; } - private static _handleComments(conf: LanguageConfiguration): ICommentsConfiguration { + private static _handleComments(conf: LanguageConfiguration): ICommentsConfiguration | null { let commentRule = conf.comments; if (!commentRule) { return null; @@ -213,7 +213,7 @@ export class LanguageConfigurationRegistryImpl { // begin electricCharacter - private _getElectricCharacterSupport(languageId: LanguageId): BracketElectricCharacterSupport { + private _getElectricCharacterSupport(languageId: LanguageId): BracketElectricCharacterSupport | null { let value = this._getRichEditSupport(languageId); if (!value) { return null; @@ -232,7 +232,7 @@ export class LanguageConfigurationRegistryImpl { /** * Should return opening bracket type to match indentation with */ - public onElectricCharacter(character: string, context: LineTokens, column: number): IElectricAction { + public onElectricCharacter(character: string, context: LineTokens, column: number): IElectricAction | null { let scopedLineTokens = createScopedLineTokens(context, column - 1); let electricCharacterSupport = this._getElectricCharacterSupport(scopedLineTokens.languageId); if (!electricCharacterSupport) { @@ -243,7 +243,7 @@ export class LanguageConfigurationRegistryImpl { // end electricCharacter - public getComments(languageId: LanguageId): ICommentsConfiguration { + public getComments(languageId: LanguageId): ICommentsConfiguration | null { let value = this._getRichEditSupport(languageId); if (!value) { return null; @@ -253,7 +253,7 @@ export class LanguageConfigurationRegistryImpl { // begin characterPair - private _getCharacterPairSupport(languageId: LanguageId): CharacterPairSupport { + private _getCharacterPairSupport(languageId: LanguageId): CharacterPairSupport | null { let value = this._getRichEditSupport(languageId); if (!value) { return null; @@ -314,7 +314,7 @@ export class LanguageConfigurationRegistryImpl { // begin Indent Rules - public getIndentRulesSupport(languageId: LanguageId): IndentRulesSupport { + public getIndentRulesSupport(languageId: LanguageId): IndentRulesSupport | null { let value = this._getRichEditSupport(languageId); if (!value) { return null; @@ -364,7 +364,7 @@ export class LanguageConfigurationRegistryImpl { * * This function only return the inherited indent based on above lines, it doesn't check whether current line should decrease or not. */ - public getInheritIndentForLine(model: IVirtualModel, lineNumber: number, honorIntentialIndent: boolean = true): { indentation: string, action: IndentAction, line?: number } { + public getInheritIndentForLine(model: IVirtualModel, lineNumber: number, honorIntentialIndent: boolean = true): { indentation: string; action: IndentAction | null; line?: number; } | null { let indentRulesSupport = this.getIndentRulesSupport(model.getLanguageIdentifier().id); if (!indentRulesSupport) { return null; @@ -485,7 +485,7 @@ export class LanguageConfigurationRegistryImpl { } } - public getGoodIndentForLine(virtualModel: IVirtualModel, languageId: LanguageId, lineNumber: number, indentConverter: IIndentConverter): string { + public getGoodIndentForLine(virtualModel: IVirtualModel, languageId: LanguageId, lineNumber: number, indentConverter: IIndentConverter): string | null { let indentRulesSupport = this.getIndentRulesSupport(languageId); if (!indentRulesSupport) { return null; @@ -498,9 +498,11 @@ export class LanguageConfigurationRegistryImpl { let inheritLine = indent.line; if (inheritLine !== undefined) { let onEnterSupport = this._getOnEnterSupport(languageId); - let enterResult: EnterAction = null; + let enterResult: EnterAction | null = null; try { - enterResult = onEnterSupport.onEnter('', virtualModel.getLineContent(inheritLine), ''); + if (onEnterSupport) { + enterResult = onEnterSupport.onEnter('', virtualModel.getLineContent(inheritLine), ''); + } } catch (e) { onUnexpectedError(e); } @@ -550,7 +552,7 @@ export class LanguageConfigurationRegistryImpl { return null; } - public getIndentForEnter(model: ITextModel, range: Range, indentConverter: IIndentConverter, autoIndent: boolean): { beforeEnter: string, afterEnter: string } { + public getIndentForEnter(model: ITextModel, range: Range, indentConverter: IIndentConverter, autoIndent: boolean): { beforeEnter: string, afterEnter: string } | null { model.forceTokenization(range.startLineNumber); let lineTokens = model.getLineTokens(range.startLineNumber); @@ -648,7 +650,7 @@ export class LanguageConfigurationRegistryImpl { * We should always allow intentional indentation. It means, if users change the indentation of `lineNumber` and the content of * this line doesn't match decreaseIndentPattern, we should not adjust the indentation. */ - public getIndentActionForType(model: ITextModel, range: Range, ch: string, indentConverter: IIndentConverter): string { + public getIndentActionForType(model: ITextModel, range: Range, ch: string, indentConverter: IIndentConverter): string | null { let scopedLineTokens = this.getScopedLineTokens(model, range.startLineNumber, range.startColumn); let indentRulesSupport = this.getIndentRulesSupport(scopedLineTokens.languageId); if (!indentRulesSupport) { @@ -689,7 +691,7 @@ export class LanguageConfigurationRegistryImpl { return null; } - public getIndentMetadata(model: ITextModel, lineNumber: number): number { + public getIndentMetadata(model: ITextModel, lineNumber: number): number | null { let indentRulesSupport = this.getIndentRulesSupport(model.getLanguageIdentifier().id); if (!indentRulesSupport) { return null; @@ -706,7 +708,7 @@ export class LanguageConfigurationRegistryImpl { // begin onEnter - private _getOnEnterSupport(languageId: LanguageId): OnEnterSupport { + private _getOnEnterSupport(languageId: LanguageId): OnEnterSupport | null { let value = this._getRichEditSupport(languageId); if (!value) { return null; @@ -714,13 +716,13 @@ export class LanguageConfigurationRegistryImpl { return value.onEnter || null; } - public getRawEnterActionAtPosition(model: ITextModel, lineNumber: number, column: number): EnterAction { + public getRawEnterActionAtPosition(model: ITextModel, lineNumber: number, column: number): EnterAction | null { let r = this.getEnterAction(model, new Range(lineNumber, column, lineNumber, column)); return r ? r.enterAction : null; } - public getEnterAction(model: ITextModel, range: Range): { enterAction: EnterAction; indentation: string; } { + public getEnterAction(model: ITextModel, range: Range): { enterAction: EnterAction; indentation: string; } | null { let indentation = this.getIndentationAtPosition(model, range.startLineNumber, range.startColumn); let scopedLineTokens = this.getScopedLineTokens(model, range.startLineNumber, range.startColumn); @@ -753,7 +755,7 @@ export class LanguageConfigurationRegistryImpl { } } - let enterResult: EnterAction = null; + let enterResult: EnterAction | null = null; try { enterResult = onEnterSupport.onEnter(oneLineAboveText, beforeEnterText, afterEnterText); } catch (e) { @@ -799,14 +801,14 @@ export class LanguageConfigurationRegistryImpl { private getScopedLineTokens(model: ITextModel, lineNumber: number, columnNumber?: number) { model.forceTokenization(lineNumber); let lineTokens = model.getLineTokens(lineNumber); - let column = isNaN(columnNumber) ? model.getLineMaxColumn(lineNumber) - 1 : columnNumber - 1; + let column = (typeof columnNumber === 'undefined' ? model.getLineMaxColumn(lineNumber) - 1 : columnNumber - 1); let scopedLineTokens = createScopedLineTokens(lineTokens, column); return scopedLineTokens; } // end onEnter - public getBracketsSupport(languageId: LanguageId): RichEditBrackets { + public getBracketsSupport(languageId: LanguageId): RichEditBrackets | null { let value = this._getRichEditSupport(languageId); if (!value) { return null; diff --git a/src/vs/editor/common/modes/languageFeatureRegistry.ts b/src/vs/editor/common/modes/languageFeatureRegistry.ts index af2d6e40754..eef1757486e 100644 --- a/src/vs/editor/common/modes/languageFeatureRegistry.ts +++ b/src/vs/editor/common/modes/languageFeatureRegistry.ts @@ -22,7 +22,7 @@ function isExclusive(selector: LanguageSelector): boolean { } else if (Array.isArray(selector)) { return selector.every(isExclusive); } else { - return selector.exclusive; + return !!selector.exclusive; } } @@ -41,7 +41,7 @@ export default class LanguageFeatureRegistry { register(selector: LanguageSelector, provider: T): IDisposable { - let entry: Entry = { + let entry: Entry | undefined = { selector, provider, _score: -1, @@ -127,7 +127,7 @@ export default class LanguageFeatureRegistry { } } - private _lastCandidate: { uri: string; language: string; }; + private _lastCandidate: { uri: string; language: string; } | undefined; private _updateScores(model: ITextModel): void { diff --git a/src/vs/editor/common/modes/linkComputer.ts b/src/vs/editor/common/modes/linkComputer.ts index 1813894e58d..dbf78a728d0 100644 --- a/src/vs/editor/common/modes/linkComputer.ts +++ b/src/vs/editor/common/modes/linkComputer.ts @@ -75,7 +75,7 @@ class StateMachine { } // State machine for http:// or https:// or file:// -let _stateMachine: StateMachine = null; +let _stateMachine: StateMachine | null = null; function getStateMachine(): StateMachine { if (_stateMachine === null) { _stateMachine = new StateMachine([ @@ -123,7 +123,7 @@ const enum CharacterClass { CannotEndIn = 2 } -let _classifier: CharacterClassifier = null; +let _classifier: CharacterClassifier | null = null; function getClassifier(): CharacterClassifier { if (_classifier === null) { _classifier = new CharacterClassifier(CharacterClass.None); diff --git a/src/vs/editor/common/modes/nullMode.ts b/src/vs/editor/common/modes/nullMode.ts index 1558e3b2a35..b0d8fe393b2 100644 --- a/src/vs/editor/common/modes/nullMode.ts +++ b/src/vs/editor/common/modes/nullMode.ts @@ -27,7 +27,7 @@ export function nullTokenize(modeId: string, buffer: string, state: IState, delt return new TokenizationResult([new Token(deltaOffset, '', modeId)], state); } -export function nullTokenize2(languageId: LanguageId, buffer: string, state: IState, deltaOffset: number): TokenizationResult2 { +export function nullTokenize2(languageId: LanguageId, buffer: string, state: IState | null, deltaOffset: number): TokenizationResult2 { let tokens = new Uint32Array(2); tokens[0] = deltaOffset; tokens[1] = ( @@ -38,5 +38,5 @@ export function nullTokenize2(languageId: LanguageId, buffer: string, state: ISt | (ColorId.DefaultBackground << MetadataConsts.BACKGROUND_OFFSET) ) >>> 0; - return new TokenizationResult2(tokens, state); + return new TokenizationResult2(tokens, state === null ? NULL_STATE : state); } diff --git a/src/vs/editor/common/modes/supports/electricCharacter.ts b/src/vs/editor/common/modes/supports/electricCharacter.ts index def16eb8aa8..33273ab64be 100644 --- a/src/vs/editor/common/modes/supports/electricCharacter.ts +++ b/src/vs/editor/common/modes/supports/electricCharacter.ts @@ -24,10 +24,10 @@ export interface IElectricAction { export class BracketElectricCharacterSupport { - private readonly _richEditBrackets: RichEditBrackets; + private readonly _richEditBrackets: RichEditBrackets | null; private readonly _complexAutoClosePairs: StandardAutoClosingPairConditional[]; - constructor(richEditBrackets: RichEditBrackets, autoClosePairs: IAutoClosingPairConditional[], contribution: IBracketElectricCharacterContribution) { + constructor(richEditBrackets: RichEditBrackets | null, autoClosePairs: IAutoClosingPairConditional[], contribution: IBracketElectricCharacterContribution | undefined) { contribution = contribution || {}; this._richEditBrackets = richEditBrackets; this._complexAutoClosePairs = autoClosePairs.filter(pair => pair.open.length > 1 && !!pair.close).map(el => new StandardAutoClosingPairConditional(el)); @@ -61,12 +61,12 @@ export class BracketElectricCharacterSupport { return result; } - public onElectricCharacter(character: string, context: ScopedLineTokens, column: number): IElectricAction { + public onElectricCharacter(character: string, context: ScopedLineTokens, column: number): IElectricAction | null { return (this._onElectricAutoClose(character, context, column) || this._onElectricAutoIndent(character, context, column)); } - private _onElectricAutoIndent(character: string, context: ScopedLineTokens, column: number): IElectricAction { + private _onElectricAutoIndent(character: string, context: ScopedLineTokens, column: number): IElectricAction | null { if (!this._richEditBrackets || this._richEditBrackets.brackets.length === 0) { return null; @@ -104,7 +104,7 @@ export class BracketElectricCharacterSupport { }; } - private _onElectricAutoClose(character: string, context: ScopedLineTokens, column: number): IElectricAction { + private _onElectricAutoClose(character: string, context: ScopedLineTokens, column: number): IElectricAction | null { if (!this._complexAutoClosePairs.length) { return null; } diff --git a/src/vs/editor/common/modes/supports/inplaceReplaceSupport.ts b/src/vs/editor/common/modes/supports/inplaceReplaceSupport.ts index ccefd954f4c..e4e069b9376 100644 --- a/src/vs/editor/common/modes/supports/inplaceReplaceSupport.ts +++ b/src/vs/editor/common/modes/supports/inplaceReplaceSupport.ts @@ -10,7 +10,7 @@ export class BasicInplaceReplace { public static readonly INSTANCE = new BasicInplaceReplace(); - public navigateValueSet(range1: IRange, text1: string, range2: IRange, text2: string, up: boolean): IInplaceReplaceSupportResult { + public navigateValueSet(range1: IRange, text1: string, range2: IRange, text2: string, up: boolean): IInplaceReplaceSupportResult | null { if (range1 && text1) { let result = this.doNavigateValueSet(text1, up); @@ -35,7 +35,7 @@ export class BasicInplaceReplace { return null; } - private doNavigateValueSet(text: string, up: boolean): string { + private doNavigateValueSet(text: string, up: boolean): string | null { let numberResult = this.numberReplace(text, up); if (numberResult !== null) { return numberResult; @@ -43,7 +43,7 @@ export class BasicInplaceReplace { return this.textReplace(text, up); } - private numberReplace(value: string, up: boolean): string { + private numberReplace(value: string, up: boolean): string | null { let precision = Math.pow(10, value.length - (value.lastIndexOf('.') + 1)); let n1 = Number(value); let n2 = parseFloat(value); @@ -71,19 +71,19 @@ export class BasicInplaceReplace { ['public', 'protected', 'private'], ]; - private textReplace(value: string, up: boolean): string { + private textReplace(value: string, up: boolean): string | null { return this.valueSetsReplace(this._defaultValueSet, value, up); } - private valueSetsReplace(valueSets: string[][], value: string, up: boolean): string { - let result: string = null; + private valueSetsReplace(valueSets: string[][], value: string, up: boolean): string | null { + let result: string | null = null; for (let i = 0, len = valueSets.length; result === null && i < len; i++) { result = this.valueSetReplace(valueSets[i], value, up); } return result; } - private valueSetReplace(valueSet: string[], value: string, up: boolean): string { + private valueSetReplace(valueSet: string[], value: string, up: boolean): string | null { let idx = valueSet.indexOf(value); if (idx >= 0) { idx += up ? +1 : -1; diff --git a/src/vs/editor/common/modes/supports/onEnter.ts b/src/vs/editor/common/modes/supports/onEnter.ts index 4615dc4903f..6822b79541d 100644 --- a/src/vs/editor/common/modes/supports/onEnter.ts +++ b/src/vs/editor/common/modes/supports/onEnter.ts @@ -32,18 +32,23 @@ export class OnEnterSupport { ['[', ']'] ]; - this._brackets = opts.brackets.map((bracket) => { - return { - open: bracket[0], - openRegExp: OnEnterSupport._createOpenBracketRegExp(bracket[0]), - close: bracket[1], - closeRegExp: OnEnterSupport._createCloseBracketRegExp(bracket[1]), - }; + this._brackets = []; + opts.brackets.forEach((bracket) => { + const openRegExp = OnEnterSupport._createOpenBracketRegExp(bracket[0]); + const closeRegExp = OnEnterSupport._createCloseBracketRegExp(bracket[1]); + if (openRegExp && closeRegExp) { + this._brackets.push({ + open: bracket[0], + openRegExp: openRegExp, + close: bracket[1], + closeRegExp: closeRegExp, + }); + } }); this._regExpRules = opts.regExpRules || []; } - public onEnter(oneLineAboveText: string, beforeEnterText: string, afterEnterText: string): EnterAction { + public onEnter(oneLineAboveText: string, beforeEnterText: string, afterEnterText: string): EnterAction | null { // (1): `regExpRules` for (let i = 0, len = this._regExpRules.length; i < len; i++) { let rule = this._regExpRules[i]; @@ -90,7 +95,7 @@ export class OnEnterSupport { return null; } - private static _createOpenBracketRegExp(bracket: string): RegExp { + private static _createOpenBracketRegExp(bracket: string): RegExp | null { let str = strings.escapeRegExpCharacters(bracket); if (!/\B/.test(str.charAt(0))) { str = '\\b' + str; @@ -99,7 +104,7 @@ export class OnEnterSupport { return OnEnterSupport._safeRegExp(str); } - private static _createCloseBracketRegExp(bracket: string): RegExp { + private static _createCloseBracketRegExp(bracket: string): RegExp | null { let str = strings.escapeRegExpCharacters(bracket); if (!/\B/.test(str.charAt(str.length - 1))) { str = str + '\\b'; @@ -108,7 +113,7 @@ export class OnEnterSupport { return OnEnterSupport._safeRegExp(str); } - private static _safeRegExp(def: string): RegExp { + private static _safeRegExp(def: string): RegExp | null { try { return new RegExp(def); } catch (err) { diff --git a/src/vs/editor/common/modes/supports/richEditBrackets.ts b/src/vs/editor/common/modes/supports/richEditBrackets.ts index d11badc422c..5a389e8a1b0 100644 --- a/src/vs/editor/common/modes/supports/richEditBrackets.ts +++ b/src/vs/editor/common/modes/supports/richEditBrackets.ts @@ -141,34 +141,34 @@ let toReversedString = (function () { return reversedStr; } - let lastInput: string = null; - let lastOutput: string = null; + let lastInput: string | null = null; + let lastOutput: string | null = null; return function toReversedString(str: string): string { if (lastInput !== str) { lastInput = str; lastOutput = reverse(lastInput); } - return lastOutput; + return lastOutput!; }; })(); export class BracketsUtils { - private static _findPrevBracketInText(reversedBracketRegex: RegExp, lineNumber: number, reversedText: string, offset: number): Range { + private static _findPrevBracketInText(reversedBracketRegex: RegExp, lineNumber: number, reversedText: string, offset: number): Range | null { let m = reversedText.match(reversedBracketRegex); if (!m) { return null; } - let matchOffset = reversedText.length - m.index; + let matchOffset = reversedText.length - (m.index || 0); let matchLength = m[0].length; let absoluteMatchOffset = offset + matchOffset; return new Range(lineNumber, absoluteMatchOffset - matchLength + 1, lineNumber, absoluteMatchOffset + 1); } - public static findPrevBracketInToken(reversedBracketRegex: RegExp, lineNumber: number, lineText: string, currentTokenStart: number, currentTokenEnd: number): Range { + public static findPrevBracketInToken(reversedBracketRegex: RegExp, lineNumber: number, lineText: string, currentTokenStart: number, currentTokenEnd: number): Range | null { // Because JS does not support backwards regex search, we search forwards in a reversed string with a reversed regex ;) let reversedLineText = toReversedString(lineText); let reversedTokenText = reversedLineText.substring(lineText.length - currentTokenEnd, lineText.length - currentTokenStart); @@ -176,14 +176,14 @@ export class BracketsUtils { return this._findPrevBracketInText(reversedBracketRegex, lineNumber, reversedTokenText, currentTokenStart); } - public static findNextBracketInText(bracketRegex: RegExp, lineNumber: number, text: string, offset: number): Range { + public static findNextBracketInText(bracketRegex: RegExp, lineNumber: number, text: string, offset: number): Range | null { let m = text.match(bracketRegex); if (!m) { return null; } - let matchOffset = m.index; + let matchOffset = m.index || 0; let matchLength = m[0].length; if (matchLength === 0) { return null; @@ -193,7 +193,7 @@ export class BracketsUtils { return new Range(lineNumber, absoluteMatchOffset + 1, lineNumber, absoluteMatchOffset + 1 + matchLength); } - public static findNextBracketInToken(bracketRegex: RegExp, lineNumber: number, lineText: string, currentTokenStart: number, currentTokenEnd: number): Range { + public static findNextBracketInToken(bracketRegex: RegExp, lineNumber: number, lineText: string, currentTokenStart: number, currentTokenEnd: number): Range | null { let currentTokenText = lineText.substring(currentTokenStart, currentTokenEnd); return this.findNextBracketInText(bracketRegex, lineNumber, currentTokenText, currentTokenStart); diff --git a/src/vs/editor/common/modes/supports/tokenization.ts b/src/vs/editor/common/modes/supports/tokenization.ts index b6bdbe778e0..bcc7c93cbb7 100644 --- a/src/vs/editor/common/modes/supports/tokenization.ts +++ b/src/vs/editor/common/modes/supports/tokenization.ts @@ -23,15 +23,15 @@ export class ParsedTokenThemeRule { * -1 if not set. An or mask of `FontStyle` otherwise. */ readonly fontStyle: FontStyle; - readonly foreground: string; - readonly background: string; + readonly foreground: string | null; + readonly background: string | null; constructor( token: string, index: number, fontStyle: number, - foreground: string, - background: string, + foreground: string | null, + background: string | null, ) { this.token = token; this.index = index; @@ -73,12 +73,12 @@ export function parseTokenTheme(source: ITokenThemeRule[]): ParsedTokenThemeRule } } - let foreground: string = null; + let foreground: string | null = null; if (typeof entry.foreground === 'string') { foreground = entry.foreground; } - let background: string = null; + let background: string | null = null; if (typeof entry.background === 'string') { background = entry.background; } @@ -114,7 +114,7 @@ function resolveParsedTokenThemeRules(parsedThemeRules: ParsedTokenThemeRule[], let defaultForeground = '000000'; let defaultBackground = 'ffffff'; while (parsedThemeRules.length >= 1 && parsedThemeRules[0].token === '') { - let incomingDefaults = parsedThemeRules.shift(); + let incomingDefaults = parsedThemeRules.shift()!; if (incomingDefaults.fontStyle !== FontStyle.NotSet) { defaultFontStyle = incomingDefaults.fontStyle; } @@ -160,7 +160,7 @@ export class ColorMap { this._color2id = new Map(); } - public getId(color: string): ColorId { + public getId(color: string | null): ColorId { if (color === null) { return 0; } diff --git a/src/vs/editor/common/modes/textToHtmlTokenizer.ts b/src/vs/editor/common/modes/textToHtmlTokenizer.ts index 80f82b78c32..d932f8d0e44 100644 --- a/src/vs/editor/common/modes/textToHtmlTokenizer.ts +++ b/src/vs/editor/common/modes/textToHtmlTokenizer.ts @@ -9,7 +9,7 @@ import { LineTokens, IViewLineTokens } from 'vs/editor/common/core/lineTokens'; import { CharCode } from 'vs/base/common/charCode'; import { NULL_STATE, nullTokenize2 } from 'vs/editor/common/modes/nullMode'; -const fallback = { +const fallback: ITokenizationSupport = { getInitialState: () => NULL_STATE, tokenize: undefined, tokenize2: (buffer: string, state: IState, deltaOffset: number) => nullTokenize2(LanguageId.Null, buffer, state, deltaOffset) diff --git a/src/vs/editor/common/modes/tokenizationRegistry.ts b/src/vs/editor/common/modes/tokenizationRegistry.ts index 8ff5f366770..502d76a349c 100644 --- a/src/vs/editor/common/modes/tokenizationRegistry.ts +++ b/src/vs/editor/common/modes/tokenizationRegistry.ts @@ -7,7 +7,6 @@ import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { Event, Emitter } from 'vs/base/common/event'; import { ColorId, ITokenizationRegistry, ITokenizationSupport, ITokenizationSupportChangedEvent } from 'vs/editor/common/modes'; import { Color } from 'vs/base/common/color'; -import { TPromise } from 'vs/base/common/winjs.base'; export class TokenizationRegistryImpl implements ITokenizationRegistry { @@ -17,7 +16,7 @@ export class TokenizationRegistryImpl implements ITokenizationRegistry { private readonly _onDidChange: Emitter = new Emitter(); public readonly onDidChange: Event = this._onDidChange.event; - private _colorMap: Color[]; + private _colorMap: Color[] | null; constructor() { this._map = Object.create(null); @@ -52,10 +51,10 @@ export class TokenizationRegistryImpl implements ITokenizationRegistry { return promise; } - public getPromise(language: string): Thenable { + public getPromise(language: string): Thenable | null { const support = this.get(language); if (support) { - return TPromise.as(support); + return Promise.resolve(support); } const promise = this._promises[language]; if (promise) { @@ -76,11 +75,14 @@ export class TokenizationRegistryImpl implements ITokenizationRegistry { }); } - public getColorMap(): Color[] { + public getColorMap(): Color[] | null { return this._colorMap; } - public getDefaultBackground(): Color { - return this._colorMap[ColorId.DefaultBackground]; + public getDefaultBackground(): Color | null { + if (this._colorMap && this._colorMap.length > ColorId.DefaultBackground) { + return this._colorMap[ColorId.DefaultBackground]; + } + return null; } } diff --git a/src/vs/editor/common/services/editorSimpleWorker.ts b/src/vs/editor/common/services/editorSimpleWorker.ts index c38a201b8b8..b5e0c80454f 100644 --- a/src/vs/editor/common/services/editorSimpleWorker.ts +++ b/src/vs/editor/common/services/editorSimpleWorker.ts @@ -19,7 +19,7 @@ import { getWordAtText, ensureValidWordDefinition } from 'vs/editor/common/model import { createMonacoBaseAPI } from 'vs/editor/common/standalone/standaloneBase'; import { IWordAtPosition, EndOfLineSequence } from 'vs/editor/common/model'; import { globals } from 'vs/base/common/platform'; -import { Iterator } from 'vs/base/common/iterator'; +import { Iterator, IteratorResult, FIN } from 'vs/base/common/iterator'; import { mergeSort } from 'vs/base/common/arrays'; export interface IMirrorModel { @@ -147,24 +147,25 @@ class MirrorModel extends BaseMirrorModel implements ICommonModel { } public createWordIterator(wordDefinition: RegExp): Iterator { - let obj = { - done: false, - value: '' - }; + let obj: { done: false; value: string; }; let lineNumber = 0; let lineText: string; let wordRangesIdx = 0; let wordRanges: IWordRange[] = []; - let next = (): { done: boolean; value: string } => { + let next = (): IteratorResult => { if (wordRangesIdx < wordRanges.length) { - obj.done = false; - obj.value = lineText.substring(wordRanges[wordRangesIdx].start, wordRanges[wordRangesIdx].end); + const value = lineText.substring(wordRanges[wordRangesIdx].start, wordRanges[wordRangesIdx].end); wordRangesIdx += 1; + if (!obj) { + obj = { done: false, value: value }; + } else { + obj.value = value; + } + return obj; } else if (lineNumber >= this._lines.length) { - obj.done = true; - obj.value = undefined; + return FIN; } else { lineText = this._lines[lineNumber]; @@ -173,8 +174,6 @@ class MirrorModel extends BaseMirrorModel implements ICommonModel { lineNumber += 1; return next(); } - - return obj; }; return { next }; } @@ -548,7 +547,7 @@ export abstract class BaseEditorSimpleWorker { let selectionText = model.getValueInRange(range); let wordRange = model.getWordAtPosition({ lineNumber: range.startLineNumber, column: range.startColumn }, wordDefRegExp); - let word: string = null; + let word: string | null = null; if (wordRange !== null) { word = model.getValueInRange(wordRange); } diff --git a/src/vs/editor/common/services/languagesRegistry.ts b/src/vs/editor/common/services/languagesRegistry.ts index dd42f985385..b782fea97a9 100644 --- a/src/vs/editor/common/services/languagesRegistry.ts +++ b/src/vs/editor/common/services/languagesRegistry.ts @@ -85,7 +85,7 @@ export class LanguagesRegistry { private _registerLanguage(lang: ILanguageExtensionPoint): void { const langId = lang.id; - let resolvedLanguage: IResolvedLanguage = null; + let resolvedLanguage: IResolvedLanguage | null = null; if (hasOwnProperty.call(this._languages, langId)) { resolvedLanguage = this._languages[langId]; } else { @@ -109,7 +109,7 @@ export class LanguagesRegistry { private _mergeLanguage(resolvedLanguage: IResolvedLanguage, lang: ILanguageExtensionPoint): void { const langId = lang.id; - let primaryMime: string = null; + let primaryMime: string | null = null; if (Array.isArray(lang.mimetypes) && lang.mimetypes.length > 0) { resolvedLanguage.mimetypes.push(...lang.mimetypes); @@ -159,7 +159,7 @@ export class LanguagesRegistry { resolvedLanguage.aliases.push(langId); - let langAliases: string[] = null; + let langAliases: string[] | null = null; if (typeof lang.aliases !== 'undefined' && Array.isArray(lang.aliases)) { if (lang.aliases.length === 0) { // signal that this language should not get a name diff --git a/src/vs/editor/common/services/modeService.ts b/src/vs/editor/common/services/modeService.ts index 5b6540f643b..b7d0b440561 100644 --- a/src/vs/editor/common/services/modeService.ts +++ b/src/vs/editor/common/services/modeService.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { Event } from 'vs/base/common/event'; -import { TPromise } from 'vs/base/common/winjs.base'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IMode, LanguageId, LanguageIdentifier } from 'vs/editor/common/modes'; import { URI } from 'vs/base/common/uri'; @@ -43,7 +42,7 @@ export interface IModeService { // --- instantiation getMode(commaSeparatedMimetypesOrCommaSeparatedIds: string): IMode; - getOrCreateMode(commaSeparatedMimetypesOrCommaSeparatedIds: string): TPromise; - getOrCreateModeByLanguageName(languageName: string): TPromise; - getOrCreateModeByFilepathOrFirstLine(filepath: string, firstLine?: string): TPromise; + getOrCreateMode(commaSeparatedMimetypesOrCommaSeparatedIds: string): Promise; + getOrCreateModeByLanguageName(languageName: string): Promise; + getOrCreateModeByFilepathOrFirstLine(filepath: string, firstLine?: string): Promise; } diff --git a/src/vs/editor/common/services/modeServiceImpl.ts b/src/vs/editor/common/services/modeServiceImpl.ts index 9f2f52ce0c5..61b1a81b9f0 100644 --- a/src/vs/editor/common/services/modeServiceImpl.ts +++ b/src/vs/editor/common/services/modeServiceImpl.ts @@ -5,7 +5,6 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { Event, Emitter } from 'vs/base/common/event'; -import { TPromise } from 'vs/base/common/winjs.base'; import { IMode, LanguageId, LanguageIdentifier } from 'vs/editor/common/modes'; import { FrankensteinMode } from 'vs/editor/common/modes/abstractMode'; import { LanguagesRegistry } from 'vs/editor/common/services/languagesRegistry'; @@ -27,8 +26,8 @@ export class ModeServiceImpl implements IModeService { this._registry = new LanguagesRegistry(true, warnOnOverwrite); } - protected _onReady(): TPromise { - return TPromise.as(true); + protected _onReady(): Promise { + return Promise.resolve(true); } public isRegisteredMode(mimetypeOrModeId: string): boolean { @@ -106,7 +105,7 @@ export class ModeServiceImpl implements IModeService { if (isPlainText) { // Try to do it synchronously - let r: IMode = null; + let r: IMode | null = null; this.getOrCreateMode(commaSeparatedMimetypesOrCommaSeparatedIds).then((mode) => { r = mode; }, onUnexpectedError); @@ -115,7 +114,7 @@ export class ModeServiceImpl implements IModeService { return null; } - public getOrCreateMode(commaSeparatedMimetypesOrCommaSeparatedIds: string): TPromise { + public getOrCreateMode(commaSeparatedMimetypesOrCommaSeparatedIds: string): Promise { return this._onReady().then(() => { const modeId = this.getModeId(commaSeparatedMimetypesOrCommaSeparatedIds); // Fall back to plain text if no mode was found @@ -123,7 +122,7 @@ export class ModeServiceImpl implements IModeService { }); } - public getOrCreateModeByLanguageName(languageName: string): TPromise { + public getOrCreateModeByLanguageName(languageName: string): Promise { return this._onReady().then(() => { const modeId = this._getModeIdByLanguageName(languageName); // Fall back to plain text if no mode was found @@ -141,7 +140,7 @@ export class ModeServiceImpl implements IModeService { return null; } - public getOrCreateModeByFilepathOrFirstLine(filepath: string, firstLine?: string): TPromise { + public getOrCreateModeByFilepathOrFirstLine(filepath: string, firstLine?: string): Promise { return this._onReady().then(() => { const modeId = this.getModeIdByFilepathOrFirstLine(filepath, firstLine); // Fall back to plain text if no mode was found diff --git a/src/vs/editor/common/services/modelService.ts b/src/vs/editor/common/services/modelService.ts index 5052fa378e5..c9994204338 100644 --- a/src/vs/editor/common/services/modelService.ts +++ b/src/vs/editor/common/services/modelService.ts @@ -5,7 +5,6 @@ import { Event } from 'vs/base/common/event'; import { URI } from 'vs/base/common/uri'; -import { TPromise } from 'vs/base/common/winjs.base'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { ITextModel, ITextModelCreationOptions, ITextBufferFactory } from 'vs/editor/common/model'; import { IMode } from 'vs/editor/common/modes'; @@ -15,11 +14,11 @@ export const IModelService = createDecorator('modelService'); export interface IModelService { _serviceBrand: any; - createModel(value: string | ITextBufferFactory, modeOrPromise: TPromise | IMode, resource: URI, isForSimpleWidget?: boolean): ITextModel; + createModel(value: string | ITextBufferFactory, modeOrPromise: Promise | IMode, resource: URI, isForSimpleWidget?: boolean): ITextModel; updateModel(model: ITextModel, value: string | ITextBufferFactory): void; - setMode(model: ITextModel, modeOrPromise: TPromise | IMode): void; + setMode(model: ITextModel, modeOrPromise: Promise | IMode): void; destroyModel(resource: URI): void; diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index 2d3c7a0e35f..301941c34d8 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -9,7 +9,6 @@ import { Event, Emitter } from 'vs/base/common/event'; import { MarkdownString } from 'vs/base/common/htmlContent'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; -import { TPromise } from 'vs/base/common/winjs.base'; import { IMarker, IMarkerService, MarkerSeverity, MarkerTag } from 'vs/platform/markers/common/markers'; import { Range } from 'vs/editor/common/core/range'; import { TextModel, createTextBuffer } from 'vs/editor/common/model/textModel'; @@ -164,7 +163,7 @@ class ModelMarkerHandler { } } - let hoverMessage: MarkdownString = null; + let hoverMessage: MarkdownString | null = null; let { message, source, relatedInformation } = marker; if (typeof message === 'string') { @@ -492,7 +491,7 @@ export class ModelServiceImpl implements IModelService { return [EditOperation.replaceMove(oldRange, textBuffer.getValueInRange(newRange, EndOfLinePreference.TextDefined))]; } - public createModel(value: string | ITextBufferFactory, modeOrPromise: TPromise | IMode, resource: URI, isForSimpleWidget: boolean = false): ITextModel { + public createModel(value: string | ITextBufferFactory, modeOrPromise: Promise | IMode, resource: URI, isForSimpleWidget: boolean = false): ITextModel { let modelData: ModelData; if (!modeOrPromise || isThenable(modeOrPromise)) { @@ -512,7 +511,7 @@ export class ModelServiceImpl implements IModelService { return modelData.model; } - public setMode(model: ITextModel, modeOrPromise: TPromise | IMode): void { + public setMode(model: ITextModel, modeOrPromise: Promise | IMode): void { if (!modeOrPromise) { return; } diff --git a/src/vs/editor/common/standalone/standaloneBase.ts b/src/vs/editor/common/standalone/standaloneBase.ts index 97c84d64e6d..dc3aa4befc6 100644 --- a/src/vs/editor/common/standalone/standaloneBase.ts +++ b/src/vs/editor/common/standalone/standaloneBase.ts @@ -231,8 +231,8 @@ export enum KeyCode { export function createMonacoBaseAPI(): typeof monaco { return { - editor: undefined, - languages: undefined, + editor: undefined!, // undefined override expected here + languages: undefined!, // undefined override expected here CancellationTokenSource: CancellationTokenSource, Emitter: Emitter, KeyCode: KeyCode, diff --git a/src/vs/editor/common/view/minimapCharRenderer.ts b/src/vs/editor/common/view/minimapCharRenderer.ts index 82ed1c196eb..b641f623708 100644 --- a/src/vs/editor/common/view/minimapCharRenderer.ts +++ b/src/vs/editor/common/view/minimapCharRenderer.ts @@ -8,7 +8,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { RGBA8 } from 'vs/editor/common/core/rgba'; export class MinimapTokensColorTracker { - private static _INSTANCE: MinimapTokensColorTracker = null; + private static _INSTANCE: MinimapTokensColorTracker | null = null; public static getInstance(): MinimapTokensColorTracker { if (!this._INSTANCE) { this._INSTANCE = new MinimapTokensColorTracker(); @@ -34,11 +34,11 @@ export class MinimapTokensColorTracker { private _updateColorMap(): void { const colorMap = TokenizationRegistry.getColorMap(); if (!colorMap) { - this._colors = [null]; + this._colors = [RGBA8.Empty]; this._backgroundIsLight = true; return; } - this._colors = [null]; + this._colors = [RGBA8.Empty]; for (let colorId = 1; colorId < colorMap.length; colorId++) { const source = colorMap[colorId].rgba; // Use a VM friendly data-type diff --git a/src/vs/editor/common/view/overviewZoneManager.ts b/src/vs/editor/common/view/overviewZoneManager.ts index 9472c41fcb9..24c204f5c13 100644 --- a/src/vs/editor/common/view/overviewZoneManager.ts +++ b/src/vs/editor/common/view/overviewZoneManager.ts @@ -41,7 +41,7 @@ export class OverviewRulerZone { public readonly endLineNumber: number; public readonly color: string; - private _colorZone: ColorZone; + private _colorZone: ColorZone | null; constructor( startLineNumber: number, @@ -68,7 +68,7 @@ export class OverviewRulerZone { this._colorZone = colorZone; } - public getColorZones(): ColorZone { + public getColorZones(): ColorZone | null { return this._colorZone; } } diff --git a/src/vs/editor/common/view/runtimeMinimapCharRenderer.ts b/src/vs/editor/common/view/runtimeMinimapCharRenderer.ts index 181c646378c..21f84e3fe98 100644 --- a/src/vs/editor/common/view/runtimeMinimapCharRenderer.ts +++ b/src/vs/editor/common/view/runtimeMinimapCharRenderer.ts @@ -13,20 +13,20 @@ function toUint8ClampedArrat(arr: number[]): Uint8ClampedArray { return r; } -let minimapCharRenderer: MinimapCharRenderer = null; +let minimapCharRenderer: MinimapCharRenderer | null = null; export function getOrCreateMinimapCharRenderer(): MinimapCharRenderer { if (!minimapCharRenderer) { - let _x1Data = toUint8ClampedArrat(x1Data); + let _x1Data = toUint8ClampedArrat(x1Data!); x1Data = null; - let _x2Data = toUint8ClampedArrat(x2Data); + let _x2Data = toUint8ClampedArrat(x2Data!); x2Data = null; minimapCharRenderer = new MinimapCharRenderer(_x2Data, _x1Data); } return minimapCharRenderer; } -let x2Data = [ +let x2Data: number[] | null = [ // 0, 0, @@ -600,7 +600,7 @@ let x2Data = [ ]; -let x1Data = [ +let x1Data: number[] | null = [ // 0, diff --git a/src/vs/editor/common/view/viewEvents.ts b/src/vs/editor/common/view/viewEvents.ts index 54035eea267..d8ccfc42c80 100644 --- a/src/vs/editor/common/view/viewEvents.ts +++ b/src/vs/editor/common/view/viewEvents.ts @@ -312,7 +312,7 @@ export interface IViewEventListener { export class ViewEventEmitter extends Disposable { private _listeners: IViewEventListener[]; - private _collector: ViewEventsCollector; + private _collector: ViewEventsCollector | null; private _collectorCnt: number; constructor() { @@ -332,13 +332,13 @@ export class ViewEventEmitter extends Disposable { if (this._collectorCnt === 1) { this._collector = new ViewEventsCollector(); } - return this._collector; + return this._collector!; } protected _endEmit(): void { this._collectorCnt--; if (this._collectorCnt === 0) { - const events = this._collector.finalize(); + const events = this._collector!.finalize(); this._collector = null; if (events.length > 0) { this._emit(events); @@ -383,7 +383,7 @@ export class ViewEventsCollector { public finalize(): ViewEvent[] { let result = this._events; - this._events = null; + this._events = []; return result; } diff --git a/src/vs/editor/common/viewModel/prefixSumComputer.ts b/src/vs/editor/common/viewModel/prefixSumComputer.ts index 88e8968e894..e3144d866dc 100644 --- a/src/vs/editor/common/viewModel/prefixSumComputer.ts +++ b/src/vs/editor/common/viewModel/prefixSumComputer.ts @@ -165,9 +165,9 @@ export class PrefixSumComputer { let low = 0; let high = this.values.length - 1; - let mid: number; - let midStop: number; - let midStart: number; + let mid = 0; + let midStop = 0; + let midStart = 0; while (low <= high) { mid = low + ((high - low) / 2) | 0; @@ -192,7 +192,7 @@ export class PrefixSumComputerWithCache { private readonly _actual: PrefixSumComputer; private _cacheAccumulatedValueStart: number = 0; - private _cache: PrefixSumIndexOfResult[] = null; + private _cache: PrefixSumIndexOfResult[] | null = null; constructor(values: Uint32Array) { this._actual = new PrefixSumComputer(values); diff --git a/src/vs/editor/common/viewModel/splitLinesCollection.ts b/src/vs/editor/common/viewModel/splitLinesCollection.ts index 62042a5b391..84e5248438c 100644 --- a/src/vs/editor/common/viewModel/splitLinesCollection.ts +++ b/src/vs/editor/common/viewModel/splitLinesCollection.ts @@ -547,7 +547,7 @@ export class SplitLinesCollection implements IViewModelLinesCollection { const modelStartLineIndex = modelStart.lineNumber - 1; const modelEndLineIndex = modelEnd.lineNumber - 1; - let reqStart: Position = null; + let reqStart: Position | null = null; for (let modelLineIndex = modelStartLineIndex; modelLineIndex <= modelEndLineIndex; modelLineIndex++) { const line = this.lines[modelLineIndex]; if (line.isVisible()) { @@ -818,7 +818,7 @@ export class SplitLinesCollection implements IViewModelLinesCollection { const modelStartLineIndex = modelStart.lineNumber - 1; const modelEndLineIndex = modelEnd.lineNumber - 1; - let reqStart: Position = null; + let reqStart: Position | null = null; for (let modelLineIndex = modelStartLineIndex; modelLineIndex <= modelEndLineIndex; modelLineIndex++) { const line = this.lines[modelLineIndex]; if (line.isVisible()) { @@ -857,7 +857,7 @@ export class SplitLinesCollection implements IViewModelLinesCollection { // Eliminate duplicate decorations that might have intersected our visible ranges multiple times let finalResult: IModelDecoration[] = [], finalResultLen = 0; - let prevDecId: string = null; + let prevDecId: string | null = null; for (let i = 0, len = result.length; i < len; i++) { const dec = result[i]; const decId = dec.id; diff --git a/src/vs/editor/common/viewModel/viewModelImpl.ts b/src/vs/editor/common/viewModel/viewModelImpl.ts index bbc30dd1ae1..d2e0cd8deda 100644 --- a/src/vs/editor/common/viewModel/viewModelImpl.ts +++ b/src/vs/editor/common/viewModel/viewModelImpl.ts @@ -127,7 +127,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel private _onConfigurationChanged(eventsCollector: viewEvents.ViewEventsCollector, e: IConfigurationChangedEvent): void { // We might need to restore the current centered view range, so save it (if available) - let previousViewportStartModelPosition: Position = null; + let previousViewportStartModelPosition: Position | null = null; if (this.viewportStartLine !== -1) { let previousViewportStartViewPosition = new Position(this.viewportStartLine, this.getLineMinColumn(this.viewportStartLine)); previousViewportStartModelPosition = this.coordinatesConverter.convertViewPositionToModelPosition(previousViewportStartViewPosition); diff --git a/src/vs/editor/contrib/bracketMatching/bracketMatching.ts b/src/vs/editor/contrib/bracketMatching/bracketMatching.ts index 94611bc6bae..7a7b8c01d16 100644 --- a/src/vs/editor/contrib/bracketMatching/bracketMatching.ts +++ b/src/vs/editor/contrib/bracketMatching/bracketMatching.ts @@ -153,7 +153,7 @@ export class BracketMatchingController extends Disposable implements editorCommo // find matching brackets if position is on a bracket const brackets = model.matchBracket(position); - let newCursorPosition: Position = null; + let newCursorPosition: Position | null = null; if (brackets) { if (brackets[0].containsPosition(position)) { newCursorPosition = brackets[1].getStartPosition(); @@ -191,8 +191,8 @@ export class BracketMatchingController extends Disposable implements editorCommo let brackets = model.matchBracket(position); - let openBracket: Position = null; - let closeBracket: Position = null; + let openBracket: Position | null = null; + let closeBracket: Position | null = null; if (!brackets) { const nextBracket = model.findNextBracket(position); diff --git a/src/vs/editor/contrib/contextmenu/contextmenu.ts b/src/vs/editor/contrib/contextmenu/contextmenu.ts index 668cdcc3617..3268ea4da95 100644 --- a/src/vs/editor/contrib/contextmenu/contextmenu.ts +++ b/src/vs/editor/contrib/contextmenu/contextmenu.ts @@ -137,7 +137,7 @@ export class ContextMenuController implements IEditorContribution { return result; } - private _doShowContextMenu(actions: IAction[], forcedPosition: IPosition = null): void { + private _doShowContextMenu(actions: IAction[], forcedPosition: IPosition | null = null): void { // Disable hover const oldHoverSetting = this._editor.getConfiguration().contribInfo.hover; diff --git a/src/vs/editor/contrib/dnd/dnd.ts b/src/vs/editor/contrib/dnd/dnd.ts index 48b343d3b64..51951f45c4b 100644 --- a/src/vs/editor/contrib/dnd/dnd.ts +++ b/src/vs/editor/contrib/dnd/dnd.ts @@ -145,7 +145,7 @@ export class DragAndDropController implements editorCommon.IEditorContribution { let newCursorPosition = new Position(mouseEvent.target.position.lineNumber, mouseEvent.target.position.column); if (this._dragSelection === null) { - let newSelections: Selection[] = null; + let newSelections: Selection[] | null = null; if (mouseEvent.event.shiftKey) { let primarySelection = this._editor.getSelection(); let { selectionStartLineNumber, selectionStartColumn } = primarySelection; diff --git a/src/vs/editor/contrib/documentSymbols/outlineModel.ts b/src/vs/editor/contrib/documentSymbols/outlineModel.ts index 83009d7fe89..23bb9a4cad5 100644 --- a/src/vs/editor/contrib/documentSymbols/outlineModel.ts +++ b/src/vs/editor/contrib/documentSymbols/outlineModel.ts @@ -419,7 +419,7 @@ export class OutlineModel extends TreeElement { } } - let result: OutlineElement = undefined; + let result: OutlineElement | undefined = undefined; for (const key in this._groups) { const group = this._groups[key]; result = group.getItemEnclosingPosition(position); diff --git a/src/vs/editor/contrib/find/findDecorations.ts b/src/vs/editor/contrib/find/findDecorations.ts index e05f4be3987..2b5a30ff8c6 100644 --- a/src/vs/editor/contrib/find/findDecorations.ts +++ b/src/vs/editor/contrib/find/findDecorations.ts @@ -93,7 +93,7 @@ export class FindDecorations implements IDisposable { } public setCurrentFindMatch(nextMatch: Range): number { - let newCurrentDecorationId: string = null; + let newCurrentDecorationId: string | null = null; let matchPosition = 0; if (nextMatch) { for (let i = 0, len = this._decorations.length; i < len; i++) { diff --git a/src/vs/editor/contrib/find/findModel.ts b/src/vs/editor/contrib/find/findModel.ts index 00db5dc69dc..146d28ad3d8 100644 --- a/src/vs/editor/contrib/find/findModel.ts +++ b/src/vs/editor/contrib/find/findModel.ts @@ -170,7 +170,7 @@ export class FindModelBoundToEditorModel { } private research(moveCursor: boolean, newFindScope?: Range): void { - let findScope: Range = null; + let findScope: Range | null = null; if (typeof newFindScope !== 'undefined') { findScope = newFindScope; } else { diff --git a/src/vs/editor/contrib/find/findState.ts b/src/vs/editor/contrib/find/findState.ts index 09641dec6df..fdd0b9093ba 100644 --- a/src/vs/editor/contrib/find/findState.ts +++ b/src/vs/editor/contrib/find/findState.ts @@ -65,10 +65,10 @@ export class FindReplaceState implements IDisposable { private _wholeWordOverride: FindOptionOverride; private _matchCase: boolean; private _matchCaseOverride: FindOptionOverride; - private _searchScope: Range; + private _searchScope: Range | null; private _matchesPosition: number; private _matchesCount: number; - private _currentMatch: Range; + private _currentMatch: Range | null; private readonly _onFindReplaceStateChange: Emitter; public get searchString(): string { return this._searchString; } @@ -83,10 +83,10 @@ export class FindReplaceState implements IDisposable { public get actualWholeWord(): boolean { return this._wholeWord; } public get actualMatchCase(): boolean { return this._matchCase; } - public get searchScope(): Range { return this._searchScope; } + public get searchScope(): Range | null { return this._searchScope; } public get matchesPosition(): number { return this._matchesPosition; } public get matchesCount(): number { return this._matchesCount; } - public get currentMatch(): Range { return this._currentMatch; } + public get currentMatch(): Range | null { return this._currentMatch; } public get onFindReplaceStateChange(): Event { return this._onFindReplaceStateChange.event; } constructor() { diff --git a/src/vs/editor/contrib/find/replacePattern.ts b/src/vs/editor/contrib/find/replacePattern.ts index d721b7c03e0..a4ee990ea20 100644 --- a/src/vs/editor/contrib/find/replacePattern.ts +++ b/src/vs/editor/contrib/find/replacePattern.ts @@ -5,47 +5,57 @@ import { CharCode } from 'vs/base/common/charCode'; +const enum ReplacePatternKind { + StaticValue = 0, + DynamicPieces = 1 +} + +/** + * Assigned when the replace pattern is entirely static. + */ +class StaticValueReplacePattern { + public readonly kind = ReplacePatternKind.StaticValue; + constructor(public readonly staticValue: string) { } +} + +/** + * Assigned when the replace pattern has replacemend patterns. + */ +class DynamicPiecesReplacePattern { + public readonly kind = ReplacePatternKind.DynamicPieces; + constructor(public readonly pieces: ReplacePiece[]) { } +} + export class ReplacePattern { public static fromStaticValue(value: string): ReplacePattern { return new ReplacePattern([ReplacePiece.staticValue(value)]); } - /** - * Assigned when the replace pattern is entirely static. - */ - private readonly _staticValue: string; + private readonly _state: StaticValueReplacePattern | DynamicPiecesReplacePattern; public get hasReplacementPatterns(): boolean { - return this._staticValue === null; + return (this._state.kind === ReplacePatternKind.DynamicPieces); } - /** - * Assigned when the replace pattern has replacemend patterns. - */ - private readonly _pieces: ReplacePiece[]; - - constructor(pieces: ReplacePiece[]) { + constructor(pieces: ReplacePiece[] | null) { if (!pieces || pieces.length === 0) { - this._staticValue = ''; - this._pieces = null; + this._state = new StaticValueReplacePattern(''); } else if (pieces.length === 1 && pieces[0].staticValue !== null) { - this._staticValue = pieces[0].staticValue; - this._pieces = null; + this._state = new StaticValueReplacePattern(pieces[0].staticValue); } else { - this._staticValue = null; - this._pieces = pieces; + this._state = new DynamicPiecesReplacePattern(pieces); } } public buildReplaceString(matches: string[]): string { - if (this._staticValue !== null) { - return this._staticValue; + if (this._state.kind === ReplacePatternKind.StaticValue) { + return this._state.staticValue; } let result = ''; - for (let i = 0, len = this._pieces.length; i < len; i++) { - let piece = this._pieces[i]; + for (let i = 0, len = this._state.pieces.length; i < len; i++) { + let piece = this._state.pieces[i]; if (piece.staticValue !== null) { // static value ReplacePiece result += piece.staticValue; @@ -91,10 +101,10 @@ export class ReplacePiece { return new ReplacePiece(null, index); } - public readonly staticValue: string; + public readonly staticValue: string | null; public readonly matchIndex: number; - private constructor(staticValue: string, matchIndex: number) { + private constructor(staticValue: string | null, matchIndex: number) { this.staticValue = staticValue; this.matchIndex = matchIndex; } @@ -185,7 +195,7 @@ export function parseReplaceString(replaceString: string): ReplacePattern { } let nextChCode = replaceString.charCodeAt(i); - // let replaceWithCharacter: string = null; + // let replaceWithCharacter: string | null = null; switch (nextChCode) { case CharCode.Backslash: diff --git a/src/vs/editor/contrib/folding/syntaxRangeProvider.ts b/src/vs/editor/contrib/folding/syntaxRangeProvider.ts index 9c9c51a5abd..d4886c64de8 100644 --- a/src/vs/editor/contrib/folding/syntaxRangeProvider.ts +++ b/src/vs/editor/contrib/folding/syntaxRangeProvider.ts @@ -45,7 +45,7 @@ export class SyntaxRangeProvider implements RangeProvider { } function collectSyntaxRanges(providers: FoldingRangeProvider[], model: ITextModel, cancellationToken: CancellationToken): Thenable { - let rangeData: IFoldingRangeData[] = null; + let rangeData: IFoldingRangeData[] | null = null; let promises = providers.map((provider, i) => { return Promise.resolve(provider.provideFoldingRanges(model, foldingContext, cancellationToken)).then(ranges => { if (cancellationToken.isCancellationRequested) { @@ -156,7 +156,7 @@ export function sanitizeRanges(rangeData: IFoldingRangeData[], limit: number): F }); let collector = new RangesCollector(limit); - let top: IFoldingRangeData = null; + let top: IFoldingRangeData | null = null; let previous = []; for (let entry of sorted) { if (!top) { diff --git a/src/vs/editor/contrib/format/formattingEdit.ts b/src/vs/editor/contrib/format/formattingEdit.ts index c6fa49410a4..b83bb89eb03 100644 --- a/src/vs/editor/contrib/format/formattingEdit.ts +++ b/src/vs/editor/contrib/format/formattingEdit.ts @@ -12,7 +12,7 @@ import { TextEdit } from 'vs/editor/common/modes'; export class FormattingEdit { private static _handleEolEdits(editor: ICodeEditor, edits: TextEdit[]): ISingleEditOperation[] { - let newEol: EndOfLineSequence = undefined; + let newEol: EndOfLineSequence | undefined = undefined; let singleEdits: ISingleEditOperation[] = []; for (let edit of edits) { diff --git a/src/vs/editor/contrib/markdown/markdownRenderer.ts b/src/vs/editor/contrib/markdown/markdownRenderer.ts index 671fdbc165c..561d886ea12 100644 --- a/src/vs/editor/contrib/markdown/markdownRenderer.ts +++ b/src/vs/editor/contrib/markdown/markdownRenderer.ts @@ -28,7 +28,7 @@ export class MarkdownRenderer { constructor( private readonly _editor: ICodeEditor, @IModeService private readonly _modeService: IModeService, - @optional(IOpenerService) private readonly _openerService: IOpenerService = NullOpenerService, + @optional(IOpenerService) private readonly _openerService: IOpenerService | null = NullOpenerService, ) { } diff --git a/src/vs/editor/contrib/multicursor/multicursor.ts b/src/vs/editor/contrib/multicursor/multicursor.ts index 55bfa59e446..fcc3610ce62 100644 --- a/src/vs/editor/contrib/multicursor/multicursor.ts +++ b/src/vs/editor/contrib/multicursor/multicursor.ts @@ -206,7 +206,7 @@ export class MultiCursorSession { const s = editor.getSelection(); let searchText: string; - let currentMatch: Selection = null; + let currentMatch: Selection | null = null; if (s.isEmpty()) { // selection is empty => expand to current word @@ -476,7 +476,7 @@ export class MultiCursorSelectionController extends Disposable implements IEdito } public selectAll(findController: CommonFindController): void { - let matches: FindMatch[] = null; + let matches: FindMatch[] | null = null; const findState = findController.getState(); diff --git a/src/vs/editor/contrib/smartSelect/test/tokenSelectionSupport.test.ts b/src/vs/editor/contrib/smartSelect/test/tokenSelectionSupport.test.ts index a31987aab62..54f7e4601b9 100644 --- a/src/vs/editor/contrib/smartSelect/test/tokenSelectionSupport.test.ts +++ b/src/vs/editor/contrib/smartSelect/test/tokenSelectionSupport.test.ts @@ -35,9 +35,9 @@ class MockJSMode extends MockMode { suite('TokenSelectionSupport', () => { - let modelService: ModelServiceImpl = null; + let modelService: ModelServiceImpl | null = null; let tokenSelectionSupport: TokenSelectionSupport; - let mode: MockJSMode = null; + let mode: MockJSMode | null = null; setup(() => { modelService = new ModelServiceImpl(null, new TestConfigurationService()); diff --git a/src/vs/editor/contrib/suggest/test/suggestModel.test.ts b/src/vs/editor/contrib/suggest/test/suggestModel.test.ts index 3daf4eec203..3df4a248ada 100644 --- a/src/vs/editor/contrib/suggest/test/suggestModel.test.ts +++ b/src/vs/editor/contrib/suggest/test/suggestModel.test.ts @@ -63,7 +63,7 @@ suite('SuggestModel - Context', function () { tokenize: undefined, tokenize2: (line: string, state: IState): TokenizationResult2 => { const tokensArr: number[] = []; - let prevLanguageId: LanguageIdentifier = undefined; + let prevLanguageId: LanguageIdentifier | undefined = undefined; for (let i = 0; i < line.length; i++) { const languageId = (line.charAt(i) === 'x' ? INNER_LANGUAGE_ID : OUTER_LANGUAGE_ID); if (prevLanguageId !== languageId) { diff --git a/src/vs/editor/standalone/browser/colorizer.ts b/src/vs/editor/standalone/browser/colorizer.ts index 4e79aaaed50..47a2bc4aa05 100644 --- a/src/vs/editor/standalone/browser/colorizer.ts +++ b/src/vs/editor/standalone/browser/colorizer.ts @@ -65,8 +65,8 @@ export class Colorizer { } return new Promise((resolve, reject) => { - let listener: IDisposable = null; - let timeout: TimeoutTimer = null; + let listener: IDisposable | null = null; + let timeout: TimeoutTimer | null = null; const execute = () => { if (listener) { diff --git a/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts b/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts index f81c9c3801b..24526f675d5 100644 --- a/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts +++ b/src/vs/editor/standalone/browser/quickOpen/quickOutline.ts @@ -190,7 +190,7 @@ export class QuickOutlineAction extends BaseEditorQuickOpenAction { if (highlights) { // Show parent scope as description - let description: string = null; + let description: string | null = null; if (element.containerName) { description = element.containerName; } @@ -211,8 +211,8 @@ export class QuickOutlineAction extends BaseEditorQuickOpenAction { // Mark all type groups if (results.length > 0 && searchValue.indexOf(SCOPE_PREFIX) === 0) { - let currentType: string = null; - let currentResult: SymbolEntry = null; + let currentType: string | null = null; + let currentResult: SymbolEntry | null = null; let typeCounter = 0; for (let i = 0; i < results.length; i++) { diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index b4ccc3ad5c7..186a6affe82 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -35,7 +35,7 @@ import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKe import { OS } from 'vs/base/common/platform'; import { Range } from 'vs/editor/common/core/range'; import { ITextModel } from 'vs/editor/common/model'; -import { INotificationService, INotification, INotificationHandle, NoOpNotification, IPromptChoice } from 'vs/platform/notification/common/notification'; +import { INotificationService, INotification, INotificationHandle, NoOpNotification, IPromptChoice, IPromptOptions } from 'vs/platform/notification/common/notification'; import { IConfirmation, IConfirmationResult, IDialogService, IDialogOptions } from 'vs/platform/dialogs/common/dialogs'; import { IPosition, Position as Pos } from 'vs/editor/common/core/position'; import { isEditorConfigurationKey, isDiffEditorConfigurationKey } from 'vs/editor/common/config/commonEditorConfig'; @@ -146,7 +146,7 @@ export class SimpleProgressService implements IProgressService { return SimpleProgressService.NULL_PROGRESS_RUNNER; } - showWhile(promise: TPromise, delay?: number): TPromise { + showWhile(promise: Thenable, delay?: number): Thenable { return null; } } @@ -155,7 +155,7 @@ export class SimpleDialogService implements IDialogService { public _serviceBrand: any; - public confirm(confirmation: IConfirmation): TPromise { + public confirm(confirmation: IConfirmation): Thenable { return this.doConfirm(confirmation).then(confirmed => { return { confirmed, @@ -164,17 +164,17 @@ export class SimpleDialogService implements IDialogService { }); } - private doConfirm(confirmation: IConfirmation): TPromise { + private doConfirm(confirmation: IConfirmation): Thenable { let messageText = confirmation.message; if (confirmation.detail) { messageText = messageText + '\n\n' + confirmation.detail; } - return TPromise.wrap(window.confirm(messageText)); + return Promise.resolve(window.confirm(messageText)); } - public show(severity: Severity, message: string, buttons: string[], options?: IDialogOptions): TPromise { - return TPromise.as(0); + public show(severity: Severity, message: string, buttons: string[], options?: IDialogOptions): Thenable { + return Promise.resolve(0); } } @@ -212,7 +212,7 @@ export class SimpleNotificationService implements INotificationService { return SimpleNotificationService.NO_OP; } - public prompt(severity: Severity, message: string, choices: IPromptChoice[], onCancel?: () => void): INotificationHandle { + public prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle { return SimpleNotificationService.NO_OP; } } @@ -470,7 +470,7 @@ export class SimpleMenuService implements IMenuService { } public createMenu(id: MenuId, contextKeyService: IContextKeyService): IMenu { - return new Menu(id, TPromise.as(true), this._commandService, contextKeyService); + return new Menu(id, Promise.resolve(true), this._commandService, contextKeyService); } } diff --git a/src/vs/editor/standalone/browser/standaloneCodeServiceImpl.ts b/src/vs/editor/standalone/browser/standaloneCodeServiceImpl.ts index 4e9ddcbc2f9..7d39af3dd1e 100644 --- a/src/vs/editor/standalone/browser/standaloneCodeServiceImpl.ts +++ b/src/vs/editor/standalone/browser/standaloneCodeServiceImpl.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { IResourceInput } from 'vs/platform/editor/common/editor'; -import { TPromise } from 'vs/base/common/winjs.base'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { CodeEditorServiceImpl } from 'vs/editor/browser/services/codeEditorServiceImpl'; import { ScrollType } from 'vs/editor/common/editorCommon'; @@ -20,12 +19,12 @@ export class StandaloneCodeEditorServiceImpl extends CodeEditorServiceImpl { return null; // not supported in the standalone case } - public openCodeEditor(input: IResourceInput, source: ICodeEditor, sideBySide?: boolean): TPromise { + public openCodeEditor(input: IResourceInput, source: ICodeEditor, sideBySide?: boolean): Thenable { if (!source) { - return TPromise.as(null); + return Promise.resolve(null); } - return TPromise.as(this.doOpenEditor(source, input)); + return Promise.resolve(this.doOpenEditor(source, input)); } private doOpenEditor(editor: ICodeEditor, input: IResourceInput): ICodeEditor { diff --git a/src/vs/editor/standalone/browser/standaloneEditor.ts b/src/vs/editor/standalone/browser/standaloneEditor.ts index a85dd145bea..9edf689c5f5 100644 --- a/src/vs/editor/standalone/browser/standaloneEditor.ts +++ b/src/vs/editor/standalone/browser/standaloneEditor.ts @@ -11,7 +11,6 @@ import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { IEditorOverrideServices, DynamicStandaloneServices, StaticServices } from 'vs/editor/standalone/browser/standaloneServices'; import { IDisposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; -import { TPromise } from 'vs/base/common/winjs.base'; import { OpenerService } from 'vs/editor/browser/services/openerService'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { Colorizer, IColorizerElementOptions, IColorizerOptions } from 'vs/editor/standalone/browser/colorizer'; @@ -41,7 +40,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur function withAllStandaloneServices(domElement: HTMLElement, override: IEditorOverrideServices, callback: (services: DynamicStandaloneServices) => T): T { let services = new DynamicStandaloneServices(domElement, override); - let simpleEditorModelResolverService: SimpleEditorModelResolverService = null; + let simpleEditorModelResolverService: SimpleEditorModelResolverService | null = null; if (!services.has(ITextModelService)) { simpleEditorModelResolverService = new SimpleEditorModelResolverService(); services.set(ITextModelService, simpleEditorModelResolverService); @@ -136,7 +135,7 @@ export function createDiffNavigator(diffEditor: IStandaloneDiffEditor, opts?: ID return new DiffNavigator(diffEditor, opts); } -function doCreateModel(value: string, mode: TPromise, uri?: URI): ITextModel { +function doCreateModel(value: string, mode: Promise, uri?: URI): ITextModel { return StaticServices.modelService.get().createModel(value, mode, uri); } diff --git a/src/vs/editor/standalone/browser/standaloneServices.ts b/src/vs/editor/standalone/browser/standaloneServices.ts index 0536d39b290..3869857d131 100644 --- a/src/vs/editor/standalone/browser/standaloneServices.ts +++ b/src/vs/editor/standalone/browser/standaloneServices.ts @@ -171,7 +171,7 @@ export class DynamicStandaloneServices extends Disposable { const themeService = this.get(IThemeService); let ensure = (serviceId: ServiceIdentifier, factory: () => T): T => { - let value: T = null; + let value: T | null = null; if (overrides) { value = overrides[serviceId.toString()]; } diff --git a/src/vs/editor/standalone/common/monarch/monarchCommon.ts b/src/vs/editor/standalone/common/monarch/monarchCommon.ts index f7c4c13e1e4..f6c564c6748 100644 --- a/src/vs/editor/standalone/common/monarch/monarchCommon.ts +++ b/src/vs/editor/standalone/common/monarch/monarchCommon.ts @@ -32,7 +32,7 @@ export interface ILexerMin { export interface ILexer extends ILexerMin { maxStack: number; - start: string; + start: string | null; ignoreCase: boolean; tokenPostfix: string; @@ -93,7 +93,7 @@ export interface IAction { export interface IBranch { name: string; value: FuzzyAction; - test: (id: string, matches: string[], state: string, eos: boolean) => boolean; + test?: (id: string, matches: string[], state: string, eos: boolean) => boolean; } // Small helper functions @@ -150,7 +150,7 @@ export function throwError(lexer: ILexerMin, msg: string) { */ export function substituteMatches(lexer: ILexerMin, str: string, id: string, matches: string[], state: string): string { const re = /\$((\$)|(#)|(\d\d?)|[sS](\d\d?)|@(\w+))/g; - let stateMatches: string[] = null; + let stateMatches: string[] | null = null; return str.replace(re, function (full, sub?, dollar?, hash?, n?, s?, attr?, ofs?, total?) { if (!empty(dollar)) { return '$'; // $$ @@ -178,7 +178,8 @@ export function substituteMatches(lexer: ILexerMin, str: string, id: string, mat /** * Find the tokenizer rules for a specific state (i.e. next action) */ -export function findRules(lexer: ILexer, state: string): IRule[] { +export function findRules(lexer: ILexer, inState: string): IRule[] | null { + let state: string | null = inState; while (state && state.length > 0) { const rules = lexer.tokenizer[state]; if (rules) { @@ -200,7 +201,8 @@ export function findRules(lexer: ILexer, state: string): IRule[] { * This is used during compilation where we may know the defined states * but not yet whether the corresponding rules are correct. */ -export function stateExists(lexer: ILexerMin, state: string): boolean { +export function stateExists(lexer: ILexerMin, inState: string): boolean { + let state: string | null = inState; while (state && state.length > 0) { const exist = lexer.stateNames[state]; if (exist) { diff --git a/src/vs/editor/standalone/common/monarch/monarchCompile.ts b/src/vs/editor/standalone/common/monarch/monarchCompile.ts index e806a9054fe..33807893dac 100644 --- a/src/vs/editor/standalone/common/monarch/monarchCompile.ts +++ b/src/vs/editor/standalone/common/monarch/monarchCompile.ts @@ -38,25 +38,18 @@ function isArrayOf(elemType: (x: any) => boolean, obj: any): boolean { return true; } -function bool(prop: any, def?: boolean, onerr?: () => void): boolean { - if (typeof (prop) === 'boolean') { +function bool(prop: any, defValue: boolean): boolean { + if (typeof prop === 'boolean') { return prop; } - if (onerr && (prop || def === undefined)) { - onerr(); // type is wrong, or there is no default - } - return (def === undefined ? null : def); + return defValue; } -function string(prop: any, def?: string, onerr?: () => void): string { +function string(prop: any, defValue: string): string { if (typeof (prop) === 'string') { return prop; } - if (onerr && (prop || def === undefined)) { - onerr(); // type is wrong, or there is no default - } - return (def === undefined ? null : def); - + return defValue; } // Lexer helpers @@ -66,10 +59,6 @@ function string(prop: any, def?: string, onerr?: () => void): string { * Also replaces @\w+ or sequences with the content of the specified attribute */ function compileRegExp(lexer: monarchCommon.ILexerMin, str: string): RegExp { - if (typeof (str) !== 'string') { - return null; - } - let n = 0; while (str.indexOf('@') >= 0 && n < 5) { // at most 5 expansions n++; @@ -98,7 +87,7 @@ function compileRegExp(lexer: monarchCommon.ILexerMin, str: string): RegExp { * This compiles 'cases' attributes into efficient match functions. * */ -function selectScrutinee(id: string, matches: string[], state: string, num: number): string { +function selectScrutinee(id: string, matches: string[], state: string, num: number): string | null { if (num < 0) { return id; } @@ -120,7 +109,7 @@ function createGuard(lexer: monarchCommon.ILexerMin, ruleName: string, tkey: str // get the scrutinee and pattern let scrut = -1; // -1: $!, 0-99: $n, 100+n: $Sn let oppat = tkey; - let matches: string[] = tkey.match(/^\$(([sS]?)(\d\d?)|#)(.*)$/); + let matches = tkey.match(/^\$(([sS]?)(\d\d?)|#)(.*)$/); if (matches) { if (matches[3]) { // if digits scrut = parseInt(matches[3]); @@ -302,7 +291,7 @@ function compileAction(lexer: monarchCommon.ILexerMin, ruleName: string, action: // what kind of case if (tkey === '@default' || tkey === '@' || tkey === '') { - cases.push({ test: null, value: val, name: tkey }); + cases.push({ test: undefined, value: val, name: tkey }); } else if (tkey === '@eos') { cases.push({ test: function (id, matches, state, eos) { return eos; }, value: val, name: tkey }); @@ -319,9 +308,10 @@ function compileAction(lexer: monarchCommon.ILexerMin, ruleName: string, action: test: function (id, matches, state, eos) { for (let idx in cases) { if (cases.hasOwnProperty(idx)) { - const didmatch = (!cases[idx].test || cases[idx].test(id, matches, state, eos)); + const _case = cases[idx]; + const didmatch = (!_case.test || _case.test(id, matches, state, eos)); if (didmatch) { - return cases[idx].value; + return _case.value; } } } @@ -357,7 +347,7 @@ class Rule implements monarchCommon.IRule { sregex = (re).source; } else { - monarchCommon.throwError(lexer, 'rules must start with a match string or regular expression: ' + this.name); + return monarchCommon.throwError(lexer, 'rules must start with a match string or regular expression: ' + this.name); } this.matchOnlyAtLineStart = (sregex.length > 0 && sregex[0] === '^'); @@ -391,11 +381,11 @@ export function compile(languageId: string, json: IMonarchLanguage): monarchComm lexer.maxStack = 100; // Set standard fields: be defensive about types - lexer.start = string(json.start); + lexer.start = (typeof json.start === 'string' ? json.start : null); lexer.ignoreCase = bool(json.ignoreCase, false); lexer.tokenPostfix = string(json.tokenPostfix, '.' + lexer.languageId); - lexer.defaultToken = string(json.defaultToken, 'source', function () { monarchCommon.throwError(lexer, 'the \'defaultToken\' must be a string'); }); + lexer.defaultToken = string(json.defaultToken, 'source'); lexer.usesEmbedded = false; // becomes true if we find a nextEmbedded action @@ -456,10 +446,12 @@ export function compile(languageId: string, json: IMonarchLanguage): monarchComm monarchCommon.throwError(lexer, 'a rule must either be an array, or an object with a \'regex\' or \'include\' field at: ' + state); } if (rule.name) { - newrule.name = string(rule.name); + if (typeof rule.name === 'string') { + newrule.name = rule.name; + } } if (rule.matchOnlyAtStart) { - newrule.matchOnlyAtLineStart = bool(rule.matchOnlyAtLineStart); + newrule.matchOnlyAtLineStart = bool(rule.matchOnlyAtLineStart, false); } newrule.setRegex(lexerMin, rule.regex); newrule.setAction(lexerMin, rule.action); @@ -514,11 +506,11 @@ export function compile(languageId: string, json: IMonarchLanguage): monarchComm monarchCommon.throwError(lexer, 'open and close brackets in a \'brackets\' attribute must be different: ' + desc.open + '\n hint: use the \'bracket\' attribute if matching on equal brackets is required.'); } - if (typeof (desc.open) === 'string' && typeof (desc.token) === 'string') { + if (typeof desc.open === 'string' && typeof desc.token === 'string' && typeof desc.close === 'string') { brackets.push({ - token: string(desc.token) + lexer.tokenPostfix - , open: monarchCommon.fixCase(lexer, string(desc.open)) - , close: monarchCommon.fixCase(lexer, string(desc.close)) + token: desc.token + lexer.tokenPostfix, + open: monarchCommon.fixCase(lexer, desc.open), + close: monarchCommon.fixCase(lexer, desc.close) }); } else { diff --git a/src/vs/editor/standalone/common/monarch/monarchLexer.ts b/src/vs/editor/standalone/common/monarch/monarchLexer.ts index 2e15f360eaa..2c9f3691e47 100644 --- a/src/vs/editor/standalone/common/monarch/monarchLexer.ts +++ b/src/vs/editor/standalone/common/monarch/monarchLexer.ts @@ -518,8 +518,8 @@ class MonarchTokenizer implements modes.ITokenizationSupport { // regular expression group matching // these never need cloning or equality since they are only used within a line match let groupActions: monarchCommon.FuzzyAction[] = null; - let groupMatches: string[] = null; - let groupMatched: string[] = null; + let groupMatches: string[] | null = null; + let groupMatched: string[] | null = null; let groupRule: monarchCommon.IRule = null; while (pos < lineLength) { @@ -528,12 +528,12 @@ class MonarchTokenizer implements modes.ITokenizationSupport { const groupLen0 = groupActions ? groupActions.length : 0; const state = stack.state; - let matches: string[] = null; - let matched: string = null; + let matches: string[] | null = null; + let matched: string | null = null; let action: monarchCommon.FuzzyAction | monarchCommon.FuzzyAction[] = null; let rule: monarchCommon.IRule = null; - let enteringEmbeddedMode: string = null; + let enteringEmbeddedMode: string | null = null; // check if we need to process group matches first if (groupActions) { @@ -738,7 +738,7 @@ class MonarchTokenizer implements modes.ITokenizationSupport { // return the result (and check for brace matching) // todo: for efficiency we could pre-sanitize tokenPostfix and substitutions - let tokenType: string = null; + let tokenType: string | null = null; if (monarchCommon.isString(result) && result.indexOf('@brackets') === 0) { let rest = result.substr('@brackets'.length); let bracket = findBracket(this._lexer, matched); diff --git a/src/vs/editor/standalone/test/browser/standaloneLanguages.test.ts b/src/vs/editor/standalone/test/browser/standaloneLanguages.test.ts index f2e4e6f3754..e8b3ec85b60 100644 --- a/src/vs/editor/standalone/test/browser/standaloneLanguages.test.ts +++ b/src/vs/editor/standalone/test/browser/standaloneLanguages.test.ts @@ -56,7 +56,7 @@ suite('TokenizationSupport2Adapter', () => { } }; } - public readonly onThemeChange: Event = null; + public readonly onThemeChange: Event | null = null; } class MockState implements IState { diff --git a/src/vs/editor/test/browser/controller/cursor.test.ts b/src/vs/editor/test/browser/controller/cursor.test.ts index fd97276f0db..b4df2444ab3 100644 --- a/src/vs/editor/test/browser/controller/cursor.test.ts +++ b/src/vs/editor/test/browser/controller/cursor.test.ts @@ -2384,7 +2384,7 @@ suite('Editor Controller - Cursor Configuration', () => { class TestCommand implements ICommand { - private _selectionId: string = null; + private _selectionId: string | null = null; public getEditOperations(model: ITextModel, builder: IEditOperationBuilder): void { builder.addEditOperation(new Range(1, 13, 1, 14), ''); @@ -3824,7 +3824,7 @@ suite('ElectricCharacter', () => { languageIdentifier: mode.getLanguageIdentifier() }, (model, cursor) => { moveTo(cursor, 1, 5); - let changeText: string = null; + let changeText: string | null = null; model.onDidChangeContent(e => { changeText = e.changes[0].text; }); diff --git a/src/vs/editor/test/browser/testCodeEditor.ts b/src/vs/editor/test/browser/testCodeEditor.ts index 914a82a127f..00233ee4c3a 100644 --- a/src/vs/editor/test/browser/testCodeEditor.ts +++ b/src/vs/editor/test/browser/testCodeEditor.ts @@ -54,7 +54,7 @@ export class TestCodeEditor extends CodeEditorWidget implements editorBrowser.IC } class TestEditorDomElement { - parentElement: IContextKeyServiceTarget = null; + parentElement: IContextKeyServiceTarget | null = null; setAttribute(attr: string, value: string): void { } removeAttribute(attr: string): void { } hasAttribute(attr: string): boolean { return false; } diff --git a/src/vs/editor/test/common/editorTestUtils.ts b/src/vs/editor/test/common/editorTestUtils.ts index daeeb7ea91f..6d800762f3b 100644 --- a/src/vs/editor/test/common/editorTestUtils.ts +++ b/src/vs/editor/test/common/editorTestUtils.ts @@ -24,7 +24,7 @@ export interface IRelaxedTextModelCreationOptions { largeFileOptimizations?: boolean; } -export function createTextModel(text: string, _options: IRelaxedTextModelCreationOptions = TextModel.DEFAULT_CREATION_OPTIONS, languageIdentifier: LanguageIdentifier = null, uri: URI = null): TextModel { +export function createTextModel(text: string, _options: IRelaxedTextModelCreationOptions = TextModel.DEFAULT_CREATION_OPTIONS, languageIdentifier: LanguageIdentifier | null = null, uri: URI | null = null): TextModel { const options: ITextModelCreationOptions = { tabSize: (typeof _options.tabSize === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.tabSize : _options.tabSize), insertSpaces: (typeof _options.insertSpaces === 'undefined' ? TextModel.DEFAULT_CREATION_OPTIONS.insertSpaces : _options.insertSpaces), diff --git a/src/vs/editor/test/common/model/model.modes.test.ts b/src/vs/editor/test/common/model/model.modes.test.ts index 177cd2c3d72..24281106b4e 100644 --- a/src/vs/editor/test/common/model/model.modes.test.ts +++ b/src/vs/editor/test/common/model/model.modes.test.ts @@ -32,8 +32,8 @@ suite('Editor Model - Model Modes 1', () => { } }; - let thisModel: TextModel = null; - let languageRegistration: IDisposable = null; + let thisModel: TextModel | null = null; + let languageRegistration: IDisposable | null = null; setup(() => { const TEXT = @@ -202,8 +202,8 @@ suite('Editor Model - Model Modes 2', () => { stateEqual((model)._tokens._lastState, states[len]); } - let thisModel: TextModel = null; - let languageRegistration: IDisposable = null; + let thisModel: TextModel | null = null; + let languageRegistration: IDisposable | null = null; setup(() => { const TEXT = diff --git a/src/vs/editor/test/common/model/model.test.ts b/src/vs/editor/test/common/model/model.test.ts index cdac6b024ca..cacd40b88b7 100644 --- a/src/vs/editor/test/common/model/model.test.ts +++ b/src/vs/editor/test/common/model/model.test.ts @@ -104,7 +104,7 @@ suite('Editor Model - Model', () => { }); test('model insert text without newline eventing', () => { - let e: ModelRawContentChangedEvent = null; + let e: ModelRawContentChangedEvent | null = null; thisModel.onDidChangeRawContent((_e) => { if (e !== null) { assert.fail('Unexpected assertion error'); @@ -123,7 +123,7 @@ suite('Editor Model - Model', () => { }); test('model insert text with one newline eventing', () => { - let e: ModelRawContentChangedEvent = null; + let e: ModelRawContentChangedEvent | null = null; thisModel.onDidChangeRawContent((_e) => { if (e !== null) { assert.fail('Unexpected assertion error'); @@ -200,7 +200,7 @@ suite('Editor Model - Model', () => { }); test('model delete text from one line eventing', () => { - let e: ModelRawContentChangedEvent = null; + let e: ModelRawContentChangedEvent | null = null; thisModel.onDidChangeRawContent((_e) => { if (e !== null) { assert.fail('Unexpected assertion error'); @@ -219,7 +219,7 @@ suite('Editor Model - Model', () => { }); test('model delete all text from a line eventing', () => { - let e: ModelRawContentChangedEvent = null; + let e: ModelRawContentChangedEvent | null = null; thisModel.onDidChangeRawContent((_e) => { if (e !== null) { assert.fail('Unexpected assertion error'); @@ -238,7 +238,7 @@ suite('Editor Model - Model', () => { }); test('model delete text from two lines eventing', () => { - let e: ModelRawContentChangedEvent = null; + let e: ModelRawContentChangedEvent | null = null; thisModel.onDidChangeRawContent((_e) => { if (e !== null) { assert.fail('Unexpected assertion error'); @@ -258,7 +258,7 @@ suite('Editor Model - Model', () => { }); test('model delete text from many lines eventing', () => { - let e: ModelRawContentChangedEvent = null; + let e: ModelRawContentChangedEvent | null = null; thisModel.onDidChangeRawContent((_e) => { if (e !== null) { assert.fail('Unexpected assertion error'); @@ -309,7 +309,7 @@ suite('Editor Model - Model', () => { // --------- setValue test('setValue eventing', () => { - let e: ModelRawContentChangedEvent = null; + let e: ModelRawContentChangedEvent | null = null; thisModel.onDidChangeRawContent((_e) => { if (e !== null) { assert.fail('Unexpected assertion error'); @@ -392,7 +392,7 @@ suite('Editor Model - Words', () => { tokenize: undefined, tokenize2: (line: string, state: IState): TokenizationResult2 => { const tokensArr: number[] = []; - let prevLanguageId: LanguageIdentifier = undefined; + let prevLanguageId: LanguageIdentifier | undefined = undefined; for (let i = 0; i < line.length; i++) { const languageId = (line.charAt(i) === 'x' ? INNER_LANGUAGE_ID : OUTER_LANGUAGE_ID); if (prevLanguageId !== languageId) { diff --git a/src/vs/editor/test/common/model/textModelSearch.test.ts b/src/vs/editor/test/common/model/textModelSearch.test.ts index 3c9ced8ebd1..c6c22689be8 100644 --- a/src/vs/editor/test/common/model/textModelSearch.test.ts +++ b/src/vs/editor/test/common/model/textModelSearch.test.ts @@ -16,7 +16,7 @@ suite('TextModelSearch', () => { const usualWordSeparators = getMapForWordSeparators(USUAL_WORD_SEPARATORS); - function assertFindMatch(actual: FindMatch, expectedRange: Range, expectedMatches: string[] = null): void { + function assertFindMatch(actual: FindMatch, expectedRange: Range, expectedMatches: string[] | null = null): void { assert.deepEqual(actual, new FindMatch(expectedRange, expectedMatches)); } diff --git a/src/vs/editor/test/common/model/textModelWithTokens.test.ts b/src/vs/editor/test/common/model/textModelWithTokens.test.ts index d4f443411b6..9350a8278db 100644 --- a/src/vs/editor/test/common/model/textModelWithTokens.test.ts +++ b/src/vs/editor/test/common/model/textModelWithTokens.test.ts @@ -157,7 +157,7 @@ suite('TextModelWithTokens - bracket matching', () => { } const languageIdentifier = new LanguageIdentifier('bracketMode1', LanguageId.PlainText); - let registration: IDisposable = null; + let registration: IDisposable | null = null; setup(() => { registration = LanguageConfigurationRegistry.register(languageIdentifier, { diff --git a/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts b/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts index 08974cba494..6a022329bdd 100644 --- a/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts +++ b/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts @@ -321,8 +321,8 @@ suite('SplitLinesCollection', () => { ] ]; - let model: TextModel = null; - let languageRegistration: IDisposable = null; + let model: TextModel | null = null; + let languageRegistration: IDisposable | null = null; setup(() => { let _lineIndex = 0; diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index e671957aa7d..df8acc21d1c 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -612,11 +612,11 @@ declare namespace monaco { /** * A intersection of the two ranges. */ - intersectRanges(range: IRange): Range; + intersectRanges(range: IRange): Range | null; /** * A intersection of the two ranges. */ - static intersectRanges(a: IRange, b: IRange): Range; + static intersectRanges(a: IRange, b: IRange): Range | null; /** * Test if this range equals other. */ @@ -624,7 +624,7 @@ declare namespace monaco { /** * Test if range `a` equals `b`. */ - static equalsRange(a: IRange, b: IRange): boolean; + static equalsRange(a: IRange | null, b: IRange | null): boolean; /** * Return the end position (which will be after or equal to the start position) */ @@ -657,6 +657,7 @@ declare namespace monaco { /** * Create a `Range` from an `IRange`. */ + static lift(range: undefined | null): null; static lift(range: IRange): Range; /** * Test if `obj` is an `IRange`. @@ -1221,15 +1222,15 @@ declare namespace monaco.editor { /** * CSS class name describing the decoration. */ - className?: string; + className?: string | null; /** * Message to be rendered when hovering over the glyph margin decoration. */ - glyphMarginHoverMessage?: IMarkdownString | IMarkdownString[]; + glyphMarginHoverMessage?: IMarkdownString | IMarkdownString[] | null; /** * Array of MarkdownString to render as the decoration message. */ - hoverMessage?: IMarkdownString | IMarkdownString[]; + hoverMessage?: IMarkdownString | IMarkdownString[] | null; /** * Should the decoration expand to encompass a whole line. */ @@ -1242,25 +1243,25 @@ declare namespace monaco.editor { /** * If set, render this decoration in the overview ruler. */ - overviewRuler?: IModelDecorationOverviewRulerOptions; + overviewRuler?: IModelDecorationOverviewRulerOptions | null; /** * If set, the decoration will be rendered in the glyph margin with this CSS class name. */ - glyphMarginClassName?: string; + glyphMarginClassName?: string | null; /** * If set, the decoration will be rendered in the lines decorations with this CSS class name. */ - linesDecorationsClassName?: string; + linesDecorationsClassName?: string | null; /** * If set, the decoration will be rendered in the margin (covering its full width) with this CSS class name. */ - marginClassName?: string; + marginClassName?: string | null; /** * If set, the decoration will be rendered inline with the text with this CSS class name. * Please use this only for CSS rules that must impact the text. For example, use `className` * to have a background color decoration. */ - inlineClassName?: string; + inlineClassName?: string | null; /** * If there is an `inlineClassName` which affects letter spacing. */ @@ -1268,11 +1269,11 @@ declare namespace monaco.editor { /** * If set, the decoration will be rendered before the text with this CSS class name. */ - beforeContentClassName?: string; + beforeContentClassName?: string | null; /** * If set, the decoration will be rendered after the text with this CSS class name. */ - afterContentClassName?: string; + afterContentClassName?: string | null; } /** @@ -1420,7 +1421,7 @@ declare namespace monaco.editor { /** * The text to replace with. This can be null to emulate a simple delete. */ - text: string; + text: string | null; /** * This indicates that this operation has "insert" semantics. * i.e. forceMoveMarkers = true => if `range` is collapsed, all markers at the position will be moved. @@ -1455,7 +1456,7 @@ declare namespace monaco.editor { export class FindMatch { _findMatchBrand: void; readonly range: Range; - readonly matches: string[]; + readonly matches: string[] | null; } /** @@ -1641,7 +1642,7 @@ declare namespace monaco.editor { * @param captureMatches The result will contain the captured groups. * @return The range where the next match is. It is null if no next match has been found. */ - findNextMatch(searchString: string, searchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string | null, captureMatches: boolean): FindMatch; + findNextMatch(searchString: string, searchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string | null, captureMatches: boolean): FindMatch | null; /** * Search the model for the previous match. Loops to the end of the model if needed. * @param searchString The string used to search. If it is a regular expression, set `isRegex` to true. @@ -1652,7 +1653,7 @@ declare namespace monaco.editor { * @param captureMatches The result will contain the captured groups. * @return The range where the previous match is. It is null if no previous match has been found. */ - findPreviousMatch(searchString: string, searchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string | null, captureMatches: boolean): FindMatch; + findPreviousMatch(searchString: string, searchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string | null, captureMatches: boolean): FindMatch | null; /** * Get the language associated with this model. */ @@ -1662,7 +1663,7 @@ declare namespace monaco.editor { * @param position The position to look for a word. * @return The word under or besides `position`. Might be null. */ - getWordAtPosition(position: IPosition): IWordAtPosition; + getWordAtPosition(position: IPosition): IWordAtPosition | null; /** * Get the word under or besides `position` trimmed to `position`.column * @param position The position to look for a word. @@ -1685,13 +1686,13 @@ declare namespace monaco.editor { * @param id The decoration id. * @return The decoration options or null if the decoration was not found. */ - getDecorationOptions(id: string): IModelDecorationOptions; + getDecorationOptions(id: string): IModelDecorationOptions | null; /** * Get the range associated with a decoration. * @param id The decoration id. * @return The decoration range or null if the decoration was not found. */ - getDecorationRange(id: string): Range; + getDecorationRange(id: string): Range | null; /** * Gets all the decorations for the line `lineNumber` as an array. * @param lineNumber The line number @@ -1760,7 +1761,7 @@ declare namespace monaco.editor { * @param cursorStateComputer A callback that can compute the resulting cursors state after the edit operations have been executed. * @return The cursor state returned by the `cursorStateComputer`. */ - pushEditOperations(beforeCursorState: Selection[], editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer): Selection[]; + pushEditOperations(beforeCursorState: Selection[], editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer): Selection[] | null; /** * Change the end of line sequence. This is the preferred way of * changing the eol sequence. This will land on the undo stack. @@ -1824,7 +1825,7 @@ declare namespace monaco.editor { * @param range The range to replace (delete). May be empty to represent a simple insert. * @param text The text to replace with. May be null to represent a simple delete. */ - addEditOperation(range: Range, text: string): void; + addEditOperation(range: Range, text: string | null): void; /** * Add a new edit operation (a replace operation). * The inverse edits will be accessible in `ICursorStateComputerData.getInverseEditOperations()` @@ -1936,7 +1937,7 @@ declare namespace monaco.editor { * A line change */ export interface ILineChange extends IChange { - readonly charChanges: ICharChange[]; + readonly charChanges: ICharChange[] | undefined; } export interface INewScrollPosition { @@ -3221,7 +3222,7 @@ declare namespace monaco.editor { readonly rulers: number[]; readonly ariaLabel: string; readonly renderLineNumbers: RenderLineNumbersType; - readonly renderCustomLineNumbers: (lineNumber: number) => string; + readonly renderCustomLineNumbers: ((lineNumber: number) => string) | null; readonly selectOnLineNumbers: boolean; readonly glyphMargin: boolean; readonly revealHorizontalRightPadding: number; diff --git a/src/vs/platform/actions/common/menu.ts b/src/vs/platform/actions/common/menu.ts index eb36c7f8699..d90656347f8 100644 --- a/src/vs/platform/actions/common/menu.ts +++ b/src/vs/platform/actions/common/menu.ts @@ -5,7 +5,6 @@ import { Event, Emitter } from 'vs/base/common/event'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { TPromise } from 'vs/base/common/winjs.base'; import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { MenuId, MenuRegistry, MenuItemAction, IMenu, IMenuItem, IMenuActionOptions, ISubmenuItem, SubmenuItemAction, isIMenuItem } from 'vs/platform/actions/common/actions'; import { ICommandService } from 'vs/platform/commands/common/commands'; @@ -20,7 +19,7 @@ export class Menu implements IMenu { constructor( id: MenuId, - startupSignal: TPromise, + startupSignal: Thenable, @ICommandService private readonly _commandService: ICommandService, @IContextKeyService private readonly _contextKeyService: IContextKeyService ) { diff --git a/src/vs/platform/commands/common/commands.ts b/src/vs/platform/commands/common/commands.ts index 14b29901647..1a6f04b2363 100644 --- a/src/vs/platform/commands/common/commands.ts +++ b/src/vs/platform/commands/common/commands.ts @@ -18,7 +18,7 @@ export interface ICommandEvent { export interface ICommandService { _serviceBrand: any; onWillExecuteCommand: Event; - executeCommand(commandId: string, ...args: any[]): Promise; + executeCommand(commandId: string, ...args: any[]): Promise; } export interface ICommandsMap { @@ -45,7 +45,7 @@ export interface ICommandRegistry { registerCommand(id: string, command: ICommandHandler): IDisposable; registerCommand(command: ICommand): IDisposable; registerCommandAlias(oldId: string, newId: string): IDisposable; - getCommand(id: string): ICommand; + getCommand(id: string): ICommand | undefined; getCommands(): ICommandsMap; } @@ -68,7 +68,7 @@ export const CommandsRegistry: ICommandRegistry = new class implements ICommandR // add argument validation if rich command metadata is provided if (idOrCommand.description) { - const constraints: TypeConstraint[] = []; + const constraints: (TypeConstraint | undefined)[] = []; for (let arg of idOrCommand.description.args) { constraints.push(arg.constraint); } @@ -104,7 +104,7 @@ export const CommandsRegistry: ICommandRegistry = new class implements ICommandR }); } - getCommand(id: string): ICommand { + getCommand(id: string): ICommand | undefined { const list = this._commands.get(id); if (!list || list.isEmpty()) { return undefined; @@ -115,7 +115,7 @@ export const CommandsRegistry: ICommandRegistry = new class implements ICommandR getCommands(): ICommandsMap { const result: ICommandsMap = Object.create(null); this._commands.forEach((value, key) => { - result[key] = this.getCommand(key); + result[key] = this.getCommand(key)!; }); return result; } @@ -124,7 +124,7 @@ export const CommandsRegistry: ICommandRegistry = new class implements ICommandR export const NullCommandService: ICommandService = { _serviceBrand: undefined, onWillExecuteCommand: () => ({ dispose: () => { } }), - executeCommand() { - return Promise.resolve(undefined); + executeCommand() { + return Promise.resolve(undefined); } }; diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index ade76fc5ec0..78ac8b14af8 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -190,7 +190,7 @@ export class DefaultConfigurationModel extends ConfigurationModel { export class ConfigurationModelParser { - private _configurationModel: ConfigurationModel = null; + private _configurationModel: ConfigurationModel | null = null; private _parseErrors: any[] = []; constructor(protected readonly _name: string) { } @@ -211,7 +211,7 @@ export class ConfigurationModelParser { protected parseContent(content: string): any { let raw: any = {}; - let currentProperty: string = null; + let currentProperty: string | null = null; let currentParent: any = []; let previousParents: any[] = []; let parseErrors: json.ParseError[] = []; @@ -276,7 +276,7 @@ export class ConfigurationModelParser { export class Configuration { - private _workspaceConsolidatedConfiguration: ConfigurationModel = null; + private _workspaceConsolidatedConfiguration: ConfigurationModel | null = null; private _foldersConsolidatedConfigurations: ResourceMap = new ResourceMap(); constructor( diff --git a/src/vs/platform/contextkey/browser/contextKeyService.ts b/src/vs/platform/contextkey/browser/contextKeyService.ts index 7bd1144931a..d3f6a029386 100644 --- a/src/vs/platform/contextkey/browser/contextKeyService.ts +++ b/src/vs/platform/contextkey/browser/contextKeyService.ts @@ -142,9 +142,9 @@ class ContextKey implements IContextKey { private _parent: AbstractContextKeyService; private _key: string; - private _defaultValue: T; + private _defaultValue: T | undefined; - constructor(parent: AbstractContextKeyService, key: string, defaultValue: T) { + constructor(parent: AbstractContextKeyService, key: string, defaultValue: T | undefined) { this._parent = parent; this._key = key; this._defaultValue = defaultValue; @@ -200,7 +200,7 @@ export abstract class AbstractContextKeyService implements IContextKeyService { abstract dispose(): void; - public createKey(key: string, defaultValue: T): IContextKey { + public createKey(key: string, defaultValue: T | undefined): IContextKey { return new ContextKey(this, key, defaultValue); } @@ -278,7 +278,7 @@ export class ContextKeyService extends AbstractContextKeyService implements ICon this._toDispose.push(myContext); // Uncomment this to see the contexts continuously logged - // let lastLoggedValue: string = null; + // let lastLoggedValue: string | null = null; // setInterval(() => { // let values = Object.keys(this._contexts).map((key) => this._contexts[key]); // let logValue = values.map(v => JSON.stringify(v._value, null, '\t')).join('\n'); diff --git a/src/vs/platform/contextkey/common/contextkey.ts b/src/vs/platform/contextkey/common/contextkey.ts index 678c3d109d0..eb9acf5392d 100644 --- a/src/vs/platform/contextkey/common/contextkey.ts +++ b/src/vs/platform/contextkey/common/contextkey.ts @@ -42,7 +42,7 @@ export abstract class ContextKeyExpr { return new ContextKeyAndExpr(expr); } - public static deserialize(serialized: string): ContextKeyExpr { + public static deserialize(serialized: string): ContextKeyExpr | null { if (!serialized) { return null; } @@ -96,7 +96,7 @@ export abstract class ContextKeyExpr { return serializedValue; } - private static _deserializeRegexValue(serializedValue: string): RegExp { + private static _deserializeRegexValue(serializedValue: string): RegExp | null { if (isFalsyOrWhitespace(serializedValue)) { console.warn('missing regexp-value for =~-expression'); @@ -123,7 +123,7 @@ export abstract class ContextKeyExpr { public abstract getType(): ContextKeyExprType; public abstract equals(other: ContextKeyExpr): boolean; public abstract evaluate(context: IContext): boolean; - public abstract normalize(): ContextKeyExpr; + public abstract normalize(): ContextKeyExpr | null; public abstract serialize(): string; public abstract keys(): string[]; } @@ -358,7 +358,7 @@ export class ContextKeyNotExpr implements ContextKeyExpr { export class ContextKeyRegexExpr implements ContextKeyExpr { - constructor(private key: string, private regexp: RegExp) { + constructor(private key: string, private regexp: RegExp | null) { // } @@ -373,11 +373,12 @@ export class ContextKeyRegexExpr implements ContextKeyExpr { if (this.key > other.key) { return 1; } - const source = this.regexp ? this.regexp.source : undefined; - if (source < other.regexp.source) { + const thisSource = this.regexp ? this.regexp.source : ''; + const otherSource = other.regexp ? other.regexp.source : ''; + if (thisSource < otherSource) { return -1; } - if (source > other.regexp.source) { + if (thisSource > otherSource) { return 1; } return 0; @@ -385,8 +386,9 @@ export class ContextKeyRegexExpr implements ContextKeyExpr { public equals(other: ContextKeyExpr): boolean { if (other instanceof ContextKeyRegexExpr) { - const source = this.regexp ? this.regexp.source : undefined; - return (this.key === other.key && source === other.regexp.source); + const thisSource = this.regexp ? this.regexp.source : ''; + const otherSource = other.regexp ? other.regexp.source : ''; + return (this.key === other.key && thisSource === otherSource); } return false; } @@ -451,7 +453,7 @@ export class ContextKeyAndExpr implements ContextKeyExpr { if (arr) { for (let i = 0, len = arr.length; i < len; i++) { - let e = arr[i]; + let e: ContextKeyExpr | null = arr[i]; if (!e) { continue; } @@ -475,7 +477,7 @@ export class ContextKeyAndExpr implements ContextKeyExpr { return expr; } - public normalize(): ContextKeyExpr { + public normalize(): ContextKeyExpr | null { if (this.expr.length === 0) { return null; } @@ -492,7 +494,11 @@ export class ContextKeyAndExpr implements ContextKeyExpr { return ''; } if (this.expr.length === 1) { - return this.normalize().serialize(); + const normalized = this.normalize(); + if (!normalized) { + return ''; + } + return normalized.serialize(); } return this.expr.map(e => e.serialize()).join(' && '); } @@ -508,9 +514,9 @@ export class ContextKeyAndExpr implements ContextKeyExpr { export class RawContextKey extends ContextKeyDefinedExpr { - private _defaultValue: T; + private _defaultValue: T | undefined; - constructor(key: string, defaultValue: T) { + constructor(key: string, defaultValue: T | undefined) { super(key); this._defaultValue = defaultValue; } @@ -569,7 +575,7 @@ export interface IContextKeyService { dispose(): void; onDidChangeContext: Event; - createKey(key: string, defaultValue: T): IContextKey; + createKey(key: string, defaultValue: T | undefined): IContextKey; contextMatchesRules(rules: ContextKeyExpr): boolean; getContextKeyValue(key: string): T; diff --git a/src/vs/platform/extensionManagement/node/extensionManagementIpc.ts b/src/vs/platform/extensionManagement/node/extensionManagementIpc.ts index 80223ea024d..43931e9a68c 100644 --- a/src/vs/platform/extensionManagement/node/extensionManagementIpc.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementIpc.ts @@ -107,7 +107,7 @@ export class ExtensionManagementChannelClient implements IExtensionManagementSer return Promise.resolve(this.channel.call('reinstallFromGallery', [this._transformOutgoing(extension)])); } - getInstalled(type: LocalExtensionType = null): Promise { + getInstalled(type: LocalExtensionType | null = null): Promise { return Promise.resolve(this.channel.call('getInstalled', [type])) .then(extensions => extensions.map(extension => this._transformIncoming(extension))); } diff --git a/src/vs/platform/extensionManagement/node/extensionManagementService.ts b/src/vs/platform/extensionManagement/node/extensionManagementService.ts index 478f253a733..7e92f58fc62 100644 --- a/src/vs/platform/extensionManagement/node/extensionManagementService.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementService.ts @@ -713,7 +713,7 @@ export class ExtensionManagementService extends Disposable implements IExtension this._onDidUninstallExtension.fire({ identifier: extension.identifier, error: errorcode }); } - getInstalled(type: LocalExtensionType = null): Promise { + getInstalled(type: LocalExtensionType | null = null): Promise { const promises = []; if (type === null || type === LocalExtensionType.System) { @@ -852,7 +852,7 @@ export class ExtensionManagementService extends Disposable implements IExtension private async withUninstalledExtensions(fn: (uninstalled: { [id: string]: boolean; }) => T): Promise { return await this.uninstalledFileLimiter.queue(() => { - let result: T = null; + let result: T | null = null; return pfs.readFile(this.uninstalledPath, 'utf8') .then(null, err => err.code === 'ENOENT' ? Promise.resolve('{}') : Promise.reject(err)) .then<{ [id: string]: boolean }>(raw => { try { return JSON.parse(raw); } catch (e) { return {}; } }) diff --git a/src/vs/platform/files/common/files.ts b/src/vs/platform/files/common/files.ts index 49c461690f2..514c81e594e 100644 --- a/src/vs/platform/files/common/files.ts +++ b/src/vs/platform/files/common/files.ts @@ -236,7 +236,7 @@ export class FileOperationEvent { return this._resource; } - get target(): IFileStat { + get target(): IFileStat | undefined { return this._target; } @@ -484,12 +484,15 @@ export interface IStringStream { * Will return null when finished. */ export interface ITextSnapshot { - read(): string; + read(): string | null; } export class StringSnapshot implements ITextSnapshot { - constructor(private _value: string) { } - read(): string { + private _value: string | null; + constructor(value: string) { + this._value = value; + } + read(): string | null { let ret = this._value; this._value = null; return ret; @@ -500,7 +503,7 @@ export class StringSnapshot implements ITextSnapshot { */ export function snapshotToString(snapshot: ITextSnapshot): string { const chunks: string[] = []; - let chunk: string; + let chunk: string | null; while (typeof (chunk = snapshot.read()) === 'string') { chunks.push(chunk); } diff --git a/src/vs/platform/integrity/node/integrityServiceImpl.ts b/src/vs/platform/integrity/node/integrityServiceImpl.ts index fe0e58cf7f3..cabc97a58f1 100644 --- a/src/vs/platform/integrity/node/integrityServiceImpl.ts +++ b/src/vs/platform/integrity/node/integrityServiceImpl.ts @@ -96,7 +96,8 @@ export class IntegrityServiceImpl implements IIntegrityService { isSecondary: true, run: () => this._storage.set({ dontShowPrompt: true, commit: product.commit }) } - ] + ], + { sticky: true } ); } diff --git a/src/vs/platform/keybinding/common/keybindingResolver.ts b/src/vs/platform/keybinding/common/keybindingResolver.ts index ad7cf6bfa84..82b335bad45 100644 --- a/src/vs/platform/keybinding/common/keybindingResolver.ts +++ b/src/vs/platform/keybinding/common/keybindingResolver.ts @@ -230,7 +230,7 @@ export class KeybindingResolver { } public resolve(context: IContext, currentChord: string, keypress: string): IResolveResult { - let lookupMap: ResolvedKeybindingItem[] = null; + let lookupMap: ResolvedKeybindingItem[] | null = null; if (currentChord !== null) { // Fetch all chord bindings for `currentChord` diff --git a/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts b/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts index 0e881d97d50..80306936a52 100644 --- a/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts +++ b/src/vs/platform/keybinding/test/common/abstractKeybindingService.test.ts @@ -16,7 +16,7 @@ import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKe import { OS } from 'vs/base/common/platform'; import { IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding'; import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; -import { INotificationService, NoOpNotification, INotification, IPromptChoice } from 'vs/platform/notification/common/notification'; +import { INotificationService, NoOpNotification, INotification, IPromptChoice, IPromptOptions } from 'vs/platform/notification/common/notification'; function createContext(ctx: any) { return { @@ -83,11 +83,11 @@ suite('AbstractKeybindingService', () => { } let createTestKeybindingService: (items: ResolvedKeybindingItem[], contextValue?: any) => TestKeybindingService = null; - let currentContextValue: IContext = null; + let currentContextValue: IContext | null = null; let executeCommandCalls: { commandId: string; args: any[]; }[] = null; let showMessageCalls: { sev: Severity, message: any; }[] = null; - let statusMessageCalls: string[] = null; - let statusMessageCallsDisposed: string[] = null; + let statusMessageCalls: string[] | null = null; + let statusMessageCallsDisposed: string[] | null = null; setup(() => { executeCommandCalls = []; @@ -140,7 +140,7 @@ suite('AbstractKeybindingService', () => { showMessageCalls.push({ sev: Severity.Error, message }); return new NoOpNotification(); }, - prompt(severity: Severity, message: string, choices: IPromptChoice[], onCancel?: () => void) { + prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions) { throw new Error('not implemented'); } }; @@ -173,7 +173,7 @@ suite('AbstractKeybindingService', () => { statusMessageCallsDisposed = null; }); - function kbItem(keybinding: number, command: string, when: ContextKeyExpr = null): ResolvedKeybindingItem { + function kbItem(keybinding: number, command: string, when: ContextKeyExpr | null = null): ResolvedKeybindingItem { const resolvedKeybinding = (keybinding !== 0 ? new USLayoutResolvedKeybinding(createKeybinding(keybinding, OS), OS) : null); return new ResolvedKeybindingItem( resolvedKeybinding, diff --git a/src/vs/platform/localizations/node/localizations.ts b/src/vs/platform/localizations/node/localizations.ts index 46bd114b4cf..d08a4100a2f 100644 --- a/src/vs/platform/localizations/node/localizations.ts +++ b/src/vs/platform/localizations/node/localizations.ts @@ -170,7 +170,7 @@ class LanguagePacksCache extends Disposable { private withLanguagePacks(fn: (languagePacks: { [language: string]: ILanguagePack }) => T = () => null): TPromise { return this.languagePacksFileLimiter.queue(() => { - let result: T = null; + let result: T | null = null; return pfs.readFile(this.languagePacksFilePath, 'utf8') .then(null, err => err.code === 'ENOENT' ? TPromise.as('{}') : TPromise.wrapError(err)) .then<{ [language: string]: ILanguagePack }>(raw => { try { return JSON.parse(raw); } catch (e) { return {}; } }) diff --git a/src/vs/platform/menubar/electron-main/menubar.ts b/src/vs/platform/menubar/electron-main/menubar.ts index e0912eb4cce..af8317230f0 100644 --- a/src/vs/platform/menubar/electron-main/menubar.ts +++ b/src/vs/platform/menubar/electron-main/menubar.ts @@ -652,8 +652,6 @@ export class Menubar { options['role'] = 'copy'; } else if (commandId === 'editor.action.clipboardPasteAction') { options['role'] = 'paste'; - } else if (commandId === 'editor.action.selectAll') { - options['role'] = 'selectAll'; } // Add context aware click handlers for special case menu items diff --git a/src/vs/platform/notification/common/notification.ts b/src/vs/platform/notification/common/notification.ts index 61a784c4f4d..55d363f77cb 100644 --- a/src/vs/platform/notification/common/notification.ts +++ b/src/vs/platform/notification/common/notification.ts @@ -45,6 +45,12 @@ export interface INotification { * this usecase and much easier to use! */ actions?: INotificationActions; + + /** + * Sticky notifications are not automatically removed after a certain timeout. By + * default, notifications with primary actions and severity error are always sticky. + */ + sticky?: boolean; } export interface INotificationActions { @@ -147,6 +153,22 @@ export interface IPromptChoice { run: () => void; } +export interface IPromptOptions { + + /** + * Sticky prompts are not automatically removed after a certain timeout. + * + * Note: Prompts of severity ERROR are always sticky. + */ + sticky?: boolean; + + /** + * Will be called if the user closed the notification without picking + * any of the provided choices. + */ + onCancel?: () => void; +} + /** * A service to bring up notifications and non-modal prompts. * @@ -195,7 +217,7 @@ export interface INotificationService { * * @returns a handle on the notification to e.g. hide it or update message, buttons, etc. */ - prompt(severity: Severity, message: string, choices: IPromptChoice[], onCancel?: () => void): INotificationHandle; + prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle; } export class NoOpNotification implements INotificationHandle { diff --git a/src/vs/platform/notification/test/common/testNotificationService.ts b/src/vs/platform/notification/test/common/testNotificationService.ts index 78f745675b3..4385727a2ec 100644 --- a/src/vs/platform/notification/test/common/testNotificationService.ts +++ b/src/vs/platform/notification/test/common/testNotificationService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { INotificationService, INotificationHandle, NoOpNotification, Severity, INotification, IPromptChoice } from 'vs/platform/notification/common/notification'; +import { INotificationService, INotificationHandle, NoOpNotification, Severity, INotification, IPromptChoice, IPromptOptions } from 'vs/platform/notification/common/notification'; export class TestNotificationService implements INotificationService { @@ -27,7 +27,7 @@ export class TestNotificationService implements INotificationService { return TestNotificationService.NO_OP; } - public prompt(severity: Severity, message: string, choices: IPromptChoice[], onCancel?: () => void): INotificationHandle { + public prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle { return TestNotificationService.NO_OP; } } \ No newline at end of file diff --git a/src/vs/platform/search/common/replace.ts b/src/vs/platform/search/common/replace.ts index 647b5d51a0d..d5100b6fc7d 100644 --- a/src/vs/platform/search/common/replace.ts +++ b/src/vs/platform/search/common/replace.ts @@ -93,7 +93,7 @@ export class ReplacePattern { } let nextChCode = replaceString.charCodeAt(i); - let replaceWithCharacter: string = null; + let replaceWithCharacter: string | null = null; switch (nextChCode) { case CharCode.Backslash: @@ -127,7 +127,7 @@ export class ReplacePattern { } let nextChCode = replaceString.charCodeAt(i); - let replaceWithCharacter: string = null; + let replaceWithCharacter: string | null = null; switch (nextChCode) { case CharCode.Digit0: diff --git a/src/vs/platform/search/common/search.ts b/src/vs/platform/search/common/search.ts index 8b4bde818b0..0bf434f5477 100644 --- a/src/vs/platform/search/common/search.ts +++ b/src/vs/platform/search/common/search.ts @@ -306,7 +306,7 @@ export interface ISearchConfiguration extends IFilesConfiguration { }; } -export function getExcludes(configuration: ISearchConfiguration): glob.IExpression { +export function getExcludes(configuration: ISearchConfiguration): glob.IExpression | undefined { const fileExcludes = configuration && configuration.files && configuration.files.exclude; const searchExcludes = configuration && configuration.search && configuration.search.exclude; @@ -337,7 +337,7 @@ export function pathIncludedInQuery(query: ISearchQuery, fsPath: string): boolea // If searchPaths are being used, the extra file must be in a subfolder and match the pattern, if present if (query.usingSearchPaths) { - return query.folderQueries.every(fq => { + return !!query.folderQueries && query.folderQueries.every(fq => { const searchPath = fq.folder.fsPath; if (paths.isEqualOrParent(fsPath, searchPath)) { return !fq.includePattern || !!glob.match(fq.includePattern, fsPath); diff --git a/src/vs/platform/state/node/stateService.ts b/src/vs/platform/state/node/stateService.ts index 45d5792cdb6..57c369a9275 100644 --- a/src/vs/platform/state/node/stateService.ts +++ b/src/vs/platform/state/node/stateService.ts @@ -13,7 +13,7 @@ import { ILogService } from 'vs/platform/log/common/log'; export class FileStorage { - private database: object = null; + private database: object | null = null; constructor(private dbPath: string, private onError: (error) => void) { } diff --git a/src/vs/platform/theme/common/colorRegistry.ts b/src/vs/platform/theme/common/colorRegistry.ts index cebda41a9c4..9a185a68f15 100644 --- a/src/vs/platform/theme/common/colorRegistry.ts +++ b/src/vs/platform/theme/common/colorRegistry.ts @@ -19,18 +19,18 @@ export interface ColorContribution { readonly description: string; readonly defaults: ColorDefaults; readonly needsTransparency: boolean; - readonly deprecationMessage: string; + readonly deprecationMessage: string | undefined; } export interface ColorFunction { - (theme: ITheme): Color; + (theme: ITheme): Color | null; } export interface ColorDefaults { - light: ColorValue; - dark: ColorValue; - hc: ColorValue; + light: ColorValue | null; + dark: ColorValue | null; + hc: ColorValue | null; } /** @@ -61,7 +61,7 @@ export interface IColorRegistry { /** * Gets the default color of the given id */ - resolveDefaultColor(id: ColorIdentifier, theme: ITheme): Color; + resolveDefaultColor(id: ColorIdentifier, theme: ITheme): Color | null; /** * JSON schema for an object to assign color values to one of the color contrbutions. @@ -93,9 +93,9 @@ class ColorRegistry implements IColorRegistry { if (deprecationMessage) { propertySchema.deprecationMessage = deprecationMessage; } - this.colorSchema.properties[id] = propertySchema; - this.colorReferenceSchema.enum.push(id); - this.colorReferenceSchema.enumDescriptions.push(description); + this.colorSchema.properties![id] = propertySchema; + this.colorReferenceSchema.enum!.push(id); + this.colorReferenceSchema.enumDescriptions!.push(description); return id; } @@ -103,7 +103,7 @@ class ColorRegistry implements IColorRegistry { return Object.keys(this.colorsById).map(id => this.colorsById[id]); } - public resolveDefaultColor(id: ColorIdentifier, theme: ITheme): Color { + public resolveDefaultColor(id: ColorIdentifier, theme: ITheme): Color | null { let colorDesc = this.colorsById[id]; if (colorDesc && colorDesc.defaults) { let colorValue = colorDesc.defaults[theme.type]; @@ -412,7 +412,7 @@ function lessProminent(colorValue: ColorValue, backgroundColorValue: ColorValue, /** * @param colorValue Resolve a color value in the context of a theme */ -function resolveColorValue(colorValue: ColorValue, theme: ITheme): Color { +function resolveColorValue(colorValue: ColorValue | null, theme: ITheme): Color | null { if (colorValue === null) { return null; } else if (typeof colorValue === 'string') { diff --git a/src/vs/platform/update/electron-main/updateService.win32.ts b/src/vs/platform/update/electron-main/updateService.win32.ts index 26ce1ea7c7f..9bb827b2b9c 100644 --- a/src/vs/platform/update/electron-main/updateService.win32.ts +++ b/src/vs/platform/update/electron-main/updateService.win32.ts @@ -194,7 +194,7 @@ export class Win32UpdateService extends AbstractUpdateService { return this.cachePath.then(cachePath => path.join(cachePath, `CodeSetup-${product.quality}-${version}.exe`)); } - private cleanup(exceptVersion: string = null): Promise { + private cleanup(exceptVersion: string | null = null): Promise { const filter = exceptVersion ? one => !(new RegExp(`${product.quality}-${exceptVersion}\\.exe$`).test(one)) : () => true; return this.cachePath diff --git a/src/vs/platform/windows/node/windowsIpc.ts b/src/vs/platform/windows/node/windowsIpc.ts index 963413ca3da..69af2c4132e 100644 --- a/src/vs/platform/windows/node/windowsIpc.ts +++ b/src/vs/platform/windows/node/windowsIpc.ts @@ -141,7 +141,7 @@ export class WindowsChannel implements IWindowsChannel { case 'removeFromRecentlyOpened': { let paths: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI | string)[] = arg; if (Array.isArray(paths)) { - paths = paths.map(path => URI.isUri(path) ? URI.revive(path) : path); + paths = paths.map(path => isWorkspaceIdentifier(path) || typeof path === 'string' ? path : URI.revive(path)); } return this.service.removeFromRecentlyOpened(paths); } diff --git a/src/vs/platform/workspace/common/workspace.ts b/src/vs/platform/workspace/common/workspace.ts index ef2cab484e7..dbedcbd5f6b 100644 --- a/src/vs/platform/workspace/common/workspace.ts +++ b/src/vs/platform/workspace/common/workspace.ts @@ -145,7 +145,7 @@ export class Workspace implements IWorkspace { constructor( private _id: string, folders: WorkspaceFolder[] = [], - private _configuration: URI = null, + private _configuration: URI | null = null, private _ctime?: number ) { this.folders = folders; diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 18714234e9d..e7c70656a60 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -14,8 +14,8 @@ declare module 'vscode' { //#region Joh - clipboard https://github.com/Microsoft/vscode/issues/217 export interface Clipboard { - readText(): Promise; - writeText(value: string): Promise; + readText(): Thenable; + writeText(value: string): Thenable; } export namespace env { diff --git a/src/vs/workbench/api/electron-browser/mainThreadComments.ts b/src/vs/workbench/api/electron-browser/mainThreadComments.ts index ecc36c17074..0b499e49b40 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadComments.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadComments.ts @@ -26,6 +26,7 @@ export class MainThreadComments extends Disposable implements MainThreadComments private _workspaceProviders = new Map(); private _firstSessionStart: boolean; + private _visibleModels: { [key /** editor widget id */: string]: string /** model id */ }; constructor( extHostContext: IExtHostContext, @IEditorService private _editorService: IEditorService, @@ -36,9 +37,35 @@ export class MainThreadComments extends Disposable implements MainThreadComments super(); this._disposables = []; this._firstSessionStart = true; + this._visibleModels = {}; this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostComments); - this._disposables.push(this._editorService.onDidActiveEditorChange(e => { + this._disposables.push(this._editorService.onDidVisibleEditorsChange(e => { const editors = this.getFocusedEditors(); + const visibleEditors = this.getVisibleEditors(); + + const _visibleEditors = {}; + visibleEditors.forEach(editor => { + const id = editor.getId(); + if (editors.filter(ed => ed.getId() === id).length > 0) { + // it's an active editor, we are going to update this editor's comments anyways + } else { + if (this._visibleModels[id]) { + // it's the same active editor, but we may want to check if the model is still the same + let modelId = editor.getModel().getModeId(); + if (modelId !== this._visibleModels[id]) { + editors.push(editor); + } + } else { + // update + editors.push(editor); + } + } + + _visibleEditors[id] = editor.getModel().getModeId(); + }); + + this._visibleModels = _visibleEditors; + if (!editors || !editors.length) { return; } @@ -119,12 +146,21 @@ export class MainThreadComments extends Disposable implements MainThreadComments this._commentService.updateComments(event); } - dispose(): void { - this._disposables = dispose(this._disposables); - this._workspaceProviders.forEach(value => dispose(value)); - this._workspaceProviders.clear(); - this._documentProviders.forEach(value => dispose(value)); - this._documentProviders.clear(); + getVisibleEditors(): ICodeEditor[] { + let ret = []; + + this._editorService.visibleControls.forEach(control => { + if (isCodeEditor(control.getControl())) { + ret.push(control.getControl() as ICodeEditor); + } + + if (isDiffEditor(control.getControl())) { + let diffEditor = control.getControl() as IDiffEditor; + ret.push(diffEditor.getOriginalEditor(), diffEditor.getModifiedEditor()); + } + }); + + return ret; } getFocusedEditors(): ICodeEditor[] { @@ -163,4 +199,13 @@ export class MainThreadComments extends Disposable implements MainThreadComments } return result; } + + dispose(): void { + this._disposables = dispose(this._disposables); + this._workspaceProviders.forEach(value => dispose(value)); + this._workspaceProviders.clear(); + this._documentProviders.forEach(value => dispose(value)); + this._documentProviders.clear(); + this._visibleModels = {}; + } } diff --git a/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts b/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts index f41a7b9caf0..c5e3b642163 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts @@ -5,7 +5,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { URI as uri } from 'vs/base/common/uri'; -import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint, IBreakpointData, ITerminalSettings, IDebugAdapter, IDebugAdapterProvider, IDebugSession, DEBUG_SCHEME } from 'vs/workbench/parts/debug/common/debug'; +import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint, IBreakpointData, ITerminalSettings, IDebugAdapter, IDebugAdapterProvider, IDebugSession } from 'vs/workbench/parts/debug/common/debug'; import { TPromise } from 'vs/base/common/winjs.base'; import { ExtHostContext, ExtHostDebugServiceShape, MainThreadDebugServiceShape, DebugSessionUUID, MainContext, @@ -302,7 +302,7 @@ class ExtensionHostDebugAdapter extends AbstractDebugAdapter { if (paths.isAbsolute(source.path)) { (source).path = uri.file(source.path); } else { - (source).path = uri.parse(`${DEBUG_SCHEME}:${source.path}`); + (source).path = uri.parse(source.path); } }); diff --git a/src/vs/workbench/api/electron-browser/mainThreadDocumentsAndEditors.ts b/src/vs/workbench/api/electron-browser/mainThreadDocumentsAndEditors.ts index 182ee957f5d..6ba27704f66 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadDocumentsAndEditors.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadDocumentsAndEditors.ts @@ -246,7 +246,7 @@ class MainThreadDocumentAndEditorStateComputer { // editor: only take those that have a not too large model const editors = new Map(); - let activeEditor: string = null; + let activeEditor: string | null = null; for (const editor of this._codeEditorService.listCodeEditors()) { if (editor.isSimpleWidget) { diff --git a/src/vs/workbench/api/electron-browser/mainThreadEditor.ts b/src/vs/workbench/api/electron-browser/mainThreadEditor.ts index 8f59fa24a38..2b7e39dd957 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadEditor.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadEditor.ts @@ -32,7 +32,7 @@ export class MainThreadTextEditorProperties { } private static _readSelectionsFromCodeEditor(previousProperties: MainThreadTextEditorProperties, codeEditor: ICodeEditor): Selection[] { - let result: Selection[] = null; + let result: Selection[] | null = null; if (codeEditor) { result = codeEditor.getSelections(); } diff --git a/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts b/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts index 2f9bbc5ae56..a3363290ea8 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadSaveParticipant.ts @@ -86,7 +86,7 @@ class TrimWhitespaceParticipant implements ISaveParticipantParticipant { } function findEditor(model: ITextModel, codeEditorService: ICodeEditorService): ICodeEditor { - let candidate: ICodeEditor = null; + let candidate: ICodeEditor | null = null; if (model.isAttachedToEditor()) { for (const editor of codeEditorService.listCodeEditors()) { diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index f625545fdf4..2b90e28cc11 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -97,7 +97,7 @@ export function createApiFactory( extHostLogService: ExtHostLogService ): IExtensionApiFactory { - let schemeTransformer: ISchemeTransformer = null; + let schemeTransformer: ISchemeTransformer | null = null; // Addressable instances rpcProtocol.set(ExtHostContext.ExtHostLogService, extHostLogService); diff --git a/src/vs/workbench/api/node/extHostDebugService.ts b/src/vs/workbench/api/node/extHostDebugService.ts index 20d39cc8805..ba28777061f 100644 --- a/src/vs/workbench/api/node/extHostDebugService.ts +++ b/src/vs/workbench/api/node/extHostDebugService.ts @@ -360,7 +360,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { return this.getAdapterDescriptor(this._providerByType.get(config.type), sessionDto, folderUri, config).then(adapter => { - let da: AbstractDebugAdapter = undefined; + let da: AbstractDebugAdapter | undefined = undefined; switch (adapter.type) { diff --git a/src/vs/workbench/api/node/extHostExtensionService.ts b/src/vs/workbench/api/node/extHostExtensionService.ts index 58aee7c4922..94ba0a24561 100644 --- a/src/vs/workbench/api/node/extHostExtensionService.ts +++ b/src/vs/workbench/api/node/extHostExtensionService.ts @@ -407,7 +407,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { } function loadCommonJSModule(logService: ILogService, modulePath: string, activationTimesBuilder: ExtensionActivationTimesBuilder): TPromise { - let r: T = null; + let r: T | null = null; activationTimesBuilder.codeLoadingStart(); logService.info(`ExtensionService#loadCommonJSModule ${modulePath}`); try { diff --git a/src/vs/workbench/api/node/extHostTerminalService.ts b/src/vs/workbench/api/node/extHostTerminalService.ts index edfa19e3fd5..ce1df33cafd 100644 --- a/src/vs/workbench/api/node/extHostTerminalService.ts +++ b/src/vs/workbench/api/node/extHostTerminalService.ts @@ -487,7 +487,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape { } private _getTerminalObjectIndexById(array: T[], id: number): number { - let index: number = null; + let index: number | null = null; array.some((item, i) => { const thisId = item._id; if (thisId === id) { diff --git a/src/vs/workbench/api/node/extHostTextEditor.ts b/src/vs/workbench/api/node/extHostTextEditor.ts index 2f559fc4180..286e1521399 100644 --- a/src/vs/workbench/api/node/extHostTextEditor.ts +++ b/src/vs/workbench/api/node/extHostTextEditor.ts @@ -76,7 +76,7 @@ export class TextEditorEdit { } replace(location: Position | Range | Selection, value: string): void { - let range: Range = null; + let range: Range | null = null; if (location instanceof Position) { range = new Range(location, location); @@ -94,7 +94,7 @@ export class TextEditorEdit { } delete(location: Range | Selection): void { - let range: Range = null; + let range: Range | null = null; if (location instanceof Range) { range = location; diff --git a/src/vs/workbench/api/node/extHostTreeViews.ts b/src/vs/workbench/api/node/extHostTreeViews.ts index df7bea58fbe..9614729d309 100644 --- a/src/vs/workbench/api/node/extHostTreeViews.ts +++ b/src/vs/workbench/api/node/extHostTreeViews.ts @@ -122,7 +122,7 @@ class ExtHostTreeView extends Disposable { private static LABEL_HANDLE_PREFIX = '0'; private static ID_HANDLE_PREFIX = '1'; - private roots: TreeNode[] = null; + private roots: TreeNode[] | null = null; private elements: Map = new Map(); private nodes: Map = new Map(); diff --git a/src/vs/workbench/browser/parts/activitybar/media/ellipsis-global.svg b/src/vs/workbench/browser/parts/activitybar/media/ellipsis-global.svg index 5df227c5829..ac92573729a 100644 --- a/src/vs/workbench/browser/parts/activitybar/media/ellipsis-global.svg +++ b/src/vs/workbench/browser/parts/activitybar/media/ellipsis-global.svg @@ -1 +1 @@ -Ellipsis_32x \ No newline at end of file + \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index c198f724c95..f9e53f434e2 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -24,7 +24,7 @@ import { IProgressService } from 'vs/platform/progress/common/progress'; import { ProgressService } from 'vs/workbench/services/progress/browser/progressService'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { localize } from 'vs/nls'; -import { isPromiseCanceledError, isErrorWithActions, IErrorWithActions } from 'vs/base/common/errors'; +import { isPromiseCanceledError } from 'vs/base/common/errors'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { Severity, INotificationService, INotificationActions } from 'vs/platform/notification/common/notification'; import { toErrorMessage } from 'vs/base/common/errorMessage'; @@ -44,6 +44,7 @@ import { IMenuService, MenuId, IMenu } from 'vs/platform/actions/common/actions' import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { fillInContextMenuActions } from 'vs/platform/actions/browser/menuItemActionItem'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { isErrorWithActions, IErrorWithActions } from 'vs/base/common/errorsWithActions'; export class EditorGroupView extends Themable implements IEditorGroupView { @@ -1424,7 +1425,7 @@ registerThemingParticipant((theme, collector, environment) => { const letterpress = `resources/letterpress${theme.type === 'dark' ? '-dark' : theme.type === 'hc' ? '-hc' : ''}.svg`; collector.addRule(` .monaco-workbench > .part.editor > .content .editor-group-container.empty .editor-group-letterpress { - background-image: url('${join(environment.appRoot, letterpress)}') + background-image: url('${join(environment.appRoot, letterpress).replace(/#/g, '%23')}') } `); diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index 6f9fb065fbc..e2917c8fab6 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -512,7 +512,8 @@ export class EditorStatus implements IStatusbarItem { run: () => { this.configurationService.updateValue('editor.accessibilitySupport', 'off', ConfigurationTarget.USER); } - }] + }], + { sticky: true } ); once(this.screenReaderNotification.onDidClose)(() => { @@ -976,7 +977,7 @@ export class ChangeModeAction extends Action { } // Find mode - let mode: TPromise; + let mode: Promise; if (pick === autoDetectMode) { mode = this.modeService.getOrCreateModeByFilepathOrFirstLine(toResource(activeEditor, { supportSideBySide: true }).fsPath, textModel.getLineContent(1)); } else { diff --git a/src/vs/workbench/browser/parts/editor/rangeDecorations.ts b/src/vs/workbench/browser/parts/editor/rangeDecorations.ts index 01b87948707..7bee04f8a7d 100644 --- a/src/vs/workbench/browser/parts/editor/rangeDecorations.ts +++ b/src/vs/workbench/browser/parts/editor/rangeDecorations.ts @@ -21,8 +21,8 @@ export interface IRangeHighlightDecoration { export class RangeHighlightDecorations extends Disposable { - private rangeHighlightDecorationId: string = null; - private editor: ICodeEditor = null; + private rangeHighlightDecorationId: string | null = null; + private editor: ICodeEditor | null = null; private editorDisposables: IDisposable[] = []; private readonly _onHighlightRemoved: Emitter = this._register(new Emitter()); diff --git a/src/vs/workbench/browser/parts/editor/resourceViewer.ts b/src/vs/workbench/browser/parts/editor/resourceViewer.ts index 9c6c760e2ae..73805e8ea9e 100644 --- a/src/vs/workbench/browser/parts/editor/resourceViewer.ts +++ b/src/vs/workbench/browser/parts/editor/resourceViewer.ts @@ -383,7 +383,7 @@ class InlineImageView { const initialState: ImageState = InlineImageView.imageStateCache.get(cacheKey) || { scale: 'fit', offsetX: 0, offsetY: 0 }; let scale = initialState.scale; - let image: HTMLImageElement = null; + let image: HTMLImageElement | null = null; function updateScale(newScale: Scale) { if (!image || !image.parentElement) { diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index b7eefa046f0..e706996720a 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -953,13 +953,13 @@ export class TabsTitleControl extends TitleControl { } layout(dimension: Dimension): void { + this.dimension = dimension; + const activeTab = this.getTab(this.group.activeEditor); - if (!activeTab || !dimension) { + if (!activeTab || !this.dimension) { return; } - this.dimension = dimension; - // The layout of tabs can be an expensive operation because we access DOM properties // that can result in the browser doing a full page layout to validate them. To buffer // this a little bit we try at least to schedule this work on the next animation frame. diff --git a/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts b/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts index 386f1587948..6132c599e14 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts @@ -21,6 +21,7 @@ import { localize } from 'vs/nls'; import { Severity } from 'vs/platform/notification/common/notification'; import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; +import { IWindowService } from 'vs/platform/windows/common/windows'; interface INotificationToast { item: INotificationViewItem; @@ -52,6 +53,7 @@ export class NotificationsToasts extends Themable { private notificationsToastsContainer: HTMLElement; private workbenchDimensions: Dimension; + private windowHasFocus: boolean; private isNotificationsCenterVisible: boolean; private mapNotificationToToast: Map; private notificationsToastsVisibleContextKey: IContextKey; @@ -64,13 +66,16 @@ export class NotificationsToasts extends Themable { @IThemeService themeService: IThemeService, @IEditorGroupsService private editorGroupService: IEditorGroupsService, @IContextKeyService contextKeyService: IContextKeyService, - @ILifecycleService private lifecycleService: ILifecycleService + @ILifecycleService private lifecycleService: ILifecycleService, + @IWindowService private windowService: IWindowService ) { super(themeService); this.mapNotificationToToast = new Map(); this.notificationsToastsVisibleContextKey = NotificationsToastsVisibleContext.bindTo(contextKeyService); + this.windowService.isFocused().then(isFocused => this.windowHasFocus = isFocused); + this.registerListeners(); } @@ -85,6 +90,9 @@ export class NotificationsToasts extends Themable { // Update toasts on notification changes this._register(this.model.onDidNotificationChange(e => this.onDidNotificationChange(e))); }); + + // Track window focus + this.windowService.onDidChangeFocus(hasFocus => this.windowHasFocus = hasFocus); } private onDidNotificationChange(e: INotificationChangeEvent): void { @@ -177,31 +185,8 @@ export class NotificationsToasts extends Themable { this.removeToast(item); }); - // Automatically hide collapsed notifications - if (!item.expanded) { - - // Track mouse over item - let isMouseOverToast = false; - itemDisposeables.push(addDisposableListener(notificationToastContainer, EventType.MOUSE_OVER, () => isMouseOverToast = true)); - itemDisposeables.push(addDisposableListener(notificationToastContainer, EventType.MOUSE_OUT, () => isMouseOverToast = false)); - - // Install Timers - let timeoutHandle: any; - const hideAfterTimeout = () => { - timeoutHandle = setTimeout(() => { - const showsProgress = item.hasProgress() && !item.progress.state.done; - if (!notificationList.hasFocus() && !item.expanded && !isMouseOverToast && !showsProgress) { - this.removeToast(item); - } else { - hideAfterTimeout(); // push out disposal if item has focus or is expanded - } - }, NotificationsToasts.PURGE_TIMEOUT[item.severity]); - }; - - hideAfterTimeout(); - - itemDisposeables.push(toDisposable(() => clearTimeout(timeoutHandle))); - } + // Automatically purge non-sticky notifications + this.purgeNotification(item, notificationToastContainer, notificationList, itemDisposeables); // Theming this.updateStyles(); @@ -217,6 +202,35 @@ export class NotificationsToasts extends Themable { })); } + private purgeNotification(item: INotificationViewItem, notificationToastContainer: HTMLElement, notificationList: NotificationsList, disposables: IDisposable[]): void { + + // Track mouse over item + let isMouseOverToast = false; + disposables.push(addDisposableListener(notificationToastContainer, EventType.MOUSE_OVER, () => isMouseOverToast = true)); + disposables.push(addDisposableListener(notificationToastContainer, EventType.MOUSE_OUT, () => isMouseOverToast = false)); + + // Install Timers + let timeoutHandle: any; + const hideAfterTimeout = () => { + timeoutHandle = setTimeout(() => { + if ( + item.sticky || // never hide sticky notifications + notificationList.hasFocus() || // never hide notifications with focus + isMouseOverToast || // never hide notifications under mouse + !this.windowHasFocus // never hide when window has no focus + ) { + hideAfterTimeout(); + } else { + this.removeToast(item); + } + }, NotificationsToasts.PURGE_TIMEOUT[item.severity]); + }; + + hideAfterTimeout(); + + disposables.push(toDisposable(() => clearTimeout(timeoutHandle))); + } + private removeToast(item: INotificationViewItem): void { const notificationToast = this.mapNotificationToToast.get(item); let focusGroup = false; diff --git a/src/vs/workbench/browser/parts/quickinput/quickInputBox.ts b/src/vs/workbench/browser/parts/quickinput/quickInputBox.ts index ef72c944eea..0ab4759c312 100644 --- a/src/vs/workbench/browser/parts/quickinput/quickInputBox.ts +++ b/src/vs/workbench/browser/parts/quickinput/quickInputBox.ts @@ -46,7 +46,7 @@ export class QuickInputBox { this.inputBox.value = value; } - select(range: IRange = null): void { + select(range: IRange | null = null): void { this.inputBox.select(range); } diff --git a/src/vs/workbench/browser/parts/quickopen/quickopen.ts b/src/vs/workbench/browser/parts/quickopen/quickopen.ts index b83c4cd5476..b5029814e52 100644 --- a/src/vs/workbench/browser/parts/quickopen/quickopen.ts +++ b/src/vs/workbench/browser/parts/quickopen/quickopen.ts @@ -20,7 +20,7 @@ export const defaultQuickOpenContext = ContextKeyExpr.and(inQuickOpenContext, Co export const QUICKOPEN_ACTION_ID = 'workbench.action.quickOpen'; export const QUICKOPEN_ACION_LABEL = nls.localize('quickOpen', "Go to File..."); -CommandsRegistry.registerCommand(QUICKOPEN_ACTION_ID, function (accessor: ServicesAccessor, prefix: string = null) { +CommandsRegistry.registerCommand(QUICKOPEN_ACTION_ID, function (accessor: ServicesAccessor, prefix: string | null = null) { const quickOpenService = accessor.get(IQuickOpenService); return quickOpenService.show(typeof prefix === 'string' ? prefix : null).then(() => { @@ -29,7 +29,7 @@ CommandsRegistry.registerCommand(QUICKOPEN_ACTION_ID, function (accessor: Servic }); export const QUICKOPEN_FOCUS_SECONDARY_ACTION_ID = 'workbench.action.quickOpenPreviousEditor'; -CommandsRegistry.registerCommand(QUICKOPEN_FOCUS_SECONDARY_ACTION_ID, function (accessor: ServicesAccessor, prefix: string = null) { +CommandsRegistry.registerCommand(QUICKOPEN_FOCUS_SECONDARY_ACTION_ID, function (accessor: ServicesAccessor, prefix: string | null = null) { const quickOpenService = accessor.get(IQuickOpenService); return quickOpenService.show(null, { autoFocus: { autoFocusSecondEntry: true } }).then(() => { diff --git a/src/vs/workbench/common/editor/textEditorModel.ts b/src/vs/workbench/common/editor/textEditorModel.ts index 41929a278af..6ae29b06ebf 100644 --- a/src/vs/workbench/common/editor/textEditorModel.ts +++ b/src/vs/workbench/common/editor/textEditorModel.ts @@ -77,7 +77,7 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd return TPromise.as(this.doCreateTextEditorModel(value, mode, resource)); } - private doCreateTextEditorModel(value: ITextBufferFactory, mode: TPromise, resource: URI): EditorModel { + private doCreateTextEditorModel(value: ITextBufferFactory, mode: Promise, resource: URI): EditorModel { let model = resource && this.modelService.getModel(resource); if (!model) { model = this.modelService.createModel(value, mode, resource); @@ -113,7 +113,7 @@ export abstract class BaseTextEditorModel extends EditorModel implements ITextEd * * @param firstLineText optional first line of the text buffer to set the mode on. This can be used to guess a mode from content. */ - protected getOrCreateMode(modeService: IModeService, modeId: string, firstLineText?: string): TPromise { + protected getOrCreateMode(modeService: IModeService, modeId: string, firstLineText?: string): Promise { return modeService.getOrCreateMode(modeId); } diff --git a/src/vs/workbench/common/editor/untitledEditorModel.ts b/src/vs/workbench/common/editor/untitledEditorModel.ts index 2d169aeeb12..936c4732993 100644 --- a/src/vs/workbench/common/editor/untitledEditorModel.ts +++ b/src/vs/workbench/common/editor/untitledEditorModel.ts @@ -58,7 +58,7 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin this.registerListeners(); } - protected getOrCreateMode(modeService: IModeService, modeId: string, firstLineText?: string): TPromise { + protected getOrCreateMode(modeService: IModeService, modeId: string, firstLineText?: string): Promise { if (!modeId || modeId === PLAINTEXT_MODE_ID) { return modeService.getOrCreateModeByFilepathOrFirstLine(this.resource.fsPath, firstLineText); // lookup mode via resource path if the provided modeId is unspecific } diff --git a/src/vs/workbench/common/notifications.ts b/src/vs/workbench/common/notifications.ts index c02358cca0d..64f1ff2d39d 100644 --- a/src/vs/workbench/common/notifications.ts +++ b/src/vs/workbench/common/notifications.ts @@ -7,8 +7,9 @@ import { INotification, INotificationHandle, INotificationActions, INotification import { toErrorMessage } from 'vs/base/common/errorMessage'; import { Event, Emitter, once } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; -import { isPromiseCanceledError, isErrorWithActions } from 'vs/base/common/errors'; +import { isPromiseCanceledError } from 'vs/base/common/errors'; import { Action } from 'vs/base/common/actions'; +import { isErrorWithActions } from 'vs/base/common/errorsWithActions'; export interface INotificationsModel { @@ -176,6 +177,7 @@ export class NotificationsModel extends Disposable implements INotificationsMode export interface INotificationViewItem { readonly severity: Severity; + readonly sticky: boolean; readonly message: INotificationMessage; readonly source: string; readonly actions: INotificationActions; @@ -362,7 +364,7 @@ export class NotificationViewItem extends Disposable implements INotificationVie actions = { primary: notification.message.actions }; } - return new NotificationViewItem(severity, message, notification.source, actions); + return new NotificationViewItem(severity, notification.sticky, message, notification.source, actions); } private static parseNotificationMessage(input: NotificationMessage): INotificationMessage { @@ -396,11 +398,10 @@ export class NotificationViewItem extends Disposable implements INotificationVie return matchString; }); - return { raw, value: message, links, original: input }; } - private constructor(private _severity: Severity, private _message: INotificationMessage, private _source: string, actions?: INotificationActions) { + private constructor(private _severity: Severity, private _sticky: boolean, private _message: INotificationMessage, private _source: string, actions?: INotificationActions) { super(); this.setActions(actions); @@ -435,6 +436,23 @@ export class NotificationViewItem extends Disposable implements INotificationVie return this._severity; } + get sticky(): boolean { + if (this._sticky) { + return true; // explicitly sticky + } + + const hasPrimaryActions = Array.isArray(this._actions.primary) && this._actions.primary.length > 0; + if ( + (hasPrimaryActions && this._severity === Severity.Error) || // notification errors with actions are sticky + (!hasPrimaryActions && this._expanded) || // notifications that got expanded are sticky + (this._progress && !this._progress.state.done) // notifications with running progress are sticky + ) { + return true; + } + + return false; // not sticky + } + hasProgress(): boolean { return !!this._progress; } diff --git a/src/vs/workbench/electron-browser/resources.ts b/src/vs/workbench/electron-browser/resources.ts index 1fb0d516674..0fe7e095669 100644 --- a/src/vs/workbench/electron-browser/resources.ts +++ b/src/vs/workbench/electron-browser/resources.ts @@ -15,7 +15,7 @@ import { normalize } from 'vs/base/common/paths'; export class ResourceGlobMatcher extends Disposable { - private static readonly NO_ROOT: string = null; + private static readonly NO_ROOT: string | null = null; private readonly _onExpressionChange: Emitter = this._register(new Emitter()); get onExpressionChange(): Event { return this._onExpressionChange.event; } diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index 8c26181539c..14f5dba8646 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -8,7 +8,7 @@ import 'vs/css!./media/workbench'; import { localize } from 'vs/nls'; import { TPromise } from 'vs/base/common/winjs.base'; import { IDisposable, dispose, toDisposable, Disposable } from 'vs/base/common/lifecycle'; -import { Event, Emitter } from 'vs/base/common/event'; +import { Event, Emitter, once } from 'vs/base/common/event'; import * as DOM from 'vs/base/browser/dom'; import { RunOnceScheduler } from 'vs/base/common/async'; import * as browser from 'vs/base/browser/browser'; @@ -501,6 +501,10 @@ export class Workbench extends Disposable implements IPartService { // Fullscreen changes this._register(browser.onDidChangeFullscreen(() => this.onFullscreenChanged())); + + // Group changes + this._register(this.editorGroupService.onDidAddGroup(() => this.centerEditorLayout(this.shouldCenterLayout))); + this._register(this.editorGroupService.onDidRemoveGroup(() => this.centerEditorLayout(this.shouldCenterLayout))); } private onFullscreenChanged(): void { @@ -658,19 +662,30 @@ export class Workbench extends Disposable implements IPartService { this.editorPart.whenRestored.then(() => updateEditorContextKeys()); this._register(this.editorService.onDidActiveEditorChange(() => updateEditorContextKeys())); this._register(this.editorService.onDidVisibleEditorsChange(() => updateEditorContextKeys())); - this._register(this.editorGroupService.onDidAddGroup(() => { - updateEditorContextKeys(); - this.centerEditorLayout(this.shouldCenterLayout); - })); - this._register(this.editorGroupService.onDidRemoveGroup(() => { - updateEditorContextKeys(); - this.centerEditorLayout(this.shouldCenterLayout); - })); + this._register(this.editorGroupService.onDidAddGroup(() => updateEditorContextKeys())); + this._register(this.editorGroupService.onDidRemoveGroup(() => updateEditorContextKeys())); const inputFocused = InputFocusedContext.bindTo(this.contextKeyService); - this._register(DOM.addDisposableListener(window, 'focusin', () => { - inputFocused.set(document.activeElement && (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA')); - }, true)); + + function activeElementIsInput(): boolean { + return document.activeElement && (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA'); + } + + function trackInputFocus(): void { + const isInputFocused = activeElementIsInput(); + inputFocused.set(isInputFocused); + + if (isInputFocused) { + const tracker = DOM.trackFocus(document.activeElement as HTMLElement); + once(tracker.onDidBlur)(() => { + inputFocused.set(activeElementIsInput()); + + tracker.dispose(); + }); + } + } + + this._register(DOM.addDisposableListener(window, 'focusin', () => trackInputFocus(), true)); const workbenchStateRawContext = new RawContextKey('workbenchState', getWorkbenchStateString(this.configurationService.getWorkbenchState())); const workbenchStateContext = workbenchStateRawContext.bindTo(this.contextKeyService); @@ -1162,7 +1177,7 @@ export class Workbench extends Disposable implements IPartService { } getContainer(part: Parts): HTMLElement { - let container: HTMLElement = null; + let container: HTMLElement | null = null; switch (part) { case Parts.TITLEBAR_PART: container = this.titlebarPart.getContainer(); diff --git a/src/vs/workbench/parts/cli/electron-browser/cli.contribution.ts b/src/vs/workbench/parts/cli/electron-browser/cli.contribution.ts index 29c3894ea60..c9d441545b0 100644 --- a/src/vs/workbench/parts/cli/electron-browser/cli.contribution.ts +++ b/src/vs/workbench/parts/cli/electron-browser/cli.contribution.ts @@ -9,7 +9,6 @@ import * as cp from 'child_process'; import * as pfs from 'vs/base/node/pfs'; import * as platform from 'vs/base/common/platform'; import { nfcall } from 'vs/base/common/async'; -import { TPromise } from 'vs/base/common/winjs.base'; import { Action } from 'vs/base/common/actions'; import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -21,11 +20,11 @@ import Severity from 'vs/base/common/severity'; import { ILogService } from 'vs/platform/log/common/log'; import { getPathFromAmdModule } from 'vs/base/common/amd'; -function ignore(code: string, value: T = null): (err: any) => TPromise { - return err => err.code === code ? TPromise.as(value) : TPromise.wrapError(err); +function ignore(code: string, value: T | null = null): (err: any) => Promise { + return err => err.code === code ? Promise.resolve(value) : Promise.reject(err); } -let _source: string = null; +let _source: string | null = null; function getSource(): string { if (!_source) { const root = getPathFromAmdModule(require, ''); @@ -34,7 +33,7 @@ function getSource(): string { return _source; } -function isAvailable(): TPromise { +function isAvailable(): Promise { return pfs.exists(getSource()); } @@ -57,7 +56,7 @@ class InstallAction extends Action { return `/usr/local/bin/${product.applicationName}`; } - run(): TPromise { + run(): Promise { return isAvailable().then(isAvailable => { if (!isAvailable) { const message = nls.localize('not available', "This command is not available"); @@ -68,7 +67,7 @@ class InstallAction extends Action { return this.isInstalled() .then(isInstalled => { if (!isAvailable || isInstalled) { - return TPromise.as(null); + return Promise.resolve(null); } else { return pfs.unlink(this.target) .then(null, ignore('ENOENT')) @@ -78,7 +77,7 @@ class InstallAction extends Action { return this.createBinFolderAndSymlinkAsAdmin(); } - return TPromise.wrapError(err); + return Promise.reject(err); }); } }) @@ -89,7 +88,7 @@ class InstallAction extends Action { }); } - private isInstalled(): TPromise { + private isInstalled(): Promise { return pfs.lstat(this.target) .then(stat => stat.isSymbolicLink()) .then(() => pfs.readlink(this.target)) @@ -97,8 +96,8 @@ class InstallAction extends Action { .then(null, ignore('ENOENT', false)); } - private createBinFolderAndSymlinkAsAdmin(): TPromise { - return new TPromise((c, e) => { + private createBinFolderAndSymlinkAsAdmin(): Promise { + return new Promise((resolve, reject) => { const buttons = [nls.localize('ok', "OK"), nls.localize('cancel2', "Cancel")]; this.dialogService.show(Severity.Info, nls.localize('warnEscalation', "Code will now prompt with 'osascript' for Administrator privileges to install the shell command."), buttons, { cancelId: 1 }).then(choice => { @@ -107,11 +106,11 @@ class InstallAction extends Action { const command = 'osascript -e "do shell script \\"mkdir -p /usr/local/bin && ln -sf \'' + getSource() + '\' \'' + this.target + '\'\\" with administrator privileges"'; nfcall(cp.exec, command, {}) - .then(null, _ => TPromise.wrapError(new Error(nls.localize('cantCreateBinFolder', "Unable to create '/usr/local/bin'.")))) - .then(c, e); + .then(null, _ => Promise.reject(new Error(nls.localize('cantCreateBinFolder', "Unable to create '/usr/local/bin'.")))) + .then(resolve, reject); break; case 1 /* Cancel */: - e(new Error(nls.localize('aborted', "Aborted"))); + reject(new Error(nls.localize('aborted', "Aborted"))); break; } }); @@ -138,7 +137,7 @@ class UninstallAction extends Action { return `/usr/local/bin/${product.applicationName}`; } - run(): TPromise { + run(): Promise { return isAvailable().then(isAvailable => { if (!isAvailable) { const message = nls.localize('not available', "This command is not available"); @@ -156,7 +155,7 @@ class UninstallAction extends Action { return this.deleteSymlinkAsAdmin(); } - return TPromise.wrapError(err); + return Promise.reject(err); }).then(() => { this.logService.trace('cli#uninstall', this.target); this.notificationService.info(nls.localize('successFrom', "Shell command '{0}' successfully uninstalled from PATH.", product.applicationName)); @@ -164,8 +163,8 @@ class UninstallAction extends Action { }); } - private deleteSymlinkAsAdmin(): TPromise { - return new TPromise((c, e) => { + private deleteSymlinkAsAdmin(): Promise { + return new Promise((resolve, reject) => { const buttons = [nls.localize('ok', "OK"), nls.localize('cancel2', "Cancel")]; this.dialogService.show(Severity.Info, nls.localize('warnEscalationUninstall', "Code will now prompt with 'osascript' for Administrator privileges to uninstall the shell command."), buttons, { cancelId: 1 }).then(choice => { @@ -174,11 +173,11 @@ class UninstallAction extends Action { const command = 'osascript -e "do shell script \\"rm \'' + this.target + '\'\\" with administrator privileges"'; nfcall(cp.exec, command, {}) - .then(null, _ => TPromise.wrapError(new Error(nls.localize('cantUninstall', "Unable to uninstall the shell command '{0}'.", this.target)))) - .then(c, e); + .then(null, _ => Promise.reject(new Error(nls.localize('cantUninstall', "Unable to uninstall the shell command '{0}'.", this.target)))) + .then(resolve, reject); break; case 1 /* Cancel */: - e(new Error(nls.localize('aborted', "Aborted"))); + reject(new Error(nls.localize('aborted', "Aborted"))); break; } }); diff --git a/src/vs/workbench/parts/codeEditor/electron-browser/languageConfiguration/languageConfigurationExtensionPoint.ts b/src/vs/workbench/parts/codeEditor/electron-browser/languageConfiguration/languageConfigurationExtensionPoint.ts index 68752105ad6..ab65572a10c 100644 --- a/src/vs/workbench/parts/codeEditor/electron-browser/languageConfiguration/languageConfigurationExtensionPoint.ts +++ b/src/vs/workbench/parts/codeEditor/electron-browser/languageConfiguration/languageConfigurationExtensionPoint.ts @@ -111,7 +111,7 @@ export class LanguageConfigurationFileHandler { return null; } - let result: CommentRule = null; + let result: CommentRule | null = null; if (typeof source.lineComment !== 'undefined') { if (typeof source.lineComment !== 'string') { console.warn(`[${languageIdentifier.language}]: language configuration: expected \`comments.lineComment\` to be a string.`); @@ -141,7 +141,7 @@ export class LanguageConfigurationFileHandler { return null; } - let result: CharacterPair[] = null; + let result: CharacterPair[] | null = null; for (let i = 0, len = source.length; i < len; i++) { const pair = source[i]; if (!isCharacterPair(pair)) { @@ -165,7 +165,7 @@ export class LanguageConfigurationFileHandler { return null; } - let result: IAutoClosingPairConditional[] = null; + let result: IAutoClosingPairConditional[] | null = null; for (let i = 0, len = source.length; i < len; i++) { const pair = source[i]; if (Array.isArray(pair)) { @@ -211,7 +211,7 @@ export class LanguageConfigurationFileHandler { return null; } - let result: IAutoClosingPair[] = null; + let result: IAutoClosingPair[] | null = null; for (let i = 0, len = source.length; i < len; i++) { const pair = source[i]; if (Array.isArray(pair)) { diff --git a/src/vs/workbench/parts/codeEditor/electron-browser/textMate/inspectTMScopes.ts b/src/vs/workbench/parts/codeEditor/electron-browser/textMate/inspectTMScopes.ts index ca4b63610d1..73ecf12bb06 100644 --- a/src/vs/workbench/parts/codeEditor/electron-browser/textMate/inspectTMScopes.ts +++ b/src/vs/workbench/parts/codeEditor/electron-browser/textMate/inspectTMScopes.ts @@ -349,7 +349,7 @@ class InspectTMScopesWidget extends Disposable implements IContentWidget { } private _getStateBeforeLine(grammar: IGrammar, lineNumber: number): StackElement { - let state: StackElement = null; + let state: StackElement | null = null; for (let i = 1; i < lineNumber; i++) { let tokenizationResult = grammar.tokenizeLine(this._model.getLineContent(i), state); diff --git a/src/vs/workbench/parts/comments/electron-browser/commentThreadWidget.ts b/src/vs/workbench/parts/comments/electron-browser/commentThreadWidget.ts index 0ac0bd5b3e1..ad58f7bb531 100644 --- a/src/vs/workbench/parts/comments/electron-browser/commentThreadWidget.ts +++ b/src/vs/workbench/parts/comments/electron-browser/commentThreadWidget.ts @@ -206,7 +206,7 @@ export class ReviewZoneWidget extends ZoneWidget { this._commentsElement.removeChild(commentElementsToDel[i].domNode); } - let lastCommentElement: HTMLElement = null; + let lastCommentElement: HTMLElement | null = null; let newCommentNodeList: CommentNode[] = []; for (let i = newCommentsLen - 1; i >= 0; i--) { let currentComment = commentThread.comments[i]; diff --git a/src/vs/workbench/parts/debug/browser/linkDetector.ts b/src/vs/workbench/parts/debug/browser/linkDetector.ts index 8846aa76a91..dee02d38435 100644 --- a/src/vs/workbench/parts/debug/browser/linkDetector.ts +++ b/src/vs/workbench/parts/debug/browser/linkDetector.ts @@ -46,7 +46,7 @@ export class LinkDetector { let match = pattern.exec(text); while (match !== null) { - let resource: uri = null; + let resource: uri | null = null; if (!resource) { match = pattern.exec(text); continue; diff --git a/src/vs/workbench/parts/debug/browser/media/debug-dark.svg b/src/vs/workbench/parts/debug/browser/media/debug-dark.svg index cedddacf03e..07232769d87 100644 --- a/src/vs/workbench/parts/debug/browser/media/debug-dark.svg +++ b/src/vs/workbench/parts/debug/browser/media/debug-dark.svg @@ -1 +1 @@ -debug-dark \ No newline at end of file + \ No newline at end of file diff --git a/src/vs/workbench/parts/debug/browser/media/debug.contribution.css b/src/vs/workbench/parts/debug/browser/media/debug.contribution.css index 6fe2dd65b0e..fc46b6a13f9 100644 --- a/src/vs/workbench/parts/debug/browser/media/debug.contribution.css +++ b/src/vs/workbench/parts/debug/browser/media/debug.contribution.css @@ -6,7 +6,6 @@ /* Activity Bar */ .monaco-workbench > .activitybar .monaco-action-bar .action-label.debug { -webkit-mask: url('debug-dark.svg') no-repeat 50% 50%; - -webkit-mask-size: 28px; } .monaco-editor .debug-top-stack-frame-column::before { diff --git a/src/vs/workbench/parts/debug/common/debugModel.ts b/src/vs/workbench/parts/debug/common/debugModel.ts index 59c903072db..3d2fe5c1b7e 100644 --- a/src/vs/workbench/parts/debug/common/debugModel.ts +++ b/src/vs/workbench/parts/debug/common/debugModel.ts @@ -271,7 +271,7 @@ export class Variable extends ExpressionContainer implements IExpression { namedVariables: number, indexedVariables: number, public presentationHint: DebugProtocol.VariablePresentationHint, - public type: string = null, + public type: string | null = null, public available = true, startOfVariables = 0 ) { @@ -280,7 +280,7 @@ export class Variable extends ExpressionContainer implements IExpression { } public setVariable(value: string): TPromise { - return this.session.setVariable((this.parent).reference, name, value).then(response => { + return this.session.setVariable((this.parent).reference, this.name, value).then(response => { if (response && response.body) { this.value = response.body.value; this.type = response.body.type || this.type; @@ -784,7 +784,7 @@ export class DebugModel implements IDebugModel { } } - public clearThreads(id: string, removeThreads: boolean, reference: number = undefined): void { + public clearThreads(id: string, removeThreads: boolean, reference: number | undefined = undefined): void { const session = this.sessions.filter(p => p.getId() === id).pop(); this.schedulers.forEach(scheduler => scheduler.dispose()); this.schedulers.clear(); @@ -1025,7 +1025,7 @@ export class DebugModel implements IDebugModel { } } - public removeWatchExpressions(id: string = null): void { + public removeWatchExpressions(id: string | null = null): void { this.watchExpressions = id ? this.watchExpressions.filter(we => we.getId() !== id) : []; this._onDidChangeWatchExpressions.fire(); } diff --git a/src/vs/workbench/parts/debug/common/debugUtils.ts b/src/vs/workbench/parts/debug/common/debugUtils.ts index 5d1f7bf6405..abcb216c141 100644 --- a/src/vs/workbench/parts/debug/common/debugUtils.ts +++ b/src/vs/workbench/parts/debug/common/debugUtils.ts @@ -25,13 +25,13 @@ export function isExtensionHostDebugging(config: IConfig) { } export function getExactExpressionStartAndEnd(lineContent: string, looseStart: number, looseEnd: number): { start: number, end: number } { - let matchingExpression: string = undefined; + let matchingExpression: string | undefined = undefined; let startOffset = 0; // Some example supported expressions: myVar.prop, a.b.c.d, myVar?.prop, myVar->prop, MyClass::StaticProp, *myVar // Match any character except a set of characters which often break interesting sub-expressions let expression: RegExp = /([^()\[\]{}<>\s+\-/%~#^;=|,`!]|\->)+/g; - let result: RegExpExecArray = undefined; + let result: RegExpExecArray | undefined = undefined; // First find the full expression under the cursor while (result = expression.exec(lineContent)) { @@ -49,7 +49,7 @@ export function getExactExpressionStartAndEnd(lineContent: string, looseStart: n // For example in expression 'a.b.c.d', if the focus was under 'b', 'a.b' would be evaluated. if (matchingExpression) { let subExpression: RegExp = /\w+/g; - let subExpressionResult: RegExpExecArray = undefined; + let subExpressionResult: RegExpExecArray | undefined = undefined; while (subExpressionResult = subExpression.exec(matchingExpression)) { let subEnd = subExpressionResult.index + 1 + startOffset + subExpressionResult[0].length; if (subEnd >= looseEnd) { diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index 261e366b312..d15a8ec1057 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -47,6 +47,7 @@ import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { IDebugService, State, IDebugSession, CONTEXT_DEBUG_TYPE, CONTEXT_DEBUG_STATE, CONTEXT_IN_DEBUG_MODE, IThread, IDebugConfiguration, VIEWLET_ID, REPL_ID, IConfig, ILaunch, IViewModel, IConfigurationManager, IDebugModel, IEnablement, IBreakpoint, IBreakpointData, ICompound, IGlobalConfig, IStackFrame, AdapterEndEvent } from 'vs/workbench/parts/debug/common/debug'; import { isExtensionHostDebugging } from 'vs/workbench/parts/debug/common/debugUtils'; import { RunOnceScheduler } from 'vs/base/common/async'; +import { isErrorWithActions, createErrorWithActions } from 'vs/base/common/errorsWithActions'; const DEBUG_BREAKPOINTS_KEY = 'debug.breakpoint'; const DEBUG_BREAKPOINTS_ACTIVATED_KEY = 'debug.breakpointactivated'; @@ -472,7 +473,7 @@ export class DebugService implements IDebugService { const errorMessage = error instanceof Error ? error.message : error; this.telemetryDebugMisconfiguration(session.configuration ? session.configuration.type : undefined, errorMessage); - return this.showError(errorMessage, errors.isErrorWithActions(error) ? error.actions : []).then(() => false); + return this.showError(errorMessage, isErrorWithActions(error) ? error.actions : []).then(() => false); }); } @@ -547,32 +548,39 @@ export class DebugService implements IDebugService { restartSession(session: IDebugSession, restartData?: any): TPromise { return this.textFileService.saveAll().then(() => { - // Do not run preLaunch and postDebug tasks for automatic restarts const isAutoRestart = !!restartData; - const taskThenable: Thenable = isAutoRestart ? Promise.resolve(TaskRunResult.Success) : - this.runTask(session.root, session.configuration.postDebugTask).then(() => this.runTaskAndCheckErrors(session.root, session.configuration.preLaunchTask)); - - return taskThenable.then(taskRunResult => { - if (taskRunResult !== TaskRunResult.Success) { - return; - } - if (session.capabilities.supportsRestartRequest) { - return session.restart().then(() => void 0); + const runTasks: () => Thenable = () => { + if (isAutoRestart) { + // Do not run preLaunch and postDebug tasks for automatic restarts + return Promise.resolve(TaskRunResult.Success); } - const shouldFocus = this.viewModel.focusedSession && session.getId() === this.viewModel.focusedSession.getId(); - if (isExtensionHostDebugging(session.configuration) && session.root) { - return this.broadcastService.broadcast({ - channel: EXTENSION_RELOAD_BROADCAST_CHANNEL, - payload: [session.root.uri.toString()] - }); - } + return this.runTask(session.root, session.configuration.postDebugTask) + .then(() => this.runTaskAndCheckErrors(session.root, session.configuration.preLaunchTask)); + }; - // If the restart is automatic -> disconnect, otherwise -> terminate #55064 - return (isAutoRestart ? session.disconnect(true) : session.terminate(true)).then(() => { + if (session.capabilities.supportsRestartRequest) { + return runTasks().then(taskResult => taskResult === TaskRunResult.Success ? session.restart() : undefined); + } + + if (isExtensionHostDebugging(session.configuration) && session.root) { + return runTasks().then(taskResult => taskResult === TaskRunResult.Success ? this.broadcastService.broadcast({ + channel: EXTENSION_RELOAD_BROADCAST_CHANNEL, + payload: [session.root.uri.toString()] + }) : undefined); + } + + const shouldFocus = this.viewModel.focusedSession && session.getId() === this.viewModel.focusedSession.getId(); + // If the restart is automatic -> disconnect, otherwise -> terminate #55064 + return (isAutoRestart ? session.disconnect(true) : session.terminate(true)).then(() => { + + return new Promise((c, e) => { + setTimeout(() => { + runTasks().then(taskResult => { + if (taskResult !== TaskRunResult.Success) { + return; + } - return new Promise((c, e) => { - setTimeout(() => { // Read the configuration again if a launch.json has been changed, if not just use the inmemory configuration let needsToSubstitute = false; let unresolved: IConfig; @@ -601,8 +609,8 @@ export class DebugService implements IDebugService { c(null); }, err => e(err)); }); - }, 300); - }); + }); + }, 300); }); }); }); @@ -621,7 +629,7 @@ export class DebugService implements IDebugService { private substituteVariables(launch: ILaunch | undefined, config: IConfig): TPromise { const dbg = this.configurationManager.getDebugger(config.type); if (dbg) { - let folder: IWorkspaceFolder = undefined; + let folder: IWorkspaceFolder | undefined = undefined; if (launch && launch.workspace) { folder = launch.workspace; } else { @@ -695,7 +703,7 @@ export class DebugService implements IDebugService { const errorMessage = typeof taskId === 'string' ? nls.localize('DebugTaskNotFoundWithTaskId', "Could not find the task '{0}'.", taskId) : nls.localize('DebugTaskNotFound', "Could not find the specified task."); - return Promise.reject(errors.create(errorMessage)); + return Promise.reject(createErrorWithActions(errorMessage)); } // If a task is missing the problem matcher the promise will never complete, so we need to have a workaround #35340 diff --git a/src/vs/workbench/parts/debug/electron-browser/debugSession.ts b/src/vs/workbench/parts/debug/electron-browser/debugSession.ts index 7e160b0ee7f..76aa66c17c8 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugSession.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugSession.ts @@ -505,7 +505,7 @@ export class DebugSession implements IDebugSession { return result; } - clearThreads(removeThreads: boolean, reference: number = undefined): void { + clearThreads(removeThreads: boolean, reference: number | undefined = undefined): void { if (reference !== undefined && reference !== null) { if (this.threads.has(reference)) { const thread = this.threads.get(reference); @@ -560,8 +560,8 @@ export class DebugSession implements IDebugSession { } } - private fetchThreads(stoppedDetails?: IRawStoppedDetails): TPromise { - return this.raw.threads().then(response => { + private fetchThreads(stoppedDetails?: IRawStoppedDetails): TPromise { + return this.raw ? this.raw.threads().then(response => { if (response && response.body && response.body.threads) { response.body.threads.forEach(thread => { this.model.rawUpdate({ @@ -572,13 +572,12 @@ export class DebugSession implements IDebugSession { }); }); } - }); + }) : TPromise.as(undefined); } //---- private private registerListeners(): void { - this.rawListeners.push(this.raw.onDidInitialize(() => { aria.status(nls.localize('debuggingStarted', "Debugging started.")); const sendConfigurationDone = () => { diff --git a/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.ts b/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.ts index e0c614f5f1a..5c70a9266bc 100644 --- a/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.ts +++ b/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.ts @@ -12,6 +12,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { formatPII } from 'vs/workbench/parts/debug/common/debugUtils'; import { IDebugAdapter, IConfig, AdapterEndEvent, IDebugger } from 'vs/workbench/parts/debug/common/debug'; +import { createErrorWithActions } from 'vs/base/common/errorsWithActions'; /** * Encapsulates the DebugAdapter lifecycle and some idiosyncrasies of the Debug Adapter Protocol. @@ -536,7 +537,7 @@ export class RawDebugSession { const userMessage = error ? formatPII(error.format, false, error.variables) : errorMessage; if (error && error.url) { const label = error.urlLabel ? error.urlLabel : nls.localize('moreInfo', "More Info"); - return errors.create(userMessage, { + return createErrorWithActions(userMessage, { actions: [new Action('debug.moreInfo', label, null, true, () => { window.open(error.url); return Promise.resolve(null); diff --git a/src/vs/workbench/parts/debug/electron-browser/replViewer.ts b/src/vs/workbench/parts/debug/electron-browser/replViewer.ts index 82bf8989a13..b4baba1d40d 100644 --- a/src/vs/workbench/parts/debug/electron-browser/replViewer.ts +++ b/src/vs/workbench/parts/debug/electron-browser/replViewer.ts @@ -351,7 +351,7 @@ export class ReplExpressionsActionProvider implements IActionProvider { export class ReplExpressionsController extends BaseDebugController { - private lastSelectedString: string = null; + private lastSelectedString: string | null = null; public toFocusOnClick: { focus(): void }; protected onLeftClick(tree: ITree, element: any, eventish: ICancelableEvent, origin: string = 'mouse'): boolean { diff --git a/src/vs/workbench/parts/debug/node/terminals.ts b/src/vs/workbench/parts/debug/node/terminals.ts index a2251d524f9..f6cc9c3ab77 100644 --- a/src/vs/workbench/parts/debug/node/terminals.ts +++ b/src/vs/workbench/parts/debug/node/terminals.ts @@ -14,7 +14,7 @@ import { getPathFromAmdModule } from 'vs/base/common/amd'; const TERMINAL_TITLE = nls.localize('console.title', "VS Code Console"); -let terminalLauncher: ITerminalLauncher = undefined; +let terminalLauncher: ITerminalLauncher | undefined = undefined; export function getTerminalLauncher() { if (!terminalLauncher) { @@ -29,7 +29,7 @@ export function getTerminalLauncher() { return terminalLauncher; } -let _DEFAULT_TERMINAL_LINUX_READY: TPromise = null; +let _DEFAULT_TERMINAL_LINUX_READY: TPromise | null = null; export function getDefaultTerminalLinuxReady(): TPromise { if (!_DEFAULT_TERMINAL_LINUX_READY) { _DEFAULT_TERMINAL_LINUX_READY = new Promise(c => { @@ -58,7 +58,7 @@ export function getDefaultTerminalLinuxReady(): TPromise { return _DEFAULT_TERMINAL_LINUX_READY; } -let _DEFAULT_TERMINAL_WINDOWS: string = null; +let _DEFAULT_TERMINAL_WINDOWS: string | null = null; export function getDefaultTerminalWindows(): string { if (!_DEFAULT_TERMINAL_WINDOWS) { const isWoW64 = !!process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'); diff --git a/src/vs/workbench/parts/emmet/electron-browser/emmetActions.ts b/src/vs/workbench/parts/emmet/electron-browser/emmetActions.ts index 3154bcd46a3..b64af96857f 100644 --- a/src/vs/workbench/parts/emmet/electron-browser/emmetActions.ts +++ b/src/vs/workbench/parts/emmet/electron-browser/emmetActions.ts @@ -26,7 +26,7 @@ export interface ILanguageIdentifierResolver { class GrammarContributions implements IGrammarContributions { - private static _grammars: ModeScopeMap = null; + private static _grammars: ModeScopeMap | null = null; constructor(contributions: ExtensionPointContribution[]) { if (GrammarContributions._grammars === null) { @@ -65,8 +65,8 @@ export abstract class EmmetEditorAction extends EditorAction { private static readonly emmetSupportedModes = ['html', 'css', 'xml', 'xsl', 'haml', 'jade', 'jsx', 'slim', 'scss', 'sass', 'less', 'stylus', 'styl', 'svg']; - private _lastGrammarContributions: TPromise = null; - private _lastExtensionService: IExtensionService = null; + private _lastGrammarContributions: TPromise | null = null; + private _lastExtensionService: IExtensionService | null = null; private _withGrammarContributions(extensionService: IExtensionService): TPromise { if (this._lastExtensionService !== extensionService) { this._lastExtensionService = extensionService; diff --git a/src/vs/workbench/parts/execution/electron-browser/terminal.ts b/src/vs/workbench/parts/execution/electron-browser/terminal.ts index fa103a8e2e9..f08fd641f0a 100644 --- a/src/vs/workbench/parts/execution/electron-browser/terminal.ts +++ b/src/vs/workbench/parts/execution/electron-browser/terminal.ts @@ -6,7 +6,7 @@ import * as env from 'vs/base/common/platform'; import * as pfs from 'vs/base/node/pfs'; -let _DEFAULT_TERMINAL_LINUX_READY: Promise = null; +let _DEFAULT_TERMINAL_LINUX_READY: Promise | null = null; export function getDefaultTerminalLinuxReady(): Promise { if (!_DEFAULT_TERMINAL_LINUX_READY) { _DEFAULT_TERMINAL_LINUX_READY = new Promise(c => { @@ -37,7 +37,7 @@ export function getDefaultTerminalLinuxReady(): Promise { export const DEFAULT_TERMINAL_OSX = 'Terminal.app'; -let _DEFAULT_TERMINAL_WINDOWS: string = null; +let _DEFAULT_TERMINAL_WINDOWS: string | null = null; export function getDefaultTerminalWindows(): string { if (!_DEFAULT_TERMINAL_WINDOWS) { const isWoW64 = !!process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'); diff --git a/src/vs/workbench/parts/experiments/electron-browser/experimentalPrompt.ts b/src/vs/workbench/parts/experiments/electron-browser/experimentalPrompt.ts index 929ad930b63..d92206737f5 100644 --- a/src/vs/workbench/parts/experiments/electron-browser/experimentalPrompt.ts +++ b/src/vs/workbench/parts/experiments/electron-browser/experimentalPrompt.ts @@ -80,9 +80,11 @@ export class ExperimentalPrompts extends Disposable implements IWorkbenchContrib }; }); - this.notificationService.prompt(Severity.Info, actionProperties.promptText, choices, () => { - logTelemetry(); - this.experimentService.markAsCompleted(experiment.id); + this.notificationService.prompt(Severity.Info, actionProperties.promptText, choices, { + onCancel: () => { + logTelemetry(); + this.experimentService.markAsCompleted(experiment.id); + } }); } diff --git a/src/vs/workbench/parts/experiments/test/electron-browser/experimentalPrompts.test.ts b/src/vs/workbench/parts/experiments/test/electron-browser/experimentalPrompts.test.ts index 75feb8d5708..374d12ce860 100644 --- a/src/vs/workbench/parts/experiments/test/electron-browser/experimentalPrompts.test.ts +++ b/src/vs/workbench/parts/experiments/test/electron-browser/experimentalPrompts.test.ts @@ -94,7 +94,7 @@ suite('Experimental Prompts', () => { }; instantiationService.stub(INotificationService, { - prompt: (a: Severity, b: string, c: IPromptChoice[], d) => { + prompt: (a: Severity, b: string, c: IPromptChoice[], options) => { assert.equal(b, promptText); assert.equal(c.length, 2); c[0].run(); @@ -118,7 +118,7 @@ suite('Experimental Prompts', () => { }; instantiationService.stub(INotificationService, { - prompt: (a: Severity, b: string, c: IPromptChoice[], d) => { + prompt: (a: Severity, b: string, c: IPromptChoice[], options) => { assert.equal(b, promptText); assert.equal(c.length, 2); c[1].run(); @@ -142,10 +142,10 @@ suite('Experimental Prompts', () => { }; instantiationService.stub(INotificationService, { - prompt: (a: Severity, b: string, c: IPromptChoice[], d) => { + prompt: (a: Severity, b: string, c: IPromptChoice[], options) => { assert.equal(b, promptText); assert.equal(c.length, 2); - d(); + options.onCancel(); } }); diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.ts index 10dfe395d9b..13682840aa1 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.ts @@ -81,7 +81,7 @@ class NavBar { private _onChange = new Emitter<{ id: string, focus: boolean }>(); get onChange(): Event<{ id: string, focus: boolean }> { return this._onChange.event; } - private currentId: string = null; + private currentId: string | null = null; private actions: Action[]; private actionbar: ActionBar; diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts index 5ac39705590..31ba8d61884 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionTipsService.ts @@ -611,14 +611,17 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe this.promptIgnoreExtensionRecommendations(); } }], - () => { - /* __GDPR__ - "extensionRecommendations:popup" : { - "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } - } - */ - this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'cancelled', extensionId: name }); + { + sticky: true, + onCancel: () => { + /* __GDPR__ + "extensionRecommendations:popup" : { + "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'cancelled', extensionId: name }); + } } ); }); @@ -687,14 +690,17 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe this.telemetryService.publicLog('fileExtensionSuggestion:popup', { userReaction: 'neverShowAgain', fileExtension: fileExtension }); } }], - () => { - /* __GDPR__ - "fileExtensionSuggestion:popup" : { - "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "fileExtension": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } - } - */ - this.telemetryService.publicLog('fileExtensionSuggestion:popup', { userReaction: 'cancelled', fileExtension: fileExtension }); + { + sticky: true, + onCancel: () => { + /* __GDPR__ + "fileExtensionSuggestion:popup" : { + "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "fileExtension": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('fileExtensionSuggestion:popup', { userReaction: 'cancelled', fileExtension: fileExtension }); + } } ); }); @@ -772,15 +778,18 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe c(void 0); } }], - () => { - /* __GDPR__ - "extensionWorkspaceRecommendations:popup" : { - "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - this.telemetryService.publicLog('extensionWorkspaceRecommendations:popup', { userReaction: 'cancelled' }); + { + sticky: true, + onCancel: () => { + /* __GDPR__ + "extensionWorkspaceRecommendations:popup" : { + "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + } + */ + this.telemetryService.publicLog('extensionWorkspaceRecommendations:popup', { userReaction: 'cancelled' }); - c(void 0); + c(void 0); + } } ); }); diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts index 7ed8e95c841..e04e6a0fed5 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts @@ -7,7 +7,6 @@ import 'vs/css!./media/extensionActions'; import { localize } from 'vs/nls'; import { IAction, Action } from 'vs/base/common/actions'; import { Throttler } from 'vs/base/common/async'; -import severity from 'vs/base/common/severity'; import * as DOM from 'vs/base/browser/dom'; import * as paths from 'vs/base/common/paths'; import { Event } from 'vs/base/common/event'; @@ -823,7 +822,7 @@ export class CheckForUpdatesAction extends Action { extensions => { const outdatedExtensions = extensions.filter(ext => ext.outdated === true); if (!outdatedExtensions.length) { - this.notificationService.notify({ severity: severity.Info, message: localize('noUpdatesAvailable', "All Extensions are up to date.") }); + this.notificationService.info(localize('noUpdatesAvailable', "All Extensions are up to date.")); return; } @@ -846,7 +845,7 @@ export class CheckForUpdatesAction extends Action { .then(viewlet => viewlet as IExtensionsViewlet) .then(viewlet => viewlet.search('')); - this.notificationService.notify({ severity: severity.Info, message: msgAvailableExtensions }); + this.notificationService.info(msgAvailableExtensions); } ); } @@ -2351,7 +2350,8 @@ export class InstallVSIXAction extends Action { [{ label: localize('InstallVSIXAction.reloadNow', "Reload Now"), run: () => this.windowService.reloadWindow() - }] + }], + { sticky: true } ); }); }); @@ -2408,7 +2408,8 @@ export class ReinstallAction extends Action { [{ label: localize('ReinstallAction.reloadNow', "Reload Now"), run: () => this.windowService.reloadWindow() - }] + }], + { sticky: true } ); }, error => this.notificationService.error(error)); } diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts index 715a1747ae7..a557912381b 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsViewlet.ts @@ -6,7 +6,7 @@ import 'vs/css!./media/extensionsViewlet'; import { localize } from 'vs/nls'; import { ThrottledDelayer, always, timeout } from 'vs/base/common/async'; -import { isPromiseCanceledError, create as createError } from 'vs/base/common/errors'; +import { isPromiseCanceledError } from 'vs/base/common/errors'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { Event as EventOf, Emitter } from 'vs/base/common/event'; @@ -54,6 +54,7 @@ import { SingleServerExtensionManagementServerService } from 'vs/workbench/servi import { Query } from 'vs/workbench/parts/extensions/common/extensionQuery'; import { SuggestEnabledInput, attachSuggestEnabledInputBoxStyler } from 'vs/workbench/parts/codeEditor/electron-browser/suggestEnabledInput'; import { alert } from 'vs/base/browser/ui/aria/aria'; +import { createErrorWithActions } from 'vs/base/common/errorsWithActions'; interface SearchInputEvent extends Event { target: HTMLInputElement; @@ -546,7 +547,7 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio const message = err && err.message || ''; if (/ECONNREFUSED/.test(message)) { - const error = createError(localize('suggestProxyError', "Marketplace returned 'ECONNREFUSED'. Please check the 'http.proxy' setting."), { + const error = createErrorWithActions(localize('suggestProxyError', "Marketplace returned 'ECONNREFUSED'. Please check the 'http.proxy' setting."), { actions: [ this.instantiationService.createInstance(OpenGlobalSettingsAction, OpenGlobalSettingsAction.ID, OpenGlobalSettingsAction.LABEL) ] @@ -634,7 +635,8 @@ export class MaliciousExtensionChecker implements IWorkbenchContribution { [{ label: localize('reloadNow', "Reload Now"), run: () => this.windowService.reloadWindow() - }] + }], + { sticky: true } ); }))); } else { diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsViews.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsViews.ts index ab9ac9cad4e..7816afdaaa1 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsViews.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsViews.ts @@ -7,7 +7,7 @@ import { localize } from 'vs/nls'; import { dispose } from 'vs/base/common/lifecycle'; import { assign } from 'vs/base/common/objects'; import { chain } from 'vs/base/common/event'; -import { isPromiseCanceledError, create as createError } from 'vs/base/common/errors'; +import { isPromiseCanceledError } from 'vs/base/common/errors'; import { PagedModel, IPagedModel, IPager, DelayedPagedModel } from 'vs/base/common/paging'; import { SortBy, SortOrder, IQueryOptions, LocalExtensionType, IExtensionTipsService, EnablementState, IExtensionRecommendation } from 'vs/platform/extensionManagement/common/extensionManagement'; import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; @@ -38,6 +38,7 @@ import { distinct } from 'vs/base/common/arrays'; import { IExperimentService, IExperiment, ExperimentActionType } from 'vs/workbench/parts/experiments/node/experimentService'; import { alert } from 'vs/base/browser/ui/aria/aria'; import { IListContextMenuEvent } from 'vs/base/browser/ui/list/list'; +import { createErrorWithActions } from 'vs/base/common/errorsWithActions'; export class ExtensionsListView extends ViewletPanel { @@ -639,7 +640,7 @@ export class ExtensionsListView extends ViewletPanel { const message = err && err.message || ''; if (/ECONNREFUSED/.test(message)) { - const error = createError(localize('suggestProxyError', "Marketplace returned 'ECONNREFUSED'. Please check the 'http.proxy' setting."), { + const error = createErrorWithActions(localize('suggestProxyError', "Marketplace returned 'ECONNREFUSED'. Please check the 'http.proxy' setting."), { actions: [ this.instantiationService.createInstance(OpenGlobalSettingsAction, OpenGlobalSettingsAction.ID, OpenGlobalSettingsAction.LABEL) ] diff --git a/src/vs/workbench/parts/extensions/electron-browser/media/extensions-dark.svg b/src/vs/workbench/parts/extensions/electron-browser/media/extensions-dark.svg index 4a1571a3c5c..357f1925ece 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/media/extensions-dark.svg +++ b/src/vs/workbench/parts/extensions/electron-browser/media/extensions-dark.svg @@ -1,6 +1 @@ - - - - + \ No newline at end of file diff --git a/src/vs/workbench/parts/extensions/electron-browser/media/extensions.css b/src/vs/workbench/parts/extensions/electron-browser/media/extensions.css index a879a47e71a..52362be55a0 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/media/extensions.css +++ b/src/vs/workbench/parts/extensions/electron-browser/media/extensions.css @@ -5,7 +5,6 @@ .monaco-workbench > .activitybar > .content .monaco-action-bar .action-label.extensions { -webkit-mask: url('extensions-dark.svg') no-repeat 50% 50%; - -webkit-mask-size: 21px; } .extensions .split-view-view .panel-header .count-badge-wrapper { diff --git a/src/vs/workbench/parts/extensions/electron-browser/runtimeExtensionsEditor.ts b/src/vs/workbench/parts/extensions/electron-browser/runtimeExtensionsEditor.ts index e34883ba455..b55336a29d8 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/runtimeExtensionsEditor.ts @@ -186,7 +186,7 @@ export class RuntimeExtensionsEditor extends BaseEditor { for (let i = 0, len = this._extensionsDescriptions.length; i < len; i++) { const extensionDescription = this._extensionsDescriptions[i]; - let profileInfo: IExtensionProfileInformation = null; + let profileInfo: IExtensionProfileInformation | null = null; if (this._profileInfo) { let extensionSegments = segments[extensionDescription.id] || []; let extensionTotalTime = 0; @@ -408,7 +408,7 @@ export class RuntimeExtensionsEditor extends BaseEditor { this._list.onContextMenu((e) => { const actions: IAction[] = []; - if (e.element.marketplaceInfo.type === LocalExtensionType.User) { + if (e.element.marketplaceInfo && e.element.marketplaceInfo.type === LocalExtensionType.User) { actions.push(this._instantiationService.createInstance(DisableForWorkspaceAction, DisableForWorkspaceAction.LABEL)); actions.push(this._instantiationService.createInstance(DisableGloballyAction, DisableGloballyAction.LABEL)); actions.forEach((a: DisableForWorkspaceAction | DisableGloballyAction) => a.extension = e.element.marketplaceInfo); diff --git a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts index d110ac2fafc..4fe3d4779fc 100644 --- a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts +++ b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts @@ -313,9 +313,9 @@ ${this.description} class ExtensionDependencies implements IExtensionDependencies { - private _hasDependencies: boolean = null; + private _hasDependencies: boolean | null = null; - constructor(private _extension: IExtension, private _identifier: string, private _map: Map, private _dependent: IExtensionDependencies = null) { } + constructor(private _extension: IExtension, private _identifier: string, private _map: Map, private _dependent: IExtensionDependencies | null = null) { } get hasDependencies(): boolean { if (this._hasDependencies === null) { @@ -1033,7 +1033,8 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService, [{ label: nls.localize('install', "Install"), run: () => this.install(extension).then(undefined, error => this.onError(error)) - }] + }], + { sticky: true } ); }); }); diff --git a/src/vs/workbench/parts/extensions/test/electron-browser/extensionsTipsService.test.ts b/src/vs/workbench/parts/extensions/test/electron-browser/extensionsTipsService.test.ts index 1c14d68cc2c..81122fc771d 100644 --- a/src/vs/workbench/parts/extensions/test/electron-browser/extensionsTipsService.test.ts +++ b/src/vs/workbench/parts/extensions/test/electron-browser/extensionsTipsService.test.ts @@ -43,7 +43,7 @@ import product from 'vs/platform/node/product'; import { ITextModel } from 'vs/editor/common/model'; import { IModelService } from 'vs/editor/common/services/modelService'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; -import { INotificationService, Severity, IPromptChoice } from 'vs/platform/notification/common/notification'; +import { INotificationService, Severity, IPromptChoice, IPromptOptions } from 'vs/platform/notification/common/notification'; import { URLService } from 'vs/platform/url/common/urlService'; import { IExperimentService } from 'vs/workbench/parts/experiments/node/experimentService'; import { TestExperimentService } from 'vs/workbench/parts/experiments/test/node/experimentService.test'; @@ -233,7 +233,7 @@ suite('ExtensionsTipsService Test', () => { prompted = false; class TestNotificationService2 extends TestNotificationService { - public prompt(severity: Severity, message: string, choices: IPromptChoice[], onCancel?: () => void) { + public prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions) { prompted = true; return null; } diff --git a/src/vs/workbench/parts/files/browser/editors/textFileEditor.ts b/src/vs/workbench/parts/files/browser/editors/textFileEditor.ts index 394ee6debfc..ed3a282c7aa 100644 --- a/src/vs/workbench/parts/files/browser/editors/textFileEditor.ts +++ b/src/vs/workbench/parts/files/browser/editors/textFileEditor.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import * as errors from 'vs/base/common/errors'; import { toErrorMessage } from 'vs/base/common/errorMessage'; import * as types from 'vs/base/common/types'; import * as paths from 'vs/base/common/paths'; @@ -30,6 +29,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { IEditorGroupsService, IEditorGroup } from 'vs/workbench/services/group/common/editorGroupsService'; import { CancellationToken } from 'vs/base/common/cancellation'; import { IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor'; +import { createErrorWithActions } from 'vs/base/common/errorsWithActions'; /** * An implementation of editor for file system resources. @@ -179,7 +179,7 @@ export class TextFileEditor extends BaseTextEditor { // Offer to create a file from the error if we have a file not found and the name is valid if ((error).fileOperationResult === FileOperationResult.FILE_NOT_FOUND && paths.isValidBasename(paths.basename(input.getResource().fsPath))) { - return Promise.reject(errors.create(toErrorMessage(error), { + return Promise.reject(createErrorWithActions(toErrorMessage(error), { actions: [ new Action('workbench.files.action.createMissingFile', nls.localize('createFile', "Create File"), null, true, () => { return this.fileService.updateContent(input.getResource(), '').then(() => this.editorService.openEditor({ @@ -196,7 +196,7 @@ export class TextFileEditor extends BaseTextEditor { if ((error).fileOperationResult === FileOperationResult.FILE_EXCEED_MEMORY_LIMIT) { const memoryLimit = Math.max(MIN_MAX_MEMORY_SIZE_MB, +this.configurationService.getValue(null, 'files.maxMemoryForLargeFilesMB') || FALLBACK_MAX_MEMORY_SIZE_MB); - return Promise.reject(errors.create(toErrorMessage(error), { + return Promise.reject(createErrorWithActions(toErrorMessage(error), { actions: [ new Action('workbench.window.action.relaunchWithIncreasedMemoryLimit', nls.localize('relaunchWithIncreasedMemoryLimit', "Restart with {0} MB", memoryLimit), null, true, () => { return this.windowsService.relaunch({ diff --git a/src/vs/workbench/parts/files/common/files.ts b/src/vs/workbench/parts/files/common/files.ts index ec77e28a9f1..b98dd326616 100644 --- a/src/vs/workbench/parts/files/common/files.ts +++ b/src/vs/workbench/parts/files/common/files.ts @@ -189,7 +189,7 @@ export class FileOnDiskContentProvider implements ITextModelContentProvider { } else if (createAsNeeded) { const fileOnDiskModel = this.modelService.getModel(fileOnDiskResource); - let mode: TPromise; + let mode: Promise; if (fileOnDiskModel) { mode = this.modeService.getOrCreateMode(fileOnDiskModel.getModeId()); } else { diff --git a/src/vs/workbench/parts/files/electron-browser/fileCommands.ts b/src/vs/workbench/parts/files/electron-browser/fileCommands.ts index d854936c9cd..ec20c823dd0 100644 --- a/src/vs/workbench/parts/files/electron-browser/fileCommands.ts +++ b/src/vs/workbench/parts/files/electron-browser/fileCommands.ts @@ -491,7 +491,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_S, handler: (accessor, resourceOrObject: URI | object | { from: string }) => { const editorService = accessor.get(IEditorService); - let resource: URI = undefined; + let resource: URI | undefined = undefined; if (resourceOrObject && 'from' in resourceOrObject && resourceOrObject.from === 'menu') { resource = toResource(editorService.activeEditor); } else { diff --git a/src/vs/workbench/parts/files/electron-browser/media/files-dark.svg b/src/vs/workbench/parts/files/electron-browser/media/files-dark.svg index 7e3e59b370b..7a9ddef571a 100644 --- a/src/vs/workbench/parts/files/electron-browser/media/files-dark.svg +++ b/src/vs/workbench/parts/files/electron-browser/media/files-dark.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.ts b/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.ts index 4eb36fe7ab2..c263de9468c 100644 --- a/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.ts +++ b/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.ts @@ -93,7 +93,8 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo label: localize('neverAgain', "Don't Show Again"), isSecondary: true, run: () => this.storageService.store(donotAskUpdateKey, true) - }] + }], + { sticky: true } ); } } @@ -200,8 +201,10 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo logUserReaction('neverShowAgain'); } }], - () => { - logUserReaction('cancelled'); + { + onCancel: () => { + logUserReaction('cancelled'); + } } ); diff --git a/src/vs/workbench/parts/markers/electron-browser/markersModel.ts b/src/vs/workbench/parts/markers/electron-browser/markersModel.ts index 0ff5bbf3759..62ee4c1e7fc 100644 --- a/src/vs/workbench/parts/markers/electron-browser/markersModel.ts +++ b/src/vs/workbench/parts/markers/electron-browser/markersModel.ts @@ -35,8 +35,8 @@ export abstract class NodeWithId { export class ResourceMarkers extends NodeWithId { - private _name: string = null; - private _path: string = null; + private _name: string | null = null; + private _path: string | null = null; private _allFixesPromise: Promise; markers: Marker[] = []; diff --git a/src/vs/workbench/parts/markers/electron-browser/markersPanel.ts b/src/vs/workbench/parts/markers/electron-browser/markersPanel.ts index 0206943dcab..af06d7e88b5 100644 --- a/src/vs/workbench/parts/markers/electron-browser/markersPanel.ts +++ b/src/vs/workbench/parts/markers/electron-browser/markersPanel.ts @@ -40,7 +40,7 @@ export class MarkersPanel extends Panel { private delayedRefresh: Delayer; private lastSelectedRelativeTop: number = 0; - private currentActiveResource: URI = null; + private currentActiveResource: URI | null = null; private tree: WorkbenchTree; private rangeHighlightDecorations: RangeHighlightDecorations; @@ -403,7 +403,7 @@ export class MarkersPanel extends Panel { } private getResourceForCurrentActiveResource(): ResourceMarkers { - let res: ResourceMarkers = null; + let res: ResourceMarkers | null = null; if (this.currentActiveResource) { this.markersWorkbenchService.markersModel.forEachFilteredResource(resource => { if (!res && resource.uri.toString() === this.currentActiveResource.toString()) { diff --git a/src/vs/workbench/parts/navigation/common/navigation.contribution.ts b/src/vs/workbench/parts/navigation/common/navigation.contribution.ts deleted file mode 100644 index 1b09f14f1dc..00000000000 --- a/src/vs/workbench/parts/navigation/common/navigation.contribution.ts +++ /dev/null @@ -1,11 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Registry } from 'vs/platform/registry/common/platform'; -import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; -import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; -import { HistoryNavigationKeybindingsChangedContribution } from 'vs/workbench/parts/navigation/common/removedKeybindingsContribution'; - -Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(HistoryNavigationKeybindingsChangedContribution, LifecyclePhase.Eventually); \ No newline at end of file diff --git a/src/vs/workbench/parts/navigation/common/removedKeybindingsContribution.ts b/src/vs/workbench/parts/navigation/common/removedKeybindingsContribution.ts deleted file mode 100644 index a0ec0ee57f6..00000000000 --- a/src/vs/workbench/parts/navigation/common/removedKeybindingsContribution.ts +++ /dev/null @@ -1,76 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; -import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { localize } from 'vs/nls'; -import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; - -// TODO@Sandeep remove me after a while -export class HistoryNavigationKeybindingsChangedContribution implements IWorkbenchContribution { - - private previousCommands: string[] = [ - - 'search.history.showNextIncludePattern', - 'search.history.showPreviousIncludePattern', - 'search.history.showNextExcludePattern', - 'search.history.showPreviousExcludePattern', - 'search.history.showNext', - 'search.history.showPrevious', - 'search.replaceHistory.showNext', - 'search.replaceHistory.showPrevious', - - 'find.history.showPrevious', - 'find.history.showNext', - - 'workbench.action.terminal.findWidget.history.showNext', - 'workbench.action.terminal.findWidget.history.showPrevious', - - 'editor.action.extensioneditor.showNextFindTerm', - 'editor.action.extensioneditor.showPreviousFindTerm', - - 'editor.action.webvieweditor.showNextFindTerm', - 'editor.action.webvieweditor.showPreviousFindTerm', - - 'repl.action.historyNext', - 'repl.action.historyPrevious' - ]; - - constructor( - @INotificationService private readonly notificationService: INotificationService, - @IKeybindingService private readonly keybindingService: IKeybindingService, - @IPreferencesService private readonly preferencesService: IPreferencesService, - @IStorageService private readonly storageService: IStorageService - ) { - this.showRemovedWarning(); - } - - private showRemovedWarning(): void { - const key = 'donotshow.historyNavigation.warning'; - if (!this.storageService.getBoolean(key, StorageScope.GLOBAL, false)) { - const keybindingsToRemove = this.keybindingService.getKeybindings().filter(keybinding => !keybinding.isDefault && this.previousCommands.indexOf(keybinding.command) !== -1); - if (keybindingsToRemove.length) { - const message = localize('showDeprecatedWarningMessage', "History navigation commands have changed. Please update your keybindings to use following new commands: 'history.showPrevious' and 'history.showNext'"); - this.notificationService.prompt(Severity.Warning, message, [ - { - label: localize('Open Keybindings', "Open Keybindings File"), - run: () => this.preferencesService.openGlobalKeybindingSettings(true) - }, - { - label: localize('more information', "More Information..."), - run: () => null - }, - { - label: localize('Do not show again', "Don't show again"), - isSecondary: true, - run: () => this.storageService.store(key, true, StorageScope.GLOBAL) - } - ]); - } - } - } -} diff --git a/src/vs/workbench/parts/outline/electron-browser/outlinePanel.ts b/src/vs/workbench/parts/outline/electron-browser/outlinePanel.ts index 89ec1101973..a8dcbd21ea0 100644 --- a/src/vs/workbench/parts/outline/electron-browser/outlinePanel.ts +++ b/src/vs/workbench/parts/outline/electron-browser/outlinePanel.ts @@ -98,7 +98,7 @@ class RequestOracle { private _update(): void { let widget = this._editorService.activeTextEditorWidget; - let codeEditor: ICodeEditor = undefined; + let codeEditor: ICodeEditor | undefined = undefined; if (isCodeEditor(widget)) { codeEditor = widget; } else if (isDiffEditor(widget)) { diff --git a/src/vs/workbench/parts/output/electron-browser/outputServices.ts b/src/vs/workbench/parts/output/electron-browser/outputServices.ts index b80224bd040..5df181c452a 100644 --- a/src/vs/workbench/parts/output/electron-browser/outputServices.ts +++ b/src/vs/workbench/parts/output/electron-browser/outputServices.ts @@ -681,7 +681,7 @@ class BufferredOutputChannel extends Disposable implements OutputChannel { readonly id: string; readonly label: string; - readonly file: URI = null; + readonly file: URI | null = null; scrollLock: boolean = false; protected _onDidAppendedContent: Emitter = new Emitter(); diff --git a/src/vs/workbench/parts/preferences/browser/keybindingWidgets.ts b/src/vs/workbench/parts/preferences/browser/keybindingWidgets.ts index 3e56b8ec671..08ba1f42e27 100644 --- a/src/vs/workbench/parts/preferences/browser/keybindingWidgets.ts +++ b/src/vs/workbench/parts/preferences/browser/keybindingWidgets.ts @@ -150,8 +150,8 @@ export class DefineKeybindingWidget extends Widget { private _outputNode: HTMLElement; private _showExistingKeybindingsNode: HTMLElement; - private _firstPart: ResolvedKeybinding = null; - private _chordPart: ResolvedKeybinding = null; + private _firstPart: ResolvedKeybinding | null = null; + private _chordPart: ResolvedKeybinding | null = null; private _isVisible: boolean = false; private _onHide = this._register(new Emitter()); diff --git a/src/vs/workbench/parts/preferences/browser/keybindingsEditorContribution.ts b/src/vs/workbench/parts/preferences/browser/keybindingsEditorContribution.ts index c00c6b10b51..5e27756c8a8 100644 --- a/src/vs/workbench/parts/preferences/browser/keybindingsEditorContribution.ts +++ b/src/vs/workbench/parts/preferences/browser/keybindingsEditorContribution.ts @@ -233,7 +233,7 @@ export class KeybindingEditorDecorationsRenderer extends Disposable { return this._createDecoration(true, null, null, model, value); } const resolvedKeybinding = resolvedKeybindings[0]; - let usLabel: string = null; + let usLabel: string | null = null; if (resolvedKeybinding instanceof WindowsNativeResolvedKeybinding) { usLabel = resolvedKeybinding.getUSLabel(); } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts b/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts index 97e40e22e39..0cf3f2e83f2 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesWidgets.ts @@ -259,6 +259,10 @@ export class SettingsGroupTitleWidget extends Widget implements IViewZone { if (previousPosition.lineNumber === currentPosition.lineNumber) { return false; } + if (!this.settingsGroup.range) { + // #60460? + return false; + } if (currentPosition.lineNumber === this.settingsGroup.range.startLineNumber - 1 || currentPosition.lineNumber === this.settingsGroup.range.startLineNumber - 2) { return true; } diff --git a/src/vs/workbench/parts/preferences/browser/settingsTree.ts b/src/vs/workbench/parts/preferences/browser/settingsTree.ts index 9a0e908dd2b..6de41e6defb 100644 --- a/src/vs/workbench/parts/preferences/browser/settingsTree.ts +++ b/src/vs/workbench/parts/preferences/browser/settingsTree.ts @@ -1053,7 +1053,6 @@ export class SettingsRenderer implements ITreeRenderer { template.labelElement.textContent = element.displayLabel; template.labelElement.title = titleTooltip; - this.renderValue(element, templateId, template); template.descriptionElement.innerHTML = ''; if (element.setting.descriptionIsMarkdown) { const renderedDescription = this.renderDescriptionMarkdown(element, element.description, template.toDispose); @@ -1065,11 +1064,6 @@ export class SettingsRenderer implements ITreeRenderer { const baseId = (element.displayCategory + '_' + element.displayLabel).replace(/ /g, '_').toLowerCase(); template.descriptionElement.id = baseId + '_setting_description'; - if (templateId === SETTINGS_BOOL_TEMPLATE_ID) { - // Add checkbox target to description clickable and able to toggle checkbox - template.descriptionElement.setAttribute('checkbox_label_target_id', baseId + '_setting_item'); - } - template.otherOverridesElement.innerHTML = ''; if (element.overriddenScopeList.length) { @@ -1097,8 +1091,11 @@ export class SettingsRenderer implements ITreeRenderer { e.stopPropagation(); }); } + } + this.renderValue(element, templateId, template); + // Remove tree attributes - sometimes overridden by tree - should be managed there template.containerElement.parentElement.removeAttribute('role'); template.containerElement.parentElement.removeAttribute('aria-level'); @@ -1165,23 +1162,7 @@ export class SettingsRenderer implements ITreeRenderer { template.onChange = onChange; // Setup and add ARIA attributes - // Create id and label for control/input element - parent is wrapper div - const baseId = (dataElement.displayCategory + '_' + dataElement.displayLabel).replace(/ /g, '_').toLowerCase(); - const modifiedText = dataElement.isConfigured ? 'Modified' : ''; - const label = dataElement.displayCategory + ' ' + dataElement.displayLabel + ' ' + modifiedText; - - // We use the parent control div for the aria-labelledby target - // Does not appear you can use the direct label on the element itself within a tree - template.checkbox.domNode.parentElement.id = baseId + '_setting_label'; - template.checkbox.domNode.parentElement.setAttribute('aria-label', label); - - // Labels will not be read on descendent input elements of the parent treeitem - // unless defined as role=treeitem and indirect aria-labelledby approach - template.checkbox.domNode.id = baseId + '_setting_item'; - template.checkbox.domNode.setAttribute('role', 'checkbox'); - template.checkbox.domNode.setAttribute('aria-labelledby', baseId + '_setting_label'); - template.checkbox.domNode.setAttribute('aria-describedby', baseId + '_setting_description'); - + this.setElementAriaLabels(dataElement, SETTINGS_BOOL_TEMPLATE_ID, template); } private renderEnum(dataElement: SettingsTreeSettingElement, template: ISettingEnumItemTemplate, onChange: (value: string) => void): void { @@ -1198,12 +1179,7 @@ export class SettingsRenderer implements ITreeRenderer { isMarkdown: enumDescriptionsAreMarkdown })); - const modifiedText = dataElement.isConfigured ? 'Modified' : ''; - - // Use ',.' as reader pause - const label = dataElement.displayCategory + ' ' + dataElement.displayLabel + ',. ' + modifiedText; - const baseId = (dataElement.displayCategory + '_' + dataElement.displayLabel).replace(/ /g, '_').toLowerCase(); - + const label = this.setElementAriaLabels(dataElement, SETTINGS_ENUM_TEMPLATE_ID, template); template.selectBox.setAriaLabel(label); const idx = dataElement.setting.enum.indexOf(dataElement.value); @@ -1211,75 +1187,33 @@ export class SettingsRenderer implements ITreeRenderer { template.selectBox.select(idx); template.onChange = idx => onChange(dataElement.setting.enum[idx]); - if (template.controlElement.firstElementChild) { - // SelectBox needs to have treeitem changed to combobox to read correctly within tree - template.controlElement.firstElementChild.setAttribute('role', 'combobox'); - template.controlElement.firstElementChild.setAttribute('aria-describedby', baseId + '_setting_description settings_aria_more_actions_shortcut_label'); - } - template.enumDescriptionElement.innerHTML = ''; } private renderText(dataElement: SettingsTreeSettingElement, template: ISettingTextItemTemplate, onChange: (value: string) => void): void { - const modifiedText = dataElement.isConfigured ? 'Modified' : ''; - // Use ',.' as reader pause - const label = dataElement.displayCategory + ' ' + dataElement.displayLabel + ',. ' + modifiedText; + const label = this.setElementAriaLabels(dataElement, SETTINGS_TEXT_TEMPLATE_ID, template); + template.onChange = null; template.inputBox.value = dataElement.value; template.onChange = value => { renderValidations(dataElement, template, false, label); onChange(value); }; - // Setup and add ARIA attributes - // Create id and label for control/input element - parent is wrapper div - const baseId = (dataElement.displayCategory + '_' + dataElement.displayLabel).replace(/ /g, '_').toLowerCase(); - - // We use the parent control div for the aria-labelledby target - // Does not appear you can use the direct label on the element itself within a tree - template.inputBox.inputElement.parentElement.id = baseId + '_setting_label'; - template.inputBox.inputElement.parentElement.setAttribute('aria-label', label); - - // Labels will not be read on descendent input elements of the parent treeitem - // unless defined as role=treeitem and indirect aria-labelledby approach - template.inputBox.inputElement.id = baseId + '_setting_item'; - template.inputBox.inputElement.setAttribute('role', 'textbox'); - template.inputBox.inputElement.setAttribute('aria-labelledby', baseId + '_setting_label'); - template.inputBox.inputElement.setAttribute('aria-describedby', baseId + '_setting_description settings_aria_more_actions_shortcut_label'); - renderValidations(dataElement, template, true, label); } - private renderNumber(dataElement: SettingsTreeSettingElement, template: ISettingTextItemTemplate, onChange: (value: number) => void): void { - const modifiedText = dataElement.isConfigured ? 'Modified' : ''; - - // Use ',.' as reader pause - const label = dataElement.displayCategory + ' ' + dataElement.displayLabel + ' number,. ' + modifiedText; const numParseFn = (dataElement.valueType === 'integer' || dataElement.valueType === 'nullable-integer') ? parseInt : parseFloat; const nullNumParseFn = (dataElement.valueType === 'nullable-integer' || dataElement.valueType === 'nullable-number') ? (v => v === '' ? null : numParseFn(v)) : numParseFn; + const label = this.setElementAriaLabels(dataElement, SETTINGS_NUMBER_TEMPLATE_ID, template); + template.onChange = null; template.inputBox.value = dataElement.value; template.onChange = value => { renderValidations(dataElement, template, false, label); onChange(nullNumParseFn(value)); }; - // Setup and add ARIA attributes - // Create id and label for control/input element - parent is wrapper div - const baseId = (dataElement.displayCategory + '_' + dataElement.displayLabel).replace(/ /g, '_').toLowerCase(); - - // We use the parent control div for the aria-labelledby target - // Does not appear you can use the direct label on the element itself within a tree - template.inputBox.inputElement.parentElement.id = baseId + '_setting_label'; - template.inputBox.inputElement.parentElement.setAttribute('aria-label', label); - - // Labels will not be read on descendent input elements of the parent treeitem - // unless defined as role=treeitem and indirect aria-labelledby approach - template.inputBox.inputElement.id = baseId + '_setting_item'; - template.inputBox.inputElement.setAttribute('role', 'textbox'); - template.inputBox.inputElement.setAttribute('aria-labelledby', baseId + '_setting_label'); - template.inputBox.inputElement.setAttribute('aria-describedby', baseId + '_setting_description settings_aria_more_actions_shortcut_label'); - renderValidations(dataElement, template, true, label); } @@ -1293,6 +1227,64 @@ export class SettingsRenderer implements ITreeRenderer { template.onChange = () => this._onDidOpenSettings.fire(dataElement.setting.key); } + + private setElementAriaLabels(dataElement: SettingsTreeSettingElement, templateId: string, template: ISettingItemTemplate): string { + // Create base Id for element references + const baseId = (dataElement.displayCategory + '_' + dataElement.displayLabel).replace(/ /g, '_').toLowerCase(); + + const modifiedText = template.otherOverridesElement.textContent ? + template.otherOverridesElement.textContent : (dataElement.isConfigured ? localize('settings.Modified', ' Modified. ') : ''); + + let itemElement = null; + + // Use '.' as reader pause + let label = dataElement.displayCategory + ' ' + dataElement.displayLabel + '. '; + + // Setup and add ARIA attributes + // Create id and label for control/input element - parent is wrapper div + + if (templateId === SETTINGS_TEXT_TEMPLATE_ID) { + if (itemElement = (template).inputBox.inputElement) { + itemElement.setAttribute('role', 'textbox'); + label += modifiedText; + } + } else if (templateId === SETTINGS_NUMBER_TEMPLATE_ID) { + if (itemElement = (template).inputBox.inputElement) { + itemElement.setAttribute('role', 'textbox'); + label += ' number. ' + modifiedText; + } + } else if (templateId === SETTINGS_BOOL_TEMPLATE_ID) { + if (itemElement = (template).checkbox.domNode) { + itemElement.setAttribute('role', 'checkbox'); + label += modifiedText; + // Add checkbox target to description clickable and able to toggle checkbox + template.descriptionElement.setAttribute('checkbox_label_target_id', baseId + '_setting_item'); + } + } else if (templateId === SETTINGS_ENUM_TEMPLATE_ID) { + if (itemElement = template.controlElement.firstElementChild) { + itemElement.setAttribute('role', 'combobox'); + label += modifiedText; + } + } else { + // Don't change attributes if we don't know what we areFunctions + return ''; + } + + // We don't have control element, return empty label + if (!itemElement) { + return ''; + } + + // Labels will not be read on descendent input elements of the parent treeitem + // unless defined as roles for input items + // voiceover does not seem to use labeledby correctly, set labels directly on input elements + itemElement.id = baseId + '_setting_item'; + itemElement.setAttribute('aria-label', label); + itemElement.setAttribute('aria-describedby', baseId + '_setting_description settings_aria_more_actions_shortcut_label'); + + return label; + } + disposeTemplate(tree: ITree, templateId: string, template: IDisposableTemplate): void { dispose(template.toDispose); } @@ -1429,6 +1421,9 @@ export class SettingsAccessibilityProvider implements IAccessibilityProvider { } if (element instanceof SettingsTreeSettingElement) { + if (element.valueType === 'boolean') { + return ''; + } return localize('settingRowAriaLabel', "{0} {1}, Setting", element.displayCategory, element.displayLabel); } diff --git a/src/vs/workbench/parts/preferences/electron-browser/settingsEditor2.ts b/src/vs/workbench/parts/preferences/electron-browser/settingsEditor2.ts index e03c01ac0d8..09a2bf8c930 100644 --- a/src/vs/workbench/parts/preferences/electron-browser/settingsEditor2.ts +++ b/src/vs/workbench/parts/preferences/electron-browser/settingsEditor2.ts @@ -1176,7 +1176,7 @@ export class SettingsEditor2 extends BaseEditor { return this.localSearchDelayer.trigger(() => { if (searchInProgress && !searchInProgress.token.isCancellationRequested) { return this.localFilterPreferences(query).then(result => { - if (!result.exactMatch) { + if (result && !result.exactMatch) { this.remoteSearchThrottle.trigger(() => { return searchInProgress && !searchInProgress.token.isCancellationRequested ? this.remoteSearchPreferences(query, this.searchInProgress.token) : diff --git a/src/vs/workbench/parts/quickopen/browser/gotoLineHandler.ts b/src/vs/workbench/parts/quickopen/browser/gotoLineHandler.ts index 4a5c49617c3..a2e4eccb86a 100644 --- a/src/vs/workbench/parts/quickopen/browser/gotoLineHandler.ts +++ b/src/vs/workbench/parts/quickopen/browser/gotoLineHandler.ts @@ -44,7 +44,7 @@ export class GotoLineAction extends QuickOpenAction { if (isDiffEditor(activeTextEditorWidget)) { activeTextEditorWidget = activeTextEditorWidget.getModifiedEditor(); } - let restoreOptions: IEditorOptions = null; + let restoreOptions: IEditorOptions | null = null; if (isCodeEditor(activeTextEditorWidget)) { const config = activeTextEditorWidget.getConfiguration(); diff --git a/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts b/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts index edb54a680cf..eb66494ac57 100644 --- a/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts +++ b/src/vs/workbench/parts/quickopen/browser/gotoSymbolHandler.ts @@ -117,8 +117,8 @@ class OutlineModel extends QuickOpenModel { // Mark all type groups const visibleResults = this.getEntries(true); if (visibleResults.length > 0 && searchValue.indexOf(SCOPE_PREFIX) === 0) { - let currentType: SymbolKind = null; - let currentResult: SymbolEntry = null; + let currentType: SymbolKind | null = null; + let currentResult: SymbolEntry | null = null; let typeCounter = 0; for (let i = 0; i < visibleResults.length; i++) { diff --git a/src/vs/workbench/parts/scm/electron-browser/media/icon-dark.svg b/src/vs/workbench/parts/scm/electron-browser/media/icon-dark.svg index 2b8f14d282b..7c6c3fd2d08 100644 --- a/src/vs/workbench/parts/scm/electron-browser/media/icon-dark.svg +++ b/src/vs/workbench/parts/scm/electron-browser/media/icon-dark.svg @@ -1,12 +1 @@ - - - - repo-forked - Created with Sketch. - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/vs/workbench/parts/scm/electron-browser/media/scmViewlet.css b/src/vs/workbench/parts/scm/electron-browser/media/scmViewlet.css index cf9ddfc9f2f..0a15ee8d540 100644 --- a/src/vs/workbench/parts/scm/electron-browser/media/scmViewlet.css +++ b/src/vs/workbench/parts/scm/electron-browser/media/scmViewlet.css @@ -5,7 +5,6 @@ .monaco-workbench > .activitybar > .content .monaco-action-bar .action-label.scm { -webkit-mask: url('icon-dark.svg') no-repeat 50% 50%; - -webkit-mask-size: 19px; } .monaco-workbench .viewlet.scm-viewlet .collapsible.header .actions { diff --git a/src/vs/workbench/parts/search/browser/openAnythingHandler.ts b/src/vs/workbench/parts/search/browser/openAnythingHandler.ts index cb8aae32fb5..a7c98574b4c 100644 --- a/src/vs/workbench/parts/search/browser/openAnythingHandler.ts +++ b/src/vs/workbench/parts/search/browser/openAnythingHandler.ts @@ -168,7 +168,7 @@ export class OpenAnythingHandler extends QuickOpenHandler { return null; } - let range: IRange = null; + let range: IRange | null = null; // Find Line/Column number from search value using RegExp const patternMatch = OpenAnythingHandler.LINE_COLON_PATTERN.exec(value); diff --git a/src/vs/workbench/parts/search/browser/replaceService.ts b/src/vs/workbench/parts/search/browser/replaceService.ts index 975d8f3f1e1..92aa7ab0116 100644 --- a/src/vs/workbench/parts/search/browser/replaceService.ts +++ b/src/vs/workbench/parts/search/browser/replaceService.ts @@ -104,7 +104,7 @@ export class ReplaceService implements IReplaceService { public replace(match: Match): TPromise; public replace(files: FileMatch[], progress?: IProgressRunner): TPromise; public replace(match: FileMatchOrMatch, progress?: IProgressRunner, resource?: URI): TPromise; - public replace(arg: any, progress: IProgressRunner = null, resource: URI = null): TPromise { + public replace(arg: any, progress: IProgressRunner | null = null, resource: URI | null = null): TPromise { const edits: ResourceTextEdit[] = this.createEdits(arg, resource); return this.bulkEditorService.apply({ edits }, { progress }).then(() => this.textFileService.saveAll(edits.map(e => e.resource))); @@ -174,7 +174,7 @@ export class ReplaceService implements IReplaceService { replaceModel.pushEditOperations([], mergeSort(modelEdits, (a, b) => Range.compareRangesUsingStarts(a.range, b.range)), () => []); } - private createEdits(arg: FileMatchOrMatch | FileMatch[], resource: URI = null): ResourceTextEdit[] { + private createEdits(arg: FileMatchOrMatch | FileMatch[], resource: URI | null = null): ResourceTextEdit[] { const edits: ResourceTextEdit[] = []; if (arg instanceof Match) { @@ -198,7 +198,7 @@ export class ReplaceService implements IReplaceService { return edits; } - private createEdit(match: Match, text: string, resource: URI = null): ResourceTextEdit { + private createEdit(match: Match, text: string, resource: URI | null = null): ResourceTextEdit { let fileMatch: FileMatch = match.parent(); let resourceEdit: ResourceTextEdit = { resource: resource !== null ? resource : fileMatch.resource(), diff --git a/src/vs/workbench/parts/search/browser/searchView.ts b/src/vs/workbench/parts/search/browser/searchView.ts index 1efd9fc31aa..e5e56b1b987 100644 --- a/src/vs/workbench/parts/search/browser/searchView.ts +++ b/src/vs/workbench/parts/search/browser/searchView.ts @@ -1429,12 +1429,16 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { this.viewModel.searchResult.rangeHighlightDecorations.removeHighlightRange(); } - return this.editorGroupsService.activateGroup(editor.group); + if (editor) { + return this.editorGroupsService.activateGroup(editor.group); + } else { + return TPromise.wrap(null); + } }, errors.onUnexpectedError); } private getSelectionFrom(element: FileMatchOrMatch): any { - let match: Match = null; + let match: Match | null = null; if (element instanceof Match) { match = element; } diff --git a/src/vs/workbench/parts/search/browser/searchWidget.ts b/src/vs/workbench/parts/search/browser/searchWidget.ts index 031b0d44d2d..b56f1a72fae 100644 --- a/src/vs/workbench/parts/search/browser/searchWidget.ts +++ b/src/vs/workbench/parts/search/browser/searchWidget.ts @@ -47,7 +47,7 @@ export interface ISearchWidgetOptions { class ReplaceAllAction extends Action { - private static fgInstance: ReplaceAllAction = null; + private static fgInstance: ReplaceAllAction | null = null; public static readonly ID: string = 'search.action.replaceAll'; static get INSTANCE(): ReplaceAllAction { @@ -57,7 +57,7 @@ class ReplaceAllAction extends Action { return ReplaceAllAction.fgInstance; } - private _searchWidget: SearchWidget = null; + private _searchWidget: SearchWidget | null = null; constructor() { super(ReplaceAllAction.ID, '', 'action-replace-all', false); diff --git a/src/vs/workbench/parts/search/common/searchModel.ts b/src/vs/workbench/parts/search/common/searchModel.ts index bcac923dd60..306759ab096 100644 --- a/src/vs/workbench/parts/search/common/searchModel.ts +++ b/src/vs/workbench/parts/search/common/searchModel.ts @@ -583,7 +583,12 @@ export class SearchResult extends Disposable { const otherFileMatches: IFileMatch[] = []; this._folderMatches.forEach((folderMatch) => rawPerFolder.set(folderMatch.resource(), [])); allRaw.forEach(rawFileMatch => { - let folderMatch = this.getFolderMatch(rawFileMatch.resource); + const folderMatch = this.getFolderMatch(rawFileMatch.resource); + if (!folderMatch) { + // foldermatch was previously removed by user or disposed for some reason + return; + } + if (folderMatch.resource()) { rawPerFolder.get(folderMatch.resource()).push(rawFileMatch); } else { @@ -677,7 +682,7 @@ export class SearchResult extends Disposable { return; } this._showHighlights = value; - let selectedMatch: Match = null; + let selectedMatch: Match | null = null; this.matches().forEach((fileMatch: FileMatch) => { fileMatch.updateHighlights(); if (!selectedMatch) { @@ -731,10 +736,10 @@ export class SearchResult extends Disposable { export class SearchModel extends Disposable { private _searchResult: SearchResult; - private _searchQuery: ISearchQuery = null; + private _searchQuery: ISearchQuery | null = null; private _replaceActive: boolean = false; - private _replaceString: string = null; - private _replacePattern: ReplacePattern = null; + private _replaceString: string | null = null; + private _replacePattern: ReplacePattern | null = null; private readonly _onReplaceTermChanged: Emitter = this._register(new Emitter()); public readonly onReplaceTermChanged: Event = this._onReplaceTermChanged.event; @@ -920,8 +925,8 @@ export interface ISearchWorkbenchService { */ export class RangeHighlightDecorations implements IDisposable { - private _decorationId: string = null; - private _model: ITextModel = null; + private _decorationId: string | null = null; + private _model: ITextModel | null = null; private _modelDisposables: IDisposable[] = []; constructor( diff --git a/src/vs/workbench/parts/search/electron-browser/media/search-dark.svg b/src/vs/workbench/parts/search/electron-browser/media/search-dark.svg index 35bda969be7..8ac0bc9bfdd 100644 --- a/src/vs/workbench/parts/search/electron-browser/media/search-dark.svg +++ b/src/vs/workbench/parts/search/electron-browser/media/search-dark.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/vs/workbench/parts/search/test/common/searchModel.test.ts b/src/vs/workbench/parts/search/test/common/searchModel.test.ts index 5edf921fd3a..c54dad1e84f 100644 --- a/src/vs/workbench/parts/search/test/common/searchModel.test.ts +++ b/src/vs/workbench/parts/search/test/common/searchModel.test.ts @@ -80,7 +80,7 @@ suite('SearchModel', () => { }); }); - function searchServiceWithResults(results: IFileMatch[], complete: ISearchComplete = null): ISearchService { + function searchServiceWithResults(results: IFileMatch[], complete: ISearchComplete | null = null): ISearchService { return { search(query: ISearchQuery, token?: CancellationToken, onProgress?: (result: ISearchProgressItem) => void): TPromise { return new TPromise(resolve => { diff --git a/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.ts b/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.ts index d139ab915b9..382c6f58e94 100644 --- a/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.ts +++ b/src/vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution.ts @@ -112,7 +112,8 @@ class LanguageSurvey { nextStorage2Service.set(IS_CANDIDATE_KEY, false, StorageScope.GLOBAL); nextStorage2Service.set(SKIP_VERSION_KEY, pkg.version, StorageScope.GLOBAL); } - }] + }], + { sticky: true } ); } } diff --git a/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.ts b/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.ts index c0792b838cf..2ca8dcb15d9 100644 --- a/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.ts +++ b/src/vs/workbench/parts/surveys/electron-browser/nps.contribution.ts @@ -79,7 +79,8 @@ class NPSContribution implements IWorkbenchContribution { nextStorage2Service.set(IS_CANDIDATE_KEY, false, StorageScope.GLOBAL); nextStorage2Service.set(SKIP_VERSION_KEY, pkg.version, StorageScope.GLOBAL); } - }] + }], + { sticky: true } ); } } diff --git a/src/vs/workbench/parts/tasks/common/problemCollectors.ts b/src/vs/workbench/parts/tasks/common/problemCollectors.ts index 1a65b43db20..98c2c309454 100644 --- a/src/vs/workbench/parts/tasks/common/problemCollectors.ts +++ b/src/vs/workbench/parts/tasks/common/problemCollectors.ts @@ -116,7 +116,7 @@ export class AbstractProblemCollector implements IDisposable { } protected tryFindMarker(line: string): ProblemMatch { - let result: ProblemMatch = null; + let result: ProblemMatch | null = null; if (this.activeMatcher) { result = this.activeMatcher.next(line); if (result) { diff --git a/src/vs/workbench/parts/tasks/common/problemMatcher.ts b/src/vs/workbench/parts/tasks/common/problemMatcher.ts index 1e4a347bbd7..f3ba6fef51a 100644 --- a/src/vs/workbench/parts/tasks/common/problemMatcher.ts +++ b/src/vs/workbench/parts/tasks/common/problemMatcher.ts @@ -349,7 +349,7 @@ abstract class AbstractLineMatcher implements ILineMatcher { } private getSeverity(data: ProblemData): MarkerSeverity { - let result: Severity = null; + let result: Severity | null = null; if (data.severity) { let value = data.severity; if (value) { @@ -893,7 +893,7 @@ export class ProblemPatternParser extends Parser { } private createRegularExpression(value: string): RegExp { - let result: RegExp = null; + let result: RegExp | null = null; if (!value) { return result; } @@ -1256,7 +1256,7 @@ export class ProblemMatcherParser extends Parser { } private createProblemMatcher(description: Config.ProblemMatcher): ProblemMatcher { - let result: ProblemMatcher = null; + let result: ProblemMatcher | null = null; let owner = description.owner ? description.owner : UUID.generateUuid(); let source = Types.isString(description.source) ? description.source : undefined; @@ -1264,8 +1264,8 @@ export class ProblemMatcherParser extends Parser { if (!applyTo) { applyTo = ApplyToKind.allDocuments; } - let fileLocation: FileLocationKind = undefined; - let filePrefix: string = undefined; + let fileLocation: FileLocationKind | undefined = undefined; + let filePrefix: string | undefined = undefined; let kind: FileLocationKind; if (Types.isUndefined(description.fileLocation)) { @@ -1428,7 +1428,7 @@ export class ProblemMatcherParser extends Parser { } private createRegularExpression(value: string): RegExp { - let result: RegExp = null; + let result: RegExp | null = null; if (!value) { return result; } diff --git a/src/vs/workbench/parts/tasks/common/taskTemplates.ts b/src/vs/workbench/parts/tasks/common/taskTemplates.ts index 06dcc4790bd..1a1d1ee1217 100644 --- a/src/vs/workbench/parts/tasks/common/taskTemplates.ts +++ b/src/vs/workbench/parts/tasks/common/taskTemplates.ts @@ -123,7 +123,7 @@ const maven: TaskEntry = { ].join('\n') }; -let _templates: TaskEntry[] = null; +let _templates: TaskEntry[] | null = null; export function getTemplates(): TaskEntry[] { if (!_templates) { _templates = [dotnetBuild, msbuild, maven].sort((a, b) => { diff --git a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts index de917d70e8c..1743ae4e780 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts @@ -508,7 +508,8 @@ class TaskService implements ITaskService { [{ label: nls.localize('reloadWindow', "Reload Window"), run: () => this._windowService.reloadWindow() - }] + }], + { sticky: true } ); return; } else { @@ -1232,7 +1233,8 @@ class TaskService implements ITaskService { { label: nls.localize('restartTask', "Restart Task"), run: () => this.restart(task) - }] + }], + { sticky: true } ); } else { throw new TaskError(Severity.Warning, nls.localize('TaskSystem.active', 'There is already a task running. Terminate it first before executing another task.'), TaskErrors.RunningTask); @@ -1721,7 +1723,7 @@ class TaskService implements ITaskService { if (res.confirmed) { return this._taskSystem.terminateAll().then((responses) => { let success = true; - let code: number = undefined; + let code: number | undefined = undefined; for (let response of responses) { success = success && response.success; // We only have a code in the old output runner which only has one task diff --git a/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts b/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts index c1d9eb253ac..63f49b40ec2 100644 --- a/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts +++ b/src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts @@ -320,10 +320,10 @@ export class TerminalTaskSystem implements ITaskSystem { } private executeInTerminal(task: CustomTask | ContributedTask, trigger: string, resolver: VariableResolver): TPromise { - let terminal: ITerminalInstance = undefined; - let executedCommand: string = undefined; - let error: TaskError = undefined; - let promise: TPromise = undefined; + let terminal: ITerminalInstance | undefined = undefined; + let executedCommand: string | undefined = undefined; + let error: TaskError | undefined = undefined; + let promise: TPromise | undefined = undefined; if (task.isBackground) { promise = new TPromise((resolve, reject) => { const problemMatchers = this.resolveMatchers(resolver, task.problemMatchers); @@ -533,7 +533,7 @@ export class TerminalTaskSystem implements ITaskSystem { waitOnExit = '\u200B'; } } - let shellLaunchConfig: IShellLaunchConfig = undefined; + let shellLaunchConfig: IShellLaunchConfig | undefined = undefined; let isShellCommand = task.command.runtime === RuntimeType.Shell; if (isShellCommand) { shellLaunchConfig = { name: terminalName, executable: null, args: null, waitOnExit }; @@ -896,7 +896,7 @@ export class TerminalTaskSystem implements ITaskSystem { // to the current working directory. return path.join(cwd, command); } - let paths: string[] = undefined; + let paths: string[] | undefined = undefined; // The options can override the PATH. So consider that PATH if present. if (options && options.env) { // Path can be named in many different ways and for the execution it doesn't matter diff --git a/src/vs/workbench/parts/tasks/node/taskConfiguration.ts b/src/vs/workbench/parts/tasks/node/taskConfiguration.ts index 076bd31dec2..324da8a9616 100644 --- a/src/vs/workbench/parts/tasks/node/taskConfiguration.ts +++ b/src/vs/workbench/parts/tasks/node/taskConfiguration.ts @@ -1561,7 +1561,7 @@ namespace Globals { export function from(config: ExternalTaskRunnerConfiguration, context: ParseContext): Globals { let result = fromBase(config, context); - let osGlobals: Globals = undefined; + let osGlobals: Globals | undefined = undefined; if (config.windows && context.platform === Platform.Windows) { osGlobals = fromBase(config.windows, context); } else if (config.osx && context.platform === Platform.Mac) { diff --git a/src/vs/workbench/parts/tasks/test/electron-browser/configuration.test.ts b/src/vs/workbench/parts/tasks/test/electron-browser/configuration.test.ts index b6d780f5c20..46fe439f55d 100644 --- a/src/vs/workbench/parts/tasks/test/electron-browser/configuration.test.ts +++ b/src/vs/workbench/parts/tasks/test/electron-browser/configuration.test.ts @@ -26,7 +26,7 @@ class ProblemReporter implements IProblemReporter { private _validationStatus: ValidationStatus = new ValidationStatus(); public receivedMessage: boolean = false; - public lastMessage: string = undefined; + public lastMessage: string | undefined = undefined; public info(message: string): void { this.log(message); diff --git a/src/vs/workbench/parts/terminal/browser/terminalWidgetManager.ts b/src/vs/workbench/parts/terminal/browser/terminalWidgetManager.ts index f40dd1407d7..9fb22f4deb3 100644 --- a/src/vs/workbench/parts/terminal/browser/terminalWidgetManager.ts +++ b/src/vs/workbench/parts/terminal/browser/terminalWidgetManager.ts @@ -8,8 +8,8 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; const WIDGET_HEIGHT = 29; export class TerminalWidgetManager implements IDisposable { - private _container: HTMLElement; - private _xtermViewport: HTMLElement; + private _container: HTMLElement | null; + private _xtermViewport: HTMLElement | null; private _messageWidget: MessageWidget; private _messageListeners: IDisposable[] = []; @@ -25,7 +25,7 @@ export class TerminalWidgetManager implements IDisposable { } public dispose(): void { - if (this._container) { + if (this._container && this._container.parentElement) { this._container.parentElement.removeChild(this._container); this._container = null; } @@ -35,11 +35,17 @@ export class TerminalWidgetManager implements IDisposable { private _initTerminalHeightWatcher(terminalWrapper: HTMLElement) { // Watch the xterm.js viewport for style changes and do a layout if it changes this._xtermViewport = terminalWrapper.querySelector('.xterm-viewport'); + if (!this._xtermViewport) { + return; + } const mutationObserver = new MutationObserver(() => this._refreshHeight()); mutationObserver.observe(this._xtermViewport, { attributes: true, attributeFilter: ['style'] }); } public showMessage(left: number, top: number, text: string): void { + if (!this._container) { + return; + } dispose(this._messageWidget); this._messageListeners = dispose(this._messageListeners); this._messageWidget = new MessageWidget(this._container, left, top, text); @@ -53,6 +59,9 @@ export class TerminalWidgetManager implements IDisposable { } private _refreshHeight(): void { + if (!this._container || !this._xtermViewport) { + return; + } this._container.style.height = this._xtermViewport.style.height; } } diff --git a/src/vs/workbench/parts/terminal/common/terminal.ts b/src/vs/workbench/parts/terminal/common/terminal.ts index 3f698d71998..00eab412d0c 100644 --- a/src/vs/workbench/parts/terminal/common/terminal.ts +++ b/src/vs/workbench/parts/terminal/common/terminal.ts @@ -17,17 +17,17 @@ export const TERMINAL_SERVICE_ID = 'terminalService'; /** A context key that is set when there is at least one opened integrated terminal. */ export const KEYBINDING_CONTEXT_TERMINAL_IS_OPEN = new RawContextKey('terminalIsOpen', false); /** A context key that is set when the integrated terminal has focus. */ -export const KEYBINDING_CONTEXT_TERMINAL_FOCUS = new RawContextKey('terminalFocus', undefined); +export const KEYBINDING_CONTEXT_TERMINAL_FOCUS = new RawContextKey('terminalFocus', false); /** A context key that is set when the integrated terminal does not have focus. */ export const KEYBINDING_CONTEXT_TERMINAL_NOT_FOCUSED: ContextKeyExpr = KEYBINDING_CONTEXT_TERMINAL_FOCUS.toNegated(); /** A keybinding context key that is set when the integrated terminal has text selected. */ -export const KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED = new RawContextKey('terminalTextSelected', undefined); +export const KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED = new RawContextKey('terminalTextSelected', false); /** A keybinding context key that is set when the integrated terminal does not have text selected. */ export const KEYBINDING_CONTEXT_TERMINAL_TEXT_NOT_SELECTED: ContextKeyExpr = KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED.toNegated(); /** A context key that is set when the find widget in integrated terminal is visible. */ -export const KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_VISIBLE = new RawContextKey('terminalFindWidgetVisible', undefined); +export const KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_VISIBLE = new RawContextKey('terminalFindWidgetVisible', false); /** A context key that is set when the find widget in integrated terminal is not visible. */ export const KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_NOT_VISIBLE: ContextKeyExpr = KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_VISIBLE.toNegated(); /** A context key that is set when the find widget find input in integrated terminal is focused. */ diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts b/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts index 4a5d86980b4..2f15b591e8d 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminal.contribution.ts @@ -283,6 +283,7 @@ configurationRegistry.registerConfiguration({ TERMINAL_COMMAND_ID.SCROLL_TO_TOP, TERMINAL_COMMAND_ID.SCROLL_UP_LINE, TERMINAL_COMMAND_ID.SCROLL_UP_PAGE, + TERMINAL_COMMAND_ID.SEND_SEQUENCE, TERMINAL_COMMAND_ID.SELECT_ALL, TERMINAL_COMMAND_ID.SELECT_TO_NEXT_COMMAND, TERMINAL_COMMAND_ID.SELECT_TO_NEXT_LINE, @@ -471,6 +472,9 @@ actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(RenameTerminalAc actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusTerminalFindWidgetAction, FocusTerminalFindWidgetAction.ID, FocusTerminalFindWidgetAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_F }, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Focus Find Widget', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusTerminalFindWidgetAction, FocusTerminalFindWidgetAction.ID, FocusTerminalFindWidgetAction.LABEL, { + primary: KeyMod.CtrlCmd | KeyCode.KEY_F +}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Focus Find Widget', category); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(HideTerminalFindWidgetAction, HideTerminalFindWidgetAction.ID, HideTerminalFindWidgetAction.LABEL, { primary: KeyCode.Escape, secondary: [KeyMod.Shift | KeyCode.Escape] diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts index 978e8fe5ea5..b04479169bb 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalConfigHelper.ts @@ -119,10 +119,10 @@ export class TerminalConfigHelper implements ITerminalConfigHelper { // Work around bad font on Fedora/Ubuntu if (!this.config.fontFamily) { if (isFedora) { - fontFamily = '\'DejaVu Sans Mono\''; + fontFamily = '\'DejaVu Sans Mono\', monospace'; } if (isUbuntu) { - fontFamily = '\'Ubuntu Mono\''; + fontFamily = '\'Ubuntu Mono\', monospace'; // Ubuntu mono is somehow smaller, so set fontSize a bit larger to get the same perceived size. fontSize = this._toInteger(fontSize + 2, MINIMUM_FONT_SIZE, MAXIMUM_FONT_SIZE, EDITOR_FONT_DEFAULTS.fontSize); diff --git a/src/vs/workbench/parts/terminal/node/terminal.ts b/src/vs/workbench/parts/terminal/node/terminal.ts index a45a93547b2..6b05bdc2b04 100644 --- a/src/vs/workbench/parts/terminal/node/terminal.ts +++ b/src/vs/workbench/parts/terminal/node/terminal.ts @@ -45,7 +45,7 @@ export function getDefaultShell(p: platform.Platform): string { return getTerminalDefaultShellUnixLike(); } -let _TERMINAL_DEFAULT_SHELL_UNIX_LIKE: string = null; +let _TERMINAL_DEFAULT_SHELL_UNIX_LIKE: string | null = null; function getTerminalDefaultShellUnixLike(): string { if (!_TERMINAL_DEFAULT_SHELL_UNIX_LIKE) { let unixLikeTerminal = 'sh'; @@ -61,7 +61,7 @@ function getTerminalDefaultShellUnixLike(): string { return _TERMINAL_DEFAULT_SHELL_UNIX_LIKE; } -let _TERMINAL_DEFAULT_SHELL_WINDOWS: string = null; +let _TERMINAL_DEFAULT_SHELL_WINDOWS: string | null = null; function getTerminalDefaultShellWindows(): string { if (!_TERMINAL_DEFAULT_SHELL_WINDOWS) { const isAtLeastWindows10 = platform.isWindows && parseFloat(os.release()) >= 10; diff --git a/src/vs/workbench/parts/terminal/node/windowsShellHelper.ts b/src/vs/workbench/parts/terminal/node/windowsShellHelper.ts index 4ebb5c4abf9..c1df2481eda 100644 --- a/src/vs/workbench/parts/terminal/node/windowsShellHelper.ts +++ b/src/vs/workbench/parts/terminal/node/windowsShellHelper.ts @@ -27,7 +27,7 @@ let windowsProcessTree: typeof WindowsProcessTreeType; export class WindowsShellHelper { private _onCheckShell: Emitter>; private _isDisposed: boolean; - private _currentRequest: Promise; + private _currentRequest: Promise | null; private _newLineFeed: boolean; public constructor( diff --git a/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts b/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts index 1cee2372412..45cfb3c02a3 100644 --- a/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts +++ b/src/vs/workbench/parts/terminal/test/electron-browser/terminalConfigHelper.test.ts @@ -31,9 +31,9 @@ suite('Workbench - TerminalConfigHelper', () => { configHelper = new TerminalConfigHelper(configurationService, null, null, null); configHelper.panelContainer = fixture; if (isFedora) { - assert.equal(configHelper.getFont().fontFamily, '\'DejaVu Sans Mono\'', 'Fedora should have its font overridden when terminal.integrated.fontFamily not set'); + assert.equal(configHelper.getFont().fontFamily, '\'DejaVu Sans Mono\', monospace', 'Fedora should have its font overridden when terminal.integrated.fontFamily not set'); } if (isUbuntu) { - assert.equal(configHelper.getFont().fontFamily, '\'Ubuntu Mono\'', 'Ubuntu should have its font overridden when terminal.integrated.fontFamily not set'); + assert.equal(configHelper.getFont().fontFamily, '\'Ubuntu Mono\', monospace', 'Ubuntu should have its font overridden when terminal.integrated.fontFamily not set'); } else { assert.equal(configHelper.getFont().fontFamily, 'foo', 'editor.fontFamily should be the fallback when terminal.integrated.fontFamily not set'); } diff --git a/src/vs/workbench/parts/themes/test/electron-browser/themes.test.contribution.ts b/src/vs/workbench/parts/themes/test/electron-browser/themes.test.contribution.ts index 80bd3118690..8ac211ef77d 100644 --- a/src/vs/workbench/parts/themes/test/electron-browser/themes.test.contribution.ts +++ b/src/vs/workbench/parts/themes/test/electron-browser/themes.test.contribution.ts @@ -95,7 +95,7 @@ class Snapper { private _themedTokenize(grammar: IGrammar, lines: string[]): IThemedToken[] { let colorMap = TokenizationRegistry.getColorMap(); - let state: StackElement = null; + let state: StackElement | null = null; let result: IThemedToken[] = [], resultLen = 0; for (let i = 0, len = lines.length; i < len; i++) { let line = lines[i]; @@ -123,13 +123,13 @@ class Snapper { } private _tokenize(grammar: IGrammar, lines: string[]): IToken[] { - let state: StackElement = null; + let state: StackElement | null = null; let result: IToken[] = [], resultLen = 0; for (let i = 0, len = lines.length; i < len; i++) { let line = lines[i]; let tokenizationResult = grammar.tokenizeLine(line, state); - let lastScopes: string = null; + let lastScopes: string | null = null; for (let j = 0, lenJ = tokenizationResult.tokens.length; j < lenJ; j++) { let token = tokenizationResult.tokens[j]; diff --git a/src/vs/workbench/parts/update/electron-browser/media/update.contribution.css b/src/vs/workbench/parts/update/electron-browser/media/update.contribution.css index 54537cdcfa7..486837877ef 100644 --- a/src/vs/workbench/parts/update/electron-browser/media/update.contribution.css +++ b/src/vs/workbench/parts/update/electron-browser/media/update.contribution.css @@ -5,5 +5,4 @@ .update-activity { -webkit-mask: url('update.svg') no-repeat 50% 50%; - -webkit-mask-size: 22px; } diff --git a/src/vs/workbench/parts/update/electron-browser/media/update.svg b/src/vs/workbench/parts/update/electron-browser/media/update.svg index c97bb48bdcc..b8bb9af637e 100644 --- a/src/vs/workbench/parts/update/electron-browser/media/update.svg +++ b/src/vs/workbench/parts/update/electron-browser/media/update.svg @@ -1 +1 @@ -configure \ No newline at end of file + \ No newline at end of file diff --git a/src/vs/workbench/parts/update/electron-browser/update.ts b/src/vs/workbench/parts/update/electron-browser/update.ts index 9bd72bb6031..68e4617fc97 100644 --- a/src/vs/workbench/parts/update/electron-browser/update.ts +++ b/src/vs/workbench/parts/update/electron-browser/update.ts @@ -134,7 +134,8 @@ export class ProductContribution implements IWorkbenchContribution { const uri = URI.parse(product.releaseNotesUrl); openerService.open(uri); } - }] + }], + { sticky: true } ); }); } @@ -204,7 +205,8 @@ export class Win3264BitContribution implements IWorkbenchContribution { neverShowAgain.action.run(handle); neverShowAgain.action.dispose(); } - }] + }], + { sticky: true } ); } } @@ -357,7 +359,8 @@ export class UpdateContribution implements IGlobalActivity { action.run(); action.dispose(); } - }] + }], + { sticky: true } ); } @@ -383,7 +386,8 @@ export class UpdateContribution implements IGlobalActivity { action.run(); action.dispose(); } - }] + }], + { sticky: true } ); } @@ -437,7 +441,8 @@ export class UpdateContribution implements IGlobalActivity { action.run(); action.dispose(); } - }] + }], + { sticky: true } ); } diff --git a/src/vs/workbench/parts/webview/electron-browser/webview.contribution.ts b/src/vs/workbench/parts/webview/electron-browser/webview.contribution.ts index 6ef9c2393d6..2fb89c454e1 100644 --- a/src/vs/workbench/parts/webview/electron-browser/webview.contribution.ts +++ b/src/vs/workbench/parts/webview/electron-browser/webview.contribution.ts @@ -20,6 +20,7 @@ import { HideWebViewEditorFindCommand, OpenWebviewDeveloperToolsAction, ReloadWe import { WebviewEditor } from './webviewEditor'; import { WebviewEditorInput } from './webviewEditorInput'; import { IWebviewEditorService, WebviewEditorService } from './webviewEditorService'; +import { InputFocusedContextKey } from 'vs/platform/workbench/common/contextkeys'; (Registry.as(EditorExtensions.Editors)).registerEditor(new EditorDescriptor( WebviewEditor, @@ -65,7 +66,7 @@ export function registerWebViewCommands(editorId: string): void { const selectAllCommand = new SelectAllWebviewEditorCommand({ id: SelectAllWebviewEditorCommand.ID, - precondition: contextKeyExpr, + precondition: ContextKeyExpr.and(contextKeyExpr, ContextKeyExpr.not(InputFocusedContextKey)), kbOpts: { primary: KeyMod.CtrlCmd | KeyCode.KEY_A, weight: KeybindingWeight.EditorContrib diff --git a/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.ts b/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.ts index bb81291105a..60656404659 100644 --- a/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.ts +++ b/src/vs/workbench/parts/welcome/gettingStarted/electron-browser/telemetryOptOut.ts @@ -67,7 +67,8 @@ export class TelemetryOptOut implements IWorkbenchContribution { [{ label: localize('telemetryOptOut.readMore', "Read More"), run: () => openerService.open(URI.parse(this.optOutUrl)) - }] + }], + { sticky: true } ); }) .then(null, onUnexpectedError); @@ -136,7 +137,10 @@ export class TelemetryOptOut implements IWorkbenchContribution { } } ], - logTelemetry + { + sticky: true, + onCancel: logTelemetry + } ); this.experimentService.markAsCompleted(experimentId); }); diff --git a/src/vs/workbench/parts/welcome/gettingStarted/test/common/gettingStarted.test.ts b/src/vs/workbench/parts/welcome/gettingStarted/test/common/gettingStarted.test.ts index 51502da8bf7..74aabc4cbaf 100644 --- a/src/vs/workbench/parts/welcome/gettingStarted/test/common/gettingStarted.test.ts +++ b/src/vs/workbench/parts/welcome/gettingStarted/test/common/gettingStarted.test.ts @@ -8,11 +8,11 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { IStorageService } from 'vs/platform/storage/common/storage'; suite('Workbench - GettingStarted', () => { - let instantiation: TestInstantiationService = null; - let welcomePageEnvConfig: string = null; - let hideWelcomeSettingsValue: string = null; - // let machineId: string = null; - let appName: string = null; + let instantiation: TestInstantiationService | null = null; + let welcomePageEnvConfig: string | null = null; + let hideWelcomeSettingsValue: string | null = null; + // let machineId: string | null = null; + let appName: string | null = null; suiteSetup(() => { instantiation = new TestInstantiationService(); diff --git a/src/vs/workbench/services/configuration/common/configurationModels.ts b/src/vs/workbench/services/configuration/common/configurationModels.ts index b6cc66f1dd4..f5fbcc43d26 100644 --- a/src/vs/workbench/services/configuration/common/configurationModels.ts +++ b/src/vs/workbench/services/configuration/common/configurationModels.ts @@ -225,7 +225,7 @@ export class Configuration extends BaseConfiguration { export class AllKeysConfigurationChangeEvent extends AbstractConfigurationChangeEvent implements IConfigurationChangeEvent { - private _changedConfiguration: ConfigurationModel = null; + private _changedConfiguration: ConfigurationModel | null = null; constructor(private _configuration: Configuration, readonly source: ConfigurationTarget, readonly sourceConfig: any) { super(); } diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts index ee609ab6307..1fa003f77ca 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts @@ -273,7 +273,8 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter { [{ label: nls.localize('reloadWindow', "Reload Window"), run: () => this._windowService.reloadWindow() - }] + }], + { sticky: true } ); }, 10000); } diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts index 9bd90935790..7811fe39444 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts @@ -51,14 +51,14 @@ import { RuntimeExtensionsInput } from 'vs/workbench/services/extensions/electro const LOG_EXTENSION_HOST_COMMUNICATION = false; const LOG_USE_COLORS = true; -let _SystemExtensionsRoot: string = null; +let _SystemExtensionsRoot: string | null = null; function getSystemExtensionsRoot(): string { if (!_SystemExtensionsRoot) { _SystemExtensionsRoot = path.normalize(path.join(getPathFromAmdModule(require, ''), '..', 'extensions')); } return _SystemExtensionsRoot; } -let _ExtraDevSystemExtensionsRoot: string = null; +let _ExtraDevSystemExtensionsRoot: string | null = null; function getExtraDevSystemExtensionsRoot(): string { if (!_ExtraDevSystemExtensionsRoot) { _ExtraDevSystemExtensionsRoot = path.normalize(path.join(getPathFromAmdModule(require, ''), '..', '.build', 'builtInExtensions')); @@ -185,7 +185,7 @@ export class ExtensionHostProcessManager extends Disposable { private _createExtensionHostCustomers(protocol: IMessagePassingProtocol): ExtHostExtensionServiceShape { - let logger: IRPCProtocolLogger = null; + let logger: IRPCProtocolLogger | null = null; if (LOG_EXTENSION_HOST_COMMUNICATION || this._environmentService.logExtensionHostCommunication) { logger = new RPCLogger(); } @@ -426,7 +426,10 @@ export class ExtensionService extends Disposable implements IExtensionService { } private _onResponsiveStateChanged(state: ResponsiveState): void { - if (this._isDev) { + // Do not show the notification anymore + // See https://github.com/Microsoft/vscode/issues/60318 + const DISABLE_PROMPT = true; + if (this._isDev || DISABLE_PROMPT) { return; // do not show any notification when developing an extension (https://github.com/Microsoft/vscode/issues/59251) } diff --git a/src/vs/workbench/services/extensions/electron-browser/inactiveExtensionUrlHandler.ts b/src/vs/workbench/services/extensions/electron-browser/inactiveExtensionUrlHandler.ts index 16bffb800bb..d667af60c1b 100644 --- a/src/vs/workbench/services/extensions/electron-browser/inactiveExtensionUrlHandler.ts +++ b/src/vs/workbench/services/extensions/electron-browser/inactiveExtensionUrlHandler.ts @@ -194,7 +194,7 @@ export class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { } } - // Extnesion is not installed + // Extension is not installed else { const galleryExtension = await this.galleryService.getExtension(extensionIdentifier); if (galleryExtension) { @@ -224,7 +224,8 @@ export class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { [{ label: reloadActionLabel, run: () => this.reloadAndHandle(uri) - }] + }], + { sticky: true } ); } } catch (e) { diff --git a/src/vs/workbench/services/extensions/node/extensionPoints.ts b/src/vs/workbench/services/extensions/node/extensionPoints.ts index 9a0f2d2e135..dba83c817aa 100644 --- a/src/vs/workbench/services/extensions/node/extensionPoints.ts +++ b/src/vs/workbench/services/extensions/node/extensionPoints.ts @@ -527,7 +527,7 @@ export class ExtensionScanner { /** * Scan a list of extensions defined in `absoluteFolderPath` */ - public static async scanExtensions(input: ExtensionScannerInput, log: ILog, resolver: IExtensionResolver = null): Promise { + public static async scanExtensions(input: ExtensionScannerInput, log: ILog, resolver: IExtensionResolver | null = null): Promise { const absoluteFolderPath = input.absoluteFolderPath; const isBuiltin = input.isBuiltin; const isUnderDevelopment = input.isUnderDevelopment; diff --git a/src/vs/workbench/services/extensions/node/lazyPromise.ts b/src/vs/workbench/services/extensions/node/lazyPromise.ts index 5d370cb4b8a..a620e3aaf86 100644 --- a/src/vs/workbench/services/extensions/node/lazyPromise.ts +++ b/src/vs/workbench/services/extensions/node/lazyPromise.ts @@ -8,9 +8,9 @@ import { onUnexpectedError } from 'vs/base/common/errors'; export class LazyPromise implements Thenable { - private _actual: TPromise; - private _actualOk: ValueCallback; - private _actualErr: ErrorCallback; + private _actual: TPromise | null; + private _actualOk: ValueCallback | null; + private _actualErr: ErrorCallback | null; private _hasValue: boolean; private _value: any; @@ -33,15 +33,15 @@ export class LazyPromise implements Thenable { this._actual = new TPromise((c, e) => { this._actualOk = c; this._actualErr = e; + + if (this._hasValue) { + this._actualOk(this._value); + } + + if (this._hasErr) { + this._actualErr(this._err); + } }); - - if (this._hasValue) { - this._actualOk(this._value); - } - - if (this._hasErr) { - this._actualErr(this._err); - } } return this._actual; } @@ -55,7 +55,7 @@ export class LazyPromise implements Thenable { this._value = value; if (this._actual) { - this._actualOk(value); + this._actualOk!(value); } } @@ -68,7 +68,7 @@ export class LazyPromise implements Thenable { this._err = err; if (this._actual) { - this._actualErr(err); + this._actualErr!(err); } else { // If nobody's listening at this point, it is safe to assume they never will, // since resolving this promise is always "async" diff --git a/src/vs/workbench/services/extensions/node/rpcProtocol.ts b/src/vs/workbench/services/extensions/node/rpcProtocol.ts index 92d1e2889dd..b30a0c6d638 100644 --- a/src/vs/workbench/services/extensions/node/rpcProtocol.ts +++ b/src/vs/workbench/services/extensions/node/rpcProtocol.ts @@ -124,7 +124,7 @@ export class RPCProtocol extends Disposable implements IRPCProtocol { private _unresponsiveTime: number; private _asyncCheckUresponsive: RunOnceScheduler; - constructor(protocol: IMessagePassingProtocol, logger: IRPCProtocolLogger = null, transformer: IURITransformer = null) { + constructor(protocol: IMessagePassingProtocol, logger: IRPCProtocolLogger | null = null, transformer: IURITransformer | null = null) { super(); this._protocol = protocol; this._logger = logger; @@ -409,7 +409,7 @@ export class RPCProtocol extends Disposable implements IRPCProtocol { const pendingReply = this._pendingRPCReplies[callId]; delete this._pendingRPCReplies[callId]; - let err: Error = null; + let err: Error | null = null; if (value && value.$isError) { err = new Error(); err.name = value.name; @@ -443,7 +443,7 @@ export class RPCProtocol extends Disposable implements IRPCProtocol { if (this._isDisposed) { return TPromise.wrapError(errors.canceled()); } - let cancellationToken: CancellationToken = null; + let cancellationToken: CancellationToken | null = null; if (args.length > 0 && CancellationToken.isCancellationToken(args[args.length - 1])) { cancellationToken = args.pop(); } diff --git a/src/vs/workbench/services/files/electron-browser/fileService.ts b/src/vs/workbench/services/files/electron-browser/fileService.ts index 69e5afe2ae4..7bfe5e647e3 100644 --- a/src/vs/workbench/services/files/electron-browser/fileService.ts +++ b/src/vs/workbench/services/files/electron-browser/fileService.ts @@ -144,7 +144,8 @@ export class FileService extends Disposable implements IFileService { label: nls.localize('neverShowAgain', "Don't Show Again"), isSecondary: true, run: () => this.storageService.store(FileService.NET_VERSION_ERROR_IGNORE_KEY, true, StorageScope.WORKSPACE) - }] + }], + { sticky: true } ); } @@ -161,7 +162,8 @@ export class FileService extends Disposable implements IFileService { label: nls.localize('neverShowAgain', "Don't Show Again"), isSecondary: true, run: () => this.storageService.store(FileService.ENOSPC_ERROR_IGNORE_KEY, true, StorageScope.WORKSPACE) - }] + }], + { sticky: true } ); } } @@ -1147,7 +1149,7 @@ export class StatResolver { else { // Convert the paths from options.resolveTo to absolute paths - let absoluteTargetPaths: string[] = null; + let absoluteTargetPaths: string[] | null = null; if (options && options.resolveTo) { absoluteTargetPaths = []; options.resolveTo.forEach(resource => { diff --git a/src/vs/workbench/services/files/node/watcher/unix/chokidarWatcherService.ts b/src/vs/workbench/services/files/node/watcher/unix/chokidarWatcherService.ts index 3b0d1ea6095..4e907ad9d5d 100644 --- a/src/vs/workbench/services/files/node/watcher/unix/chokidarWatcherService.ts +++ b/src/vs/workbench/services/files/node/watcher/unix/chokidarWatcherService.ts @@ -311,7 +311,7 @@ function isIgnored(path: string, requests: ExtendedWatcherRequest[]): boolean { */ export function normalizeRoots(requests: IWatcherRequest[]): { [basePath: string]: IWatcherRequest[] } { requests = requests.sort((r1, r2) => r1.basePath.localeCompare(r2.basePath)); - let prevRequest: IWatcherRequest = null; + let prevRequest: IWatcherRequest | null = null; let result: { [basePath: string]: IWatcherRequest[] } = Object.create(null); for (let request of requests) { let basePath = request.basePath; diff --git a/src/vs/workbench/services/keybinding/test/keyboardMapperTestUtils.ts b/src/vs/workbench/services/keybinding/test/keyboardMapperTestUtils.ts index 82f4de6f644..c1a812bf381 100644 --- a/src/vs/workbench/services/keybinding/test/keyboardMapperTestUtils.ts +++ b/src/vs/workbench/services/keybinding/test/keyboardMapperTestUtils.ts @@ -53,7 +53,7 @@ export function readRawMapping(file: string): TPromise { return readFile(getPathFromAmdModule(require, `vs/workbench/services/keybinding/test/${file}.js`)).then((buff) => { let contents = buff.toString(); let func = new Function('define', contents); - let rawMappings: T = null; + let rawMappings: T | null = null; func(function (value: T) { rawMappings = value; }); diff --git a/src/vs/workbench/services/mode/common/workbenchModeService.ts b/src/vs/workbench/services/mode/common/workbenchModeService.ts index 0a5daec589d..f0f732ddef1 100644 --- a/src/vs/workbench/services/mode/common/workbenchModeService.ts +++ b/src/vs/workbench/services/mode/common/workbenchModeService.ts @@ -5,7 +5,6 @@ import * as nls from 'vs/nls'; import * as resources from 'vs/base/common/resources'; -import { TPromise } from 'vs/base/common/winjs.base'; import * as mime from 'vs/base/common/mime'; import { IFilesConfiguration, FILES_ASSOCIATIONS_CONFIG } from 'vs/platform/files/common/files'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; @@ -91,7 +90,7 @@ export const languagesExtPoint: IExtensionPoint = export class WorkbenchModeServiceImpl extends ModeServiceImpl { private _configurationService: IConfigurationService; private _extensionService: IExtensionService; - private _onReadyPromise: TPromise; + private _onReadyPromise: Promise; constructor( @IExtensionService extensionService: IExtensionService, @@ -149,12 +148,14 @@ export class WorkbenchModeServiceImpl extends ModeServiceImpl { }); } - protected _onReady(): TPromise { + protected _onReady(): Promise { if (!this._onReadyPromise) { - this._onReadyPromise = this._extensionService.whenInstalledExtensionsRegistered().then(() => { - this.updateMime(); - return true; - }); + this._onReadyPromise = Promise.resolve( + this._extensionService.whenInstalledExtensionsRegistered().then(() => { + this.updateMime(); + return true; + }) + ); } return this._onReadyPromise; diff --git a/src/vs/workbench/services/notification/common/notificationService.ts b/src/vs/workbench/services/notification/common/notificationService.ts index d7ac3afa37c..b8eadaddd49 100644 --- a/src/vs/workbench/services/notification/common/notificationService.ts +++ b/src/vs/workbench/services/notification/common/notificationService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { INotificationService, INotification, INotificationHandle, Severity, NotificationMessage, INotificationActions, IPromptChoice } from 'vs/platform/notification/common/notification'; +import { INotificationService, INotification, INotificationHandle, Severity, NotificationMessage, INotificationActions, IPromptChoice, IPromptOptions } from 'vs/platform/notification/common/notification'; import { INotificationsModel, NotificationsModel, ChoiceAction } from 'vs/workbench/common/notifications'; import { dispose, Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { once } from 'vs/base/common/event'; @@ -52,7 +52,7 @@ export class NotificationService extends Disposable implements INotificationServ return this.model.notify(notification); } - prompt(severity: Severity, message: string, choices: IPromptChoice[], onCancel?: () => void): INotificationHandle { + prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle { const toDispose: IDisposable[] = []; let choiceClicked = false; @@ -82,7 +82,7 @@ export class NotificationService extends Disposable implements INotificationServ }); // Show notification with actions - handle = this.notify({ severity, message, actions }); + handle = this.notify({ severity, message, actions, sticky: options && options.sticky }); once(handle.onDidClose)(() => { @@ -90,8 +90,8 @@ export class NotificationService extends Disposable implements INotificationServ dispose(toDispose); // Indicate cancellation to the outside if no action was executed - if (typeof onCancel === 'function' && !choiceClicked) { - onCancel(); + if (options && typeof options.onCancel === 'function' && !choiceClicked) { + options.onCancel(); } }); diff --git a/src/vs/workbench/services/preferences/browser/preferencesService.ts b/src/vs/workbench/services/preferences/browser/preferencesService.ts index fc708c03923..3cb58c9e65d 100644 --- a/src/vs/workbench/services/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/services/preferences/browser/preferencesService.ts @@ -44,7 +44,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic _serviceBrand: any; - private lastOpenedSettingsInput: PreferencesEditorInput = null; + private lastOpenedSettingsInput: PreferencesEditorInput | null = null; private readonly _onDispose: Emitter = new Emitter(); diff --git a/src/vs/workbench/services/preferences/common/keybindingsEditorModel.ts b/src/vs/workbench/services/preferences/common/keybindingsEditorModel.ts index 00026d6716e..6b8b5655bd6 100644 --- a/src/vs/workbench/services/preferences/common/keybindingsEditorModel.ts +++ b/src/vs/workbench/services/preferences/common/keybindingsEditorModel.ts @@ -254,12 +254,12 @@ export class KeybindingsEditorModel extends EditorModel { class KeybindingItemMatches { - public readonly commandIdMatches: IMatch[] = null; - public readonly commandLabelMatches: IMatch[] = null; - public readonly commandDefaultLabelMatches: IMatch[] = null; - public readonly sourceMatches: IMatch[] = null; - public readonly whenMatches: IMatch[] = null; - public readonly keybindingMatches: KeybindingMatches = null; + public readonly commandIdMatches: IMatch[] | null = null; + public readonly commandLabelMatches: IMatch[] | null = null; + public readonly commandDefaultLabelMatches: IMatch[] | null = null; + public readonly sourceMatches: IMatch[] | null = null; + public readonly whenMatches: IMatch[] | null = null; + public readonly keybindingMatches: KeybindingMatches | null = null; constructor(private modifierLabels: ModifierLabels, keybindingItem: IKeybindingItem, searchValue: string, words: string[], keybindingWords: string[], completeMatch: boolean) { if (!completeMatch) { diff --git a/src/vs/workbench/services/preferences/common/preferencesModels.ts b/src/vs/workbench/services/preferences/common/preferencesModels.ts index 5ebf357c101..950371a1a7d 100644 --- a/src/vs/workbench/services/preferences/common/preferencesModels.ts +++ b/src/vs/workbench/services/preferences/common/preferencesModels.ts @@ -247,9 +247,9 @@ export class Settings2EditorModel extends AbstractSettingsModel implements ISett function parse(model: ITextModel, isSettingsProperty: (currentProperty: string, previousParents: string[]) => boolean): ISettingsGroup[] { const settings: ISetting[] = []; - let overrideSetting: ISetting = null; + let overrideSetting: ISetting | null = null; - let currentProperty: string = null; + let currentProperty: string | null = null; let currentParent: any = []; let previousParents: any[] = []; let settingsPropertyIndex: number = -1; @@ -910,7 +910,7 @@ class SettingsContentBuilder { private _pushGroup(group: ISettingsGroup): ISetting { const indent = ' '; - let lastSetting: ISetting = null; + let lastSetting: ISetting | null = null; let groupStart = this.lineCountWithOffset + 1; for (const section of group.sections) { if (section.title) { diff --git a/src/vs/workbench/services/search/node/worker/searchWorker.ts b/src/vs/workbench/services/search/node/worker/searchWorker.ts index 26eef593908..de39d2f6453 100644 --- a/src/vs/workbench/services/search/node/worker/searchWorker.ts +++ b/src/vs/workbench/services/search/node/worker/searchWorker.ts @@ -124,7 +124,7 @@ export class SearchWorkerEngine { } private searchInFile(absolutePath: string, contentPattern: RegExp, fileEncoding: string, maxResults?: number, previewOptions?: ITextSearchPreviewOptions): TPromise { - let fileMatch: FileMatch = null; + let fileMatch: FileMatch | null = null; let limitReached = false; let numMatches = 0; diff --git a/src/vs/workbench/services/textMate/electron-browser/TMHelper.ts b/src/vs/workbench/services/textMate/electron-browser/TMHelper.ts index f4d8f3463aa..92fddea536b 100644 --- a/src/vs/workbench/services/textMate/electron-browser/TMHelper.ts +++ b/src/vs/workbench/services/textMate/electron-browser/TMHelper.ts @@ -18,7 +18,7 @@ export function findMatchingThemeRule(theme: IColorTheme, scopes: string[], only } function findMatchingThemeRule2(theme: IColorTheme, scope: string, parentScopes: string[], onlyColorRules: boolean): ThemeRule { - let result: ThemeRule = null; + let result: ThemeRule | null = null; // Loop backwards, to ensure the last most specific rule wins for (let i = theme.tokenColors.length - 1; i >= 0; i--) { diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index 48a1893ec24..f6e908bede0 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -492,7 +492,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil return this.backupFileService.resolveBackupContent(backup).then(backupContent => backupContent, error => null /* ignore errors */); } - protected getOrCreateMode(modeService: IModeService, preferredModeIds: string, firstLineText?: string): TPromise { + protected getOrCreateMode(modeService: IModeService, preferredModeIds: string, firstLineText?: string): Promise { return modeService.getOrCreateModeByFilepathOrFirstLine(this.resource.fsPath, firstLineText); } diff --git a/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.ts b/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.ts index 8c2223842fb..71404c276f3 100644 --- a/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.ts +++ b/src/vs/workbench/services/themes/electron-browser/fileIconThemeData.ts @@ -58,7 +58,7 @@ export class FileIconThemeData implements IFileIconTheme { return themeData; } - private static _noIconTheme: FileIconThemeData = null; + private static _noIconTheme: FileIconThemeData | null = null; static noIconTheme(): FileIconThemeData { let themeData = FileIconThemeData._noIconTheme; diff --git a/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts b/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts index 496cc5a5285..a2f7c35d755 100644 --- a/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/electron-browser/workbenchThemeService.ts @@ -119,7 +119,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { // In order to avoid paint flashing for tokens, because // themes are loaded asynchronously, we need to initialize // a color theme document with good defaults until the theme is loaded - let themeData: ColorThemeData = null; + let themeData: ColorThemeData | null = null; let persistedThemeData = this.storageService.get(PERSISTED_THEME_STORAGE_KEY); if (persistedThemeData) { themeData = ColorThemeData.fromStorageData(persistedThemeData); @@ -133,7 +133,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { this.updateDynamicCSSRules(themeData); this.applyTheme(themeData, null, true); - let iconData: FileIconThemeData = null; + let iconData: FileIconThemeData | null = null; let persistedIconThemeData = this.storageService.get(PERSISTED_ICON_THEME_STORAGE_KEY); if (persistedIconThemeData) { iconData = FileIconThemeData.fromStorageData(persistedIconThemeData); diff --git a/src/vs/workbench/test/common/memento.test.ts b/src/vs/workbench/test/common/memento.test.ts index 72f70a67f84..120be40a7f0 100644 --- a/src/vs/workbench/test/common/memento.test.ts +++ b/src/vs/workbench/test/common/memento.test.ts @@ -11,7 +11,7 @@ import { StorageService, InMemoryLocalStorage } from 'vs/platform/storage/common import { TestWorkspace } from 'vs/platform/workspace/test/common/testWorkspace'; suite('Memento', () => { - let context: Scope = undefined; + let context: Scope | undefined = undefined; let storage: StorageService; setup(() => { diff --git a/src/vs/workbench/test/common/notifications.test.ts b/src/vs/workbench/test/common/notifications.test.ts index 57d3afac04a..282f6d63df5 100644 --- a/src/vs/workbench/test/common/notifications.test.ts +++ b/src/vs/workbench/test/common/notifications.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import { NotificationsModel, NotificationViewItem, INotificationChangeEvent, NotificationChangeType, NotificationViewItemLabelKind } from 'vs/workbench/common/notifications'; import { Action } from 'vs/base/common/actions'; import { INotification, Severity } from 'vs/platform/notification/common/notification'; -import { create } from 'vs/base/common/errors'; +import { createErrorWithActions } from 'vs/base/common/errorsWithActions'; suite('Notifications', () => { @@ -102,7 +102,7 @@ suite('Notifications', () => { assert.equal(called, 1); // Error with Action - let item6 = NotificationViewItem.create({ severity: Severity.Error, message: create('Hello Error', { actions: [new Action('id', 'label')] }) }); + let item6 = NotificationViewItem.create({ severity: Severity.Error, message: createErrorWithActions('Hello Error', { actions: [new Action('id', 'label')] }) }); assert.equal(item6.actions.primary.length, 1); // Links diff --git a/src/vs/workbench/test/electron-browser/api/extHostMessagerService.test.ts b/src/vs/workbench/test/electron-browser/api/extHostMessagerService.test.ts index 7153e52f31d..c518c4148f0 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostMessagerService.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostMessagerService.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import { MainThreadMessageService } from 'vs/workbench/api/electron-browser/mainThreadMessageService'; import { TPromise } from 'vs/base/common/winjs.base'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; -import { INotificationService, INotification, NoOpNotification, INotificationHandle, Severity, IPromptChoice } from 'vs/platform/notification/common/notification'; +import { INotificationService, INotification, NoOpNotification, INotificationHandle, Severity, IPromptChoice, IPromptOptions } from 'vs/platform/notification/common/notification'; import { ICommandService } from 'vs/platform/commands/common/commands'; const emptyDialogService = new class implements IDialogService { @@ -43,7 +43,7 @@ const emptyNotificationService = new class implements INotificationService { error(...args: any[]): never { throw new Error('not implemented'); } - prompt(severity: Severity, message: string, choices: IPromptChoice[], onCancel?: () => void): INotificationHandle { + prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle { throw new Error('not implemented'); } }; @@ -69,7 +69,7 @@ class EmptyNotificationService implements INotificationService { error(message: any): void { throw new Error('Method not implemented.'); } - prompt(severity: Severity, message: string, choices: IPromptChoice[], onCancel?: () => void): INotificationHandle { + prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle { throw new Error('not implemented'); } } diff --git a/src/vs/workbench/workbench.main.ts b/src/vs/workbench/workbench.main.ts index 521eef90c18..dbaf8bcf012 100644 --- a/src/vs/workbench/workbench.main.ts +++ b/src/vs/workbench/workbench.main.ts @@ -56,16 +56,16 @@ import 'vs/workbench/parts/stats/node/stats.contribution'; import 'vs/workbench/parts/splash/electron-browser/partsSplash.contribution'; import 'vs/workbench/parts/search/electron-browser/search.contribution'; -import 'vs/workbench/parts/search/browser/searchView'; // can be packaged separately -import 'vs/workbench/parts/search/browser/openAnythingHandler'; // can be packaged separately +import 'vs/workbench/parts/search/browser/searchView'; +import 'vs/workbench/parts/search/browser/openAnythingHandler'; import 'vs/workbench/parts/scm/electron-browser/scm.contribution'; -import 'vs/workbench/parts/scm/electron-browser/scmViewlet'; // can be packaged separately +import 'vs/workbench/parts/scm/electron-browser/scmViewlet'; import 'vs/workbench/parts/debug/electron-browser/debug.contribution'; import 'vs/workbench/parts/debug/browser/debugQuickOpen'; import 'vs/workbench/parts/debug/electron-browser/repl'; -import 'vs/workbench/parts/debug/browser/debugViewlet'; // can be packaged separately +import 'vs/workbench/parts/debug/browser/debugViewlet'; import 'vs/workbench/parts/markers/electron-browser/markers.contribution'; import 'vs/workbench/parts/comments/electron-browser/comments.contribution'; @@ -79,16 +79,16 @@ import 'vs/workbench/parts/welcome/walkThrough/electron-browser/walkThrough.cont import 'vs/workbench/parts/extensions/electron-browser/extensions.contribution'; import 'vs/workbench/parts/extensions/browser/extensionsQuickOpen'; -import 'vs/workbench/parts/extensions/electron-browser/extensionsViewlet'; // can be packaged separately +import 'vs/workbench/parts/extensions/electron-browser/extensionsViewlet'; import 'vs/workbench/parts/welcome/page/electron-browser/welcomePage.contribution'; import 'vs/workbench/parts/output/electron-browser/output.contribution'; -import 'vs/workbench/parts/output/browser/outputPanel'; // can be packaged separately +import 'vs/workbench/parts/output/browser/outputPanel'; import 'vs/workbench/parts/terminal/electron-browser/terminal.contribution'; import 'vs/workbench/parts/terminal/browser/terminalQuickOpen'; -import 'vs/workbench/parts/terminal/electron-browser/terminalPanel'; // can be packaged separately +import 'vs/workbench/parts/terminal/electron-browser/terminalPanel'; import 'vs/workbench/electron-browser/workbench'; @@ -99,7 +99,6 @@ import 'vs/workbench/parts/tasks/electron-browser/task.contribution'; import 'vs/workbench/parts/emmet/browser/emmet.browser.contribution'; import 'vs/workbench/parts/emmet/electron-browser/emmet.contribution'; -// Code Editor enhacements import 'vs/workbench/parts/codeEditor/codeEditor.contribution'; import 'vs/workbench/parts/execution/electron-browser/execution.contribution'; @@ -138,8 +137,6 @@ import 'vs/workbench/parts/welcome/overlay/browser/welcomeOverlay'; import 'vs/workbench/parts/outline/electron-browser/outline.contribution'; -import 'vs/workbench/parts/navigation/common/navigation.contribution'; - -// services import 'vs/workbench/services/bulkEdit/electron-browser/bulkEditService'; + import 'vs/workbench/parts/experiments/electron-browser/experiments.contribution'; diff --git a/yarn.lock b/yarn.lock index 04640aad243..e70d99fb8d2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5649,7 +5649,7 @@ minimatch@0.3: dependencies: brace-expansion "^1.1.7" -minimatch@2.x, minimatch@^2.0.1, minimatch@^2.0.10: +minimatch@2.x, minimatch@^2.0.1: version "2.0.10" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-2.0.10.tgz#8d087c39c6b38c001b97fca7ce6d0e1e80afbac7" integrity sha1-jQh8OcazjAAbl/ynzm0OHoCvusc= @@ -9357,10 +9357,10 @@ vscode-textmate@^4.0.1: dependencies: oniguruma "^7.0.0" -vscode-xterm@3.9.0-beta5: - version "3.9.0-beta5" - resolved "https://registry.yarnpkg.com/vscode-xterm/-/vscode-xterm-3.9.0-beta5.tgz#3730966ed586632f40883852252333744ba5b9b7" - integrity sha512-MWLnQieNviCsvuV8He93N2usI2FXBGeUyNzIQNO7HsxjgIhn4zEwg3e2aSeQAAABeEkqLec5hp4vHpcqdPGU7Q== +vscode-xterm@3.9.0-beta7: + version "3.9.0-beta7" + resolved "https://registry.yarnpkg.com/vscode-xterm/-/vscode-xterm-3.9.0-beta7.tgz#435b929001354309c25e330cc187785add938c8e" + integrity sha512-UTDnACoqpQbAzzxBfwZf+sWsUxcJ+t2CHprGJ5gjXEnI6soNB3C/MFEnASMjkz0FttQafVvDMu9vhByH5xTvjg== vso-node-api@6.1.2-preview: version "6.1.2-preview"