diff --git a/.github/classifier.yml b/.github/classifier.yml index c1c067e5c53..a7bcb40c96f 100644 --- a/.github/classifier.yml +++ b/.github/classifier.yml @@ -15,7 +15,7 @@ css-less-scss: [ aeschli ], debug-console: [], debug: { - assignees: [ weinand ], + assignees: [ isidorn ], assignLabel: false }, diff-editor: [], diff --git a/.yarnrc b/.yarnrc index f1749b387ef..58d37cc88fb 100644 --- a/.yarnrc +++ b/.yarnrc @@ -1,3 +1,3 @@ disturl "https://atom.io/download/electron" -target "2.0.5" +target "2.0.7" runtime "electron" diff --git a/OSSREADME.json b/OSSREADME.json index ddfe2a1fa05..e15cccabcad 100644 --- a/OSSREADME.json +++ b/OSSREADME.json @@ -51,7 +51,7 @@ }, { "name": "electron", - "version": "2.0.5", + "version": "2.0.7", "license": "MIT", "repositoryURL": "https://github.com/electron/electron", "isProd": true diff --git a/build/gulpfile.editor.js b/build/gulpfile.editor.js index 562ee1dd754..52d1f0fcf32 100644 --- a/build/gulpfile.editor.js +++ b/build/gulpfile.editor.js @@ -122,17 +122,25 @@ gulp.task('clean-minified-editor', util.rimraf('out-editor-min')); gulp.task('minify-editor', ['clean-minified-editor', 'optimize-editor'], common.minifyTask('out-editor')); gulp.task('clean-editor-esm', util.rimraf('out-editor-esm')); -gulp.task('extract-editor-esm', ['clean-editor-esm', 'clean-editor-distro'], function () { - standalone.createESMSourcesAndResources({ - entryPoints: [ - 'vs/editor/editor.main', - 'vs/editor/editor.worker' - ], +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', outResourcesFolder: './out-monaco-editor-core/esm', - redirects: { - 'vs/base/browser/ui/octiconLabel/octiconLabel': 'vs/base/browser/ui/octiconLabel/octiconLabel.mock', - 'vs/nls': 'vs/nls.mock', + ignores: [ + 'inlineEntryPoint:0.ts', + 'inlineEntryPoint:1.ts', + 'vs/loader.js', + 'vs/nls.ts', + 'vs/nls.build.js', + 'vs/nls.d.ts', + 'vs/css.js', + 'vs/css.build.js', + 'vs/css.d.ts', + 'vs/base/worker/workerMain.ts', + ], + renames: { + 'vs/nls.mock.ts': 'vs/nls.ts' } }); }); diff --git a/build/lib/optimize.js b/build/lib/optimize.js index 4fafbd800a9..60169cf1892 100644 --- a/build/lib/optimize.js +++ b/build/lib/optimize.js @@ -20,6 +20,7 @@ var util = require("./util"); var gulpUtil = require("gulp-util"); var flatmap = require("gulp-flatmap"); var pump = require("pump"); +var i18n_1 = require("./i18n"); var REPO_ROOT_PATH = path.join(__dirname, '../..'); function log(prefix, message) { gulpUtil.log(gulpUtil.colors.cyan('[' + prefix + ']'), message); @@ -164,6 +165,10 @@ function optimizeTask(opts) { addComment: true, includeContent: true })) + .pipe(opts.languages && opts.languages.length ? i18n_1.processNlsFiles({ + fileHeader: bundledFileHeader, + languages: opts.languages + }) : es.through()) .pipe(gulp.dest(out)); }; } diff --git a/build/lib/optimize.ts b/build/lib/optimize.ts index 78328e3ce2c..038cf09dd21 100644 --- a/build/lib/optimize.ts +++ b/build/lib/optimize.ts @@ -22,7 +22,7 @@ import * as gulpUtil from 'gulp-util'; import * as flatmap from 'gulp-flatmap'; import * as pump from 'pump'; import * as sm from 'source-map'; -import { Language } from './i18n'; +import { processNlsFiles, Language } from './i18n'; const REPO_ROOT_PATH = path.join(__dirname, '../..'); @@ -239,6 +239,10 @@ export function optimizeTask(opts: IOptimizeTaskOpts): () => NodeJS.ReadWriteStr addComment: true, includeContent: true })) + .pipe(opts.languages && opts.languages.length ? processNlsFiles({ + fileHeader: bundledFileHeader, + languages: opts.languages + }) : es.through()) .pipe(gulp.dest(out)); }; } diff --git a/build/lib/standalone.js b/build/lib/standalone.js index 885d3e789f5..3e2bacc25d5 100644 --- a/build/lib/standalone.js +++ b/build/lib/standalone.js @@ -10,7 +10,6 @@ var path = require("path"); var tss = require("./treeshaking"); var REPO_ROOT = path.join(__dirname, '../../'); var SRC_DIR = path.join(REPO_ROOT, 'src'); -var OUT_EDITOR = path.join(REPO_ROOT, 'out-editor'); var dirCache = {}; function writeFile(filePath, contents) { function ensureDirs(dirPath) { @@ -76,6 +75,8 @@ 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', @@ -94,167 +95,148 @@ function extractEditor(options) { ].forEach(copyFile); } exports.extractEditor = extractEditor; -function createESMSourcesAndResources(options) { +function createESMSourcesAndResources2(options) { + var SRC_FOLDER = path.join(REPO_ROOT, options.srcFolder); var OUT_FOLDER = path.join(REPO_ROOT, options.outFolder); var OUT_RESOURCES_FOLDER = path.join(REPO_ROOT, options.outResourcesFolder); - var in_queue = Object.create(null); - var queue = []; - var enqueue = function (module) { - if (in_queue[module]) { - return; + var getDestAbsoluteFilePath = function (file) { + var dest = options.renames[file.replace(/\\/g, '/')] || file; + if (dest === 'tsconfig.json') { + return path.join(OUT_FOLDER, "../tsconfig.json"); } - in_queue[module] = true; - queue.push(module); + if (/\.ts$/.test(dest)) { + return path.join(OUT_FOLDER, dest); + } + return path.join(OUT_RESOURCES_FOLDER, dest); }; - var seenDir = {}; - var createDirectoryRecursive = function (dir) { - if (seenDir[dir]) { - return; + var allFiles = walkDirRecursive(SRC_FOLDER); + for (var i = 0; i < allFiles.length; i++) { + var file = allFiles[i]; + if (options.ignores.indexOf(file.replace(/\\/g, '/')) >= 0) { + continue; } - var lastSlash = dir.lastIndexOf('/'); - if (lastSlash === -1) { - lastSlash = dir.lastIndexOf('\\'); + 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); + write(getDestAbsoluteFilePath(file), JSON.stringify(tsConfig, null, '\t')); + continue; } - if (lastSlash !== -1) { - createDirectoryRecursive(dir.substring(0, lastSlash)); + if (/\.d\.ts$/.test(file) || /\.css$/.test(file) || /\.js$/.test(file)) { + // Transport the files directly + write(getDestAbsoluteFilePath(file), fs.readFileSync(path.join(SRC_FOLDER, file))); + continue; } - seenDir[dir] = true; - try { - fs.mkdirSync(dir); - } - catch (err) { } - }; - seenDir[REPO_ROOT] = true; - var toggleComments = function (fileContents) { - var lines = fileContents.split(/\r\n|\r|\n/); - var mode = 0; - for (var i = 0; i < lines.length; i++) { - var line = lines[i]; - if (mode === 0) { - if (/\/\/ ESM-comment-begin/.test(line)) { - mode = 1; - continue; + if (/\.ts$/.test(file)) { + // Transform the .ts file + var fileContents = fs.readFileSync(path.join(SRC_FOLDER, file)).toString(); + var info = ts.preProcessFile(fileContents); + for (var i_1 = info.importedFiles.length - 1; i_1 >= 0; i_1--) { + var importedFilename = info.importedFiles[i_1].fileName; + var pos = info.importedFiles[i_1].pos; + var end = info.importedFiles[i_1].end; + var importedFilepath = void 0; + if (/^vs\/css!/.test(importedFilename)) { + importedFilepath = importedFilename.substr('vs/css!'.length) + '.css'; } - if (/\/\/ ESM-uncomment-begin/.test(line)) { - mode = 2; - continue; + else { + importedFilepath = importedFilename; } - continue; + if (/(^\.\/)|(^\.\.\/)/.test(importedFilepath)) { + importedFilepath = path.join(path.dirname(file), importedFilepath); + } + var relativePath = void 0; + if (importedFilepath === path.dirname(file)) { + relativePath = '../' + path.basename(path.dirname(file)); + } + else if (importedFilepath === path.dirname(path.dirname(file))) { + relativePath = '../../' + path.basename(path.dirname(path.dirname(file))); + } + else { + relativePath = path.relative(path.dirname(file), importedFilepath); + } + if (!/(^\.\/)|(^\.\.\/)/.test(relativePath)) { + relativePath = './' + relativePath; + } + fileContents = (fileContents.substring(0, pos + 1) + + relativePath + + fileContents.substring(end + 1)); } - if (mode === 1) { - if (/\/\/ ESM-comment-end/.test(line)) { - mode = 0; - continue; - } - lines[i] = '// ' + line; - continue; + fileContents = fileContents.replace(/import ([a-zA-z0-9]+) = require\(('[^']+')\);/g, function (_, m1, m2) { + return "import * as " + m1 + " from " + m2 + ";"; + }); + write(getDestAbsoluteFilePath(file), fileContents); + continue; + } + console.log("UNKNOWN FILE: " + file); + } + function walkDirRecursive(dir) { + if (dir.charAt(dir.length - 1) !== '/' || dir.charAt(dir.length - 1) !== '\\') { + dir += '/'; + } + var result = []; + _walkDirRecursive(dir, result, dir.length); + return result; + } + function _walkDirRecursive(dir, result, trimPos) { + var files = fs.readdirSync(dir); + for (var i = 0; i < files.length; i++) { + var file = path.join(dir, files[i]); + if (fs.statSync(file).isDirectory()) { + _walkDirRecursive(file, result, trimPos); } - if (mode === 2) { - if (/\/\/ ESM-uncomment-end/.test(line)) { - mode = 0; - continue; - } - lines[i] = line.replace(/^(\s*)\/\/ ?/, function (_, indent) { - return indent; - }); + else { + result.push(file.substr(trimPos)); } } - return lines.join('\n'); - }; - var write = function (filePath, contents) { - var absoluteFilePath; - if (/\.ts$/.test(filePath)) { - absoluteFilePath = path.join(OUT_FOLDER, filePath); - } - else { - absoluteFilePath = path.join(OUT_RESOURCES_FOLDER, filePath); - } - createDirectoryRecursive(path.dirname(absoluteFilePath)); - if (/(\.ts$)|(\.js$)/.test(filePath)) { + } + function write(absoluteFilePath, contents) { + if (/(\.ts$)|(\.js$)/.test(absoluteFilePath)) { contents = toggleComments(contents.toString()); } - fs.writeFileSync(absoluteFilePath, contents); - }; - options.entryPoints.forEach(function (entryPoint) { return enqueue(entryPoint); }); - while (queue.length > 0) { - var module_1 = queue.shift(); - if (transportCSS(module_1, enqueue, write)) { - continue; + writeFile(absoluteFilePath, contents); + function toggleComments(fileContents) { + var lines = fileContents.split(/\r\n|\r|\n/); + var mode = 0; + for (var i = 0; i < lines.length; i++) { + var line = lines[i]; + if (mode === 0) { + if (/\/\/ ESM-comment-begin/.test(line)) { + mode = 1; + continue; + } + if (/\/\/ ESM-uncomment-begin/.test(line)) { + mode = 2; + continue; + } + continue; + } + if (mode === 1) { + if (/\/\/ ESM-comment-end/.test(line)) { + mode = 0; + continue; + } + lines[i] = '// ' + line; + continue; + } + if (mode === 2) { + if (/\/\/ ESM-uncomment-end/.test(line)) { + mode = 0; + continue; + } + lines[i] = line.replace(/^(\s*)\/\/ ?/, function (_, indent) { + return indent; + }); + } + } + return lines.join('\n'); } - if (transportResource(options, module_1, enqueue, write)) { - continue; - } - if (transportDTS(options, module_1, enqueue, write)) { - continue; - } - var filename = void 0; - if (options.redirects[module_1]) { - filename = path.join(SRC_DIR, options.redirects[module_1] + '.ts'); - } - else { - filename = path.join(SRC_DIR, module_1 + '.ts'); - } - var fileContents = fs.readFileSync(filename).toString(); - var info = ts.preProcessFile(fileContents); - for (var i = info.importedFiles.length - 1; i >= 0; i--) { - var importedFilename = info.importedFiles[i].fileName; - var pos = info.importedFiles[i].pos; - var end = info.importedFiles[i].end; - var importedFilepath = void 0; - if (/^vs\/css!/.test(importedFilename)) { - importedFilepath = importedFilename.substr('vs/css!'.length) + '.css'; - } - else { - importedFilepath = importedFilename; - } - if (/(^\.\/)|(^\.\.\/)/.test(importedFilepath)) { - importedFilepath = path.join(path.dirname(module_1), importedFilepath); - } - enqueue(importedFilepath); - var relativePath = void 0; - if (importedFilepath === path.dirname(module_1)) { - relativePath = '../' + path.basename(path.dirname(module_1)); - } - else if (importedFilepath === path.dirname(path.dirname(module_1))) { - relativePath = '../../' + path.basename(path.dirname(path.dirname(module_1))); - } - else { - relativePath = path.relative(path.dirname(module_1), importedFilepath); - } - if (!/(^\.\/)|(^\.\.\/)/.test(relativePath)) { - relativePath = './' + relativePath; - } - fileContents = (fileContents.substring(0, pos + 1) - + relativePath - + fileContents.substring(end + 1)); - } - fileContents = fileContents.replace(/import ([a-zA-z0-9]+) = require\(('[^']+')\);/g, function (_, m1, m2) { - return "import * as " + m1 + " from " + m2 + ";"; - }); - fileContents = fileContents.replace(/Thenable/g, 'PromiseLike'); - write(module_1 + '.ts', fileContents); } - var esm_opts = { - "compilerOptions": { - "outDir": path.relative(path.dirname(OUT_FOLDER), OUT_RESOURCES_FOLDER), - "rootDir": "src", - "module": "es6", - "target": "es5", - "experimentalDecorators": true, - "lib": [ - "dom", - "es5", - "es2015.collection", - "es2015.promise" - ], - "types": [] - } - }; - fs.writeFileSync(path.join(path.dirname(OUT_FOLDER), 'tsconfig.json'), JSON.stringify(esm_opts, null, '\t')); - var monacodts = fs.readFileSync(path.join(SRC_DIR, 'vs/monaco.d.ts')).toString(); - fs.writeFileSync(path.join(OUT_FOLDER, 'vs/monaco.d.ts'), monacodts); } -exports.createESMSourcesAndResources = createESMSourcesAndResources; +exports.createESMSourcesAndResources2 = createESMSourcesAndResources2; function transportCSS(module, enqueue, write) { if (!/\.css/.test(module)) { return false; @@ -323,27 +305,3 @@ function transportCSS(module, enqueue, write) { return haystack.length >= needle.length && haystack.substr(0, needle.length) === needle; } } -function transportResource(options, module, enqueue, write) { - if (!/\.svg/.test(module)) { - return false; - } - write(module, fs.readFileSync(path.join(SRC_DIR, module))); - return true; -} -function transportDTS(options, module, enqueue, write) { - if (options.redirects[module] && fs.existsSync(path.join(SRC_DIR, options.redirects[module] + '.ts'))) { - return false; - } - if (!fs.existsSync(path.join(SRC_DIR, module + '.d.ts'))) { - return false; - } - write(module + '.d.ts', fs.readFileSync(path.join(SRC_DIR, module + '.d.ts'))); - var filename; - if (options.redirects[module]) { - write(module + '.js', fs.readFileSync(path.join(SRC_DIR, options.redirects[module] + '.js'))); - } - else { - write(module + '.js', fs.readFileSync(path.join(SRC_DIR, module + '.js'))); - } - return true; -} diff --git a/build/lib/standalone.ts b/build/lib/standalone.ts index 7931737fadb..621b4aea6d4 100644 --- a/build/lib/standalone.ts +++ b/build/lib/standalone.ts @@ -10,7 +10,6 @@ import * as tss from './treeshaking'; const REPO_ROOT = path.join(__dirname, '../../'); const SRC_DIR = path.join(REPO_ROOT, 'src'); -const OUT_EDITOR = path.join(REPO_ROOT, 'out-editor'); let dirCache: { [dir: string]: boolean; } = {}; @@ -38,7 +37,7 @@ export function extractEditor(options: tss.ITreeShakingOptions & { destRoot: str writeFile(path.join(options.destRoot, fileName), result[fileName]); } } - let copied: { [fileName:string]: boolean; } = {}; + let copied: { [fileName: string]: boolean; } = {}; const copyFile = (fileName: string) => { if (copied[fileName]) { return; @@ -82,6 +81,8 @@ 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')); [ @@ -101,191 +102,174 @@ export function extractEditor(options: tss.ITreeShakingOptions & { destRoot: str ].forEach(copyFile); } -export interface IOptions { - entryPoints: string[]; +export interface IOptions2 { + srcFolder: string; outFolder: string; outResourcesFolder: string; - redirects: { [module: string]: string; }; + ignores: string[]; + renames: { [filename: string]: string; }; } -export function createESMSourcesAndResources(options: IOptions): void { +export function createESMSourcesAndResources2(options: IOptions2): void { + const SRC_FOLDER = path.join(REPO_ROOT, options.srcFolder); const OUT_FOLDER = path.join(REPO_ROOT, options.outFolder); const OUT_RESOURCES_FOLDER = path.join(REPO_ROOT, options.outResourcesFolder); - let in_queue: { [module: string]: boolean; } = Object.create(null); - let queue: string[] = []; - - const enqueue = (module: string) => { - if (in_queue[module]) { - return; + const getDestAbsoluteFilePath = (file: string): string => { + let dest = options.renames[file.replace(/\\/g, '/')] || file; + if (dest === 'tsconfig.json') { + return path.join(OUT_FOLDER, `../tsconfig.json`); } - in_queue[module] = true; - queue.push(module); + if (/\.ts$/.test(dest)) { + return path.join(OUT_FOLDER, dest); + } + return path.join(OUT_RESOURCES_FOLDER, dest); }; - const seenDir: { [key: string]: boolean; } = {}; - const createDirectoryRecursive = (dir: string) => { - if (seenDir[dir]) { - return; - } + const allFiles = walkDirRecursive(SRC_FOLDER); + for (let i = 0; i < allFiles.length; i++) { + const file = allFiles[i]; - let lastSlash = dir.lastIndexOf('/'); - if (lastSlash === -1) { - lastSlash = dir.lastIndexOf('\\'); - } - if (lastSlash !== -1) { - createDirectoryRecursive(dir.substring(0, lastSlash)); - } - seenDir[dir] = true; - try { fs.mkdirSync(dir); } catch (err) { } - }; - - seenDir[REPO_ROOT] = true; - - const toggleComments = (fileContents: string) => { - let lines = fileContents.split(/\r\n|\r|\n/); - let mode = 0; - for (let i = 0; i < lines.length; i++) { - const line = lines[i]; - - if (mode === 0) { - if (/\/\/ ESM-comment-begin/.test(line)) { - mode = 1; - continue; - } - if (/\/\/ ESM-uncomment-begin/.test(line)) { - mode = 2; - continue; - } - continue; - } - - if (mode === 1) { - if (/\/\/ ESM-comment-end/.test(line)) { - mode = 0; - continue; - } - lines[i] = '// ' + line; - continue; - } - - if (mode === 2) { - if (/\/\/ ESM-uncomment-end/.test(line)) { - mode = 0; - continue; - } - lines[i] = line.replace(/^(\s*)\/\/ ?/, function (_, indent) { - return indent; - }); - } - } - - return lines.join('\n'); - }; - - const write = (filePath: string, contents: string | Buffer) => { - let absoluteFilePath: string; - if (/\.ts$/.test(filePath)) { - absoluteFilePath = path.join(OUT_FOLDER, filePath); - } else { - absoluteFilePath = path.join(OUT_RESOURCES_FOLDER, filePath); - } - createDirectoryRecursive(path.dirname(absoluteFilePath)); - if (/(\.ts$)|(\.js$)/.test(filePath)) { - contents = toggleComments(contents.toString()); - } - fs.writeFileSync(absoluteFilePath, contents); - }; - - options.entryPoints.forEach((entryPoint) => enqueue(entryPoint)); - - while (queue.length > 0) { - const module = queue.shift(); - if (transportCSS(module, enqueue, write)) { - continue; - } - if (transportResource(options, module, enqueue, write)) { - continue; - } - if (transportDTS(options, module, enqueue, write)) { + if (options.ignores.indexOf(file.replace(/\\/g, '/')) >= 0) { continue; } - let filename: string; - if (options.redirects[module]) { - filename = path.join(SRC_DIR, options.redirects[module] + '.ts'); - } else { - filename = path.join(SRC_DIR, module + '.ts'); - } - let fileContents = fs.readFileSync(filename).toString(); - - const info = ts.preProcessFile(fileContents); - - for (let i = info.importedFiles.length - 1; i >= 0; i--) { - const importedFilename = info.importedFiles[i].fileName; - const pos = info.importedFiles[i].pos; - const end = info.importedFiles[i].end; - - let importedFilepath: string; - if (/^vs\/css!/.test(importedFilename)) { - importedFilepath = importedFilename.substr('vs/css!'.length) + '.css'; - } else { - importedFilepath = importedFilename; - } - if (/(^\.\/)|(^\.\.\/)/.test(importedFilepath)) { - importedFilepath = path.join(path.dirname(module), importedFilepath); - } - - enqueue(importedFilepath); - - let relativePath: string; - if (importedFilepath === path.dirname(module)) { - relativePath = '../' + path.basename(path.dirname(module)); - } else if (importedFilepath === path.dirname(path.dirname(module))) { - relativePath = '../../' + path.basename(path.dirname(path.dirname(module))); - } else { - relativePath = path.relative(path.dirname(module), importedFilepath); - } - if (!/(^\.\/)|(^\.\.\/)/.test(relativePath)) { - relativePath = './' + relativePath; - } - fileContents = ( - fileContents.substring(0, pos + 1) - + relativePath - + fileContents.substring(end + 1) - ); + 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); + write(getDestAbsoluteFilePath(file), JSON.stringify(tsConfig, null, '\t')); + continue; } - fileContents = fileContents.replace(/import ([a-zA-z0-9]+) = require\(('[^']+')\);/g, function (_, m1, m2) { - return `import * as ${m1} from ${m2};`; - }); - fileContents = fileContents.replace(/Thenable/g, 'PromiseLike'); + if (/\.d\.ts$/.test(file) || /\.css$/.test(file) || /\.js$/.test(file)) { + // Transport the files directly + write(getDestAbsoluteFilePath(file), fs.readFileSync(path.join(SRC_FOLDER, file))); + continue; + } - write(module + '.ts', fileContents); + if (/\.ts$/.test(file)) { + // Transform the .ts file + let fileContents = fs.readFileSync(path.join(SRC_FOLDER, file)).toString(); + + const info = ts.preProcessFile(fileContents); + + for (let i = info.importedFiles.length - 1; i >= 0; i--) { + const importedFilename = info.importedFiles[i].fileName; + const pos = info.importedFiles[i].pos; + const end = info.importedFiles[i].end; + + let importedFilepath: string; + if (/^vs\/css!/.test(importedFilename)) { + importedFilepath = importedFilename.substr('vs/css!'.length) + '.css'; + } else { + importedFilepath = importedFilename; + } + if (/(^\.\/)|(^\.\.\/)/.test(importedFilepath)) { + importedFilepath = path.join(path.dirname(file), importedFilepath); + } + + let relativePath: string; + if (importedFilepath === path.dirname(file)) { + relativePath = '../' + path.basename(path.dirname(file)); + } else if (importedFilepath === path.dirname(path.dirname(file))) { + relativePath = '../../' + path.basename(path.dirname(path.dirname(file))); + } else { + relativePath = path.relative(path.dirname(file), importedFilepath); + } + if (!/(^\.\/)|(^\.\.\/)/.test(relativePath)) { + relativePath = './' + relativePath; + } + fileContents = ( + fileContents.substring(0, pos + 1) + + relativePath + + fileContents.substring(end + 1) + ); + } + + fileContents = fileContents.replace(/import ([a-zA-z0-9]+) = require\(('[^']+')\);/g, function (_, m1, m2) { + return `import * as ${m1} from ${m2};`; + }); + + write(getDestAbsoluteFilePath(file), fileContents); + continue; + } + + console.log(`UNKNOWN FILE: ${file}`); } - const esm_opts = { - "compilerOptions": { - "outDir": path.relative(path.dirname(OUT_FOLDER), OUT_RESOURCES_FOLDER), - "rootDir": "src", - "module": "es6", - "target": "es5", - "experimentalDecorators": true, - "lib": [ - "dom", - "es5", - "es2015.collection", - "es2015.promise" - ], - "types": [ - ] + + function walkDirRecursive(dir: string): string[] { + if (dir.charAt(dir.length - 1) !== '/' || dir.charAt(dir.length - 1) !== '\\') { + dir += '/'; } - }; - fs.writeFileSync(path.join(path.dirname(OUT_FOLDER), 'tsconfig.json'), JSON.stringify(esm_opts, null, '\t')); + let result: string[] = []; + _walkDirRecursive(dir, result, dir.length); + return result; + } - const monacodts = fs.readFileSync(path.join(SRC_DIR, 'vs/monaco.d.ts')).toString(); - fs.writeFileSync(path.join(OUT_FOLDER, 'vs/monaco.d.ts'), monacodts); + function _walkDirRecursive(dir: string, result: string[], trimPos: number): void { + const files = fs.readdirSync(dir); + for (let i = 0; i < files.length; i++) { + const file = path.join(dir, files[i]); + if (fs.statSync(file).isDirectory()) { + _walkDirRecursive(file, result, trimPos); + } else { + result.push(file.substr(trimPos)); + } + } + } + function write(absoluteFilePath: string, contents: string | Buffer): void { + if (/(\.ts$)|(\.js$)/.test(absoluteFilePath)) { + contents = toggleComments(contents.toString()); + } + writeFile(absoluteFilePath, contents); + + function toggleComments(fileContents: string): string { + let lines = fileContents.split(/\r\n|\r|\n/); + let mode = 0; + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + + if (mode === 0) { + if (/\/\/ ESM-comment-begin/.test(line)) { + mode = 1; + continue; + } + if (/\/\/ ESM-uncomment-begin/.test(line)) { + mode = 2; + continue; + } + continue; + } + + if (mode === 1) { + if (/\/\/ ESM-comment-end/.test(line)) { + mode = 0; + continue; + } + lines[i] = '// ' + line; + continue; + } + + if (mode === 2) { + if (/\/\/ ESM-uncomment-end/.test(line)) { + mode = 0; + continue; + } + lines[i] = line.replace(/^(\s*)\/\/ ?/, function (_, indent) { + return indent; + }); + } + } + + return lines.join('\n'); + } + } } function transportCSS(module: string, enqueue: (module: string) => void, write: (path: string, contents: string | Buffer) => void): boolean { @@ -363,33 +347,3 @@ function transportCSS(module: string, enqueue: (module: string) => void, write: return haystack.length >= needle.length && haystack.substr(0, needle.length) === needle; } } - -function transportResource(options: IOptions, module: string, enqueue: (module: string) => void, write: (path: string, contents: string | Buffer) => void): boolean { - - if (!/\.svg/.test(module)) { - return false; - } - - write(module, fs.readFileSync(path.join(SRC_DIR, module))); - return true; -} - -function transportDTS(options: IOptions, module: string, enqueue: (module: string) => void, write: (path: string, contents: string | Buffer) => void): boolean { - - if (options.redirects[module] && fs.existsSync(path.join(SRC_DIR, options.redirects[module] + '.ts'))) { - return false; - } - - if (!fs.existsSync(path.join(SRC_DIR, module + '.d.ts'))) { - return false; - } - - write(module + '.d.ts', fs.readFileSync(path.join(SRC_DIR, module + '.d.ts'))); - let filename: string; - if (options.redirects[module]) { - write(module + '.js', fs.readFileSync(path.join(SRC_DIR, options.redirects[module] + '.js'))); - } else { - write(module + '.js', fs.readFileSync(path.join(SRC_DIR, module + '.js'))); - } - return true; -} diff --git a/build/monaco/monaco.d.ts.recipe b/build/monaco/monaco.d.ts.recipe index e39100bc3bc..bebfe723484 100644 --- a/build/monaco/monaco.d.ts.recipe +++ b/build/monaco/monaco.d.ts.recipe @@ -25,13 +25,6 @@ declare namespace monaco { dispose(): void; } - export enum Severity { - Ignore = 0, - Info = 1, - Warning = 2, - Error = 3, - } - export enum MarkerTag { Unnecessary = 1, } diff --git a/build/monaco/monaco.usage.recipe b/build/monaco/monaco.usage.recipe index 05377a19ba0..beaad500aad 100644 --- a/build/monaco/monaco.usage.recipe +++ b/build/monaco/monaco.usage.recipe @@ -71,7 +71,6 @@ import * as editorAPI from 'vs/editor/editor.api'; a = editorAPI.Range; a = editorAPI.Selection; a = editorAPI.SelectionDirection; - a = editorAPI.Severity; a = editorAPI.MarkerSeverity; a = editorAPI.MarkerTag; a = editorAPI.Promise; diff --git a/build/monaco/package.json b/build/monaco/package.json index 256ca1ff534..efd919085b2 100644 --- a/build/monaco/package.json +++ b/build/monaco/package.json @@ -1,7 +1,7 @@ { "name": "monaco-editor-core", "private": true, - "version": "0.12.0", + "version": "0.14.3", "description": "A browser based code editor", "author": "Microsoft Corporation", "license": "MIT", diff --git a/extensions/extension-editing/src/extensionLinter.ts b/extensions/extension-editing/src/extensionLinter.ts index cfcb7ca04d4..54af327ae07 100644 --- a/extensions/extension-editing/src/extensionLinter.ts +++ b/extensions/extension-editing/src/extensionLinter.ts @@ -249,7 +249,7 @@ export class ExtensionLinter { private readPackageJsonInfo(folder: Uri, tree: JsonNode) { const engine = tree && findNodeAtLocation(tree, ['engines', 'vscode']); const repo = tree && findNodeAtLocation(tree, ['repository', 'url']); - const uri = parseUri(repo.value); + const uri = repo && parseUri(repo.value); const info: PackageJsonInfo = { isExtension: !!(engine && engine.type === 'string'), hasHttpsRepository: !!(repo && repo.type === 'string' && repo.value && uri && uri.scheme.toLowerCase() === 'https') diff --git a/src/main.js b/src/main.js index ca00474ba1e..1c13edd6c05 100644 --- a/src/main.js +++ b/src/main.js @@ -7,9 +7,6 @@ const perf = require('./vs/base/common/performance'); perf.mark('main:started'); -// Perf measurements -global.perfStartTime = Date.now(); - Error.stackTraceLimit = 100; // increase number of stack frames (from 10, https://github.com/v8/v8/wiki/Stack-Trace-API) const fs = require('fs'); @@ -84,9 +81,8 @@ const app = require('electron').app; // TODO@Ben Electron 2.0.x: prevent localStorage migration from SQLite to LevelDB due to issues app.commandLine.appendSwitch('disable-mojo-local-storage'); -// TODO@Ben Electron 2.0.x: force srgb color profile (for https://github.com/Microsoft/vscode/issues/51791) -// This also seems to fix: https://github.com/Microsoft/vscode/issues/48043 -app.commandLine.appendSwitch('force-color-profile', 'srgb'); +// Force pre-Chrome-60 color profile handling (for https://github.com/Microsoft/vscode/issues/51791) +app.commandLine.appendSwitch('disable-features', 'ColorCorrectRendering'); const minimist = require('minimist'); const paths = require('./paths'); diff --git a/src/vs/base/browser/ui/menu/menu.css b/src/vs/base/browser/ui/menu/menu.css index 221640196a1..4f0c0152caa 100644 --- a/src/vs/base/browser/ui/menu/menu.css +++ b/src/vs/base/browser/ui/menu/menu.css @@ -40,7 +40,7 @@ flex: 1 1 auto; display: -ms-flexbox; display: flex; - height: 2.6em; + height: 2em; align-items: center; } @@ -50,7 +50,7 @@ text-decoration: none; padding: 0 1em; background: none; - font-size: inherit; + font-size: 12px; line-height: 1; } @@ -61,7 +61,7 @@ flex: 2 1 auto; padding: 0 1em; text-align: right; - font-size: inherit; + font-size: 12px; line-height: 1; } diff --git a/src/vs/base/common/marked/marked.js b/src/vs/base/common/marked/marked.js index 64cc685b4c2..92e7aaa8b53 100644 --- a/src/vs/base/common/marked/marked.js +++ b/src/vs/base/common/marked/marked.js @@ -1242,7 +1242,7 @@ Parser.prototype.tok = function() { return this.renderer.listitem(body); } case 'html': { - // TODO parse inline content if parameter markdown=1 + // TODO@matt parse inline content if parameter markdown=1 return this.renderer.html(this.token.text); } case 'paragraph': { diff --git a/src/vs/base/common/performance.js b/src/vs/base/common/performance.js index c89ace71f2c..5590211c6d5 100644 --- a/src/vs/base/common/performance.js +++ b/src/vs/base/common/performance.js @@ -76,17 +76,16 @@ define([], function () { function getDuration(from, to) { const entries = global._performanceEntries; - let name = from; - let startTime = 0; - for (let i = 0; i < entries.length; i += 5) { - if (entries[i + 1] === name) { - if (name === from) { - // found `from` (start of interval) - name = to; - startTime = entries[i + 2]; + let target = to; + let endTime = 0; + for (let i = entries.length - 1; i >= 0; i -= 5) { + if (entries[i - 3] === target) { + if (target === to) { + // found `to` (end of interval) + endTime = entries[i - 2]; + target = from; } else { - // from `to` (end of interval) - return entries[i + 2] - startTime; + return endTime - entries[i - 2]; } } } diff --git a/src/vs/base/common/resources.ts b/src/vs/base/common/resources.ts index 95d05f973df..a9a53243001 100644 --- a/src/vs/base/common/resources.ts +++ b/src/vs/base/common/resources.ts @@ -26,16 +26,23 @@ export function basenameOrAuthority(resource: URI): string { } export function isEqualOrParent(resource: URI, candidate: URI, ignoreCase?: boolean): boolean { - if (resource.scheme === candidate.scheme && resource.authority === candidate.authority) { + if (resource.scheme === candidate.scheme) { if (resource.scheme === Schemas.file) { return paths.isEqualOrParent(resource.fsPath, candidate.fsPath, ignoreCase); } + if (!isEqualAuthority(resource.authority, candidate.authority, ignoreCase)) { + return false; + } return paths.isEqualOrParent(resource.path, candidate.path, ignoreCase, '/'); } return false; } +function isEqualAuthority(a1: string, a2: string, ignoreCase?: boolean) { + return a1 === a2 || ignoreCase && a1 && a2 && equalsIgnoreCase(a1, a2); +} + export function isEqual(first: URI, second: URI, ignoreCase?: boolean): boolean { const identityEquals = (first === second); if (identityEquals) { diff --git a/src/vs/base/test/browser/ui/tree/treeModel.test.ts b/src/vs/base/test/browser/ui/tree/treeModel.test.ts index f348b38a9d9..71d44e275e2 100644 --- a/src/vs/base/test/browser/ui/tree/treeModel.test.ts +++ b/src/vs/base/test/browser/ui/tree/treeModel.test.ts @@ -259,45 +259,45 @@ suite('TreeModel2', function () { assert.deepEqual(list[2].depth, 1); }); - test('expand', function () { - const list = [] as ITreeNode[]; - const model = new TreeModel(toSpliceable(list)); + // test('expand', function () { + // const list = [] as ITreeNode[]; + // const model = new TreeModel(toSpliceable(list)); - model.splice([0], 0, Iterator.iterate([ - { - element: 0, collapsed: true, children: Iterator.iterate([ - { element: 10 }, - { element: 11 }, - { element: 12 }, - ]) - }, - { element: 1 }, - { element: 2 } - ])); + // model.splice([0], 0, Iterator.iterate([ + // { + // element: 0, collapsed: true, children: Iterator.iterate([ + // { element: 10 }, + // { element: 11 }, + // { element: 12 }, + // ]) + // }, + // { element: 1 }, + // { element: 2 } + // ])); - assert.deepEqual(list.length, 3); + // assert.deepEqual(list.length, 3); - model.setCollapsed([0], false); - assert.deepEqual(list.length, 6); - assert.deepEqual(list[0].element, 0); - assert.deepEqual(list[0].collapsed, false); - assert.deepEqual(list[0].depth, 1); - assert.deepEqual(list[1].element, 10); - assert.deepEqual(list[1].collapsed, false); - assert.deepEqual(list[1].depth, 2); - assert.deepEqual(list[2].element, 11); - assert.deepEqual(list[2].collapsed, false); - assert.deepEqual(list[2].depth, 2); - assert.deepEqual(list[3].element, 12); - assert.deepEqual(list[3].collapsed, false); - assert.deepEqual(list[3].depth, 2); - assert.deepEqual(list[4].element, 1); - assert.deepEqual(list[4].collapsed, false); - assert.deepEqual(list[4].depth, 1); - assert.deepEqual(list[5].element, 2); - assert.deepEqual(list[5].collapsed, false); - assert.deepEqual(list[5].depth, 1); - }); + // model.setCollapsed([0], false); + // assert.deepEqual(list.length, 6); + // assert.deepEqual(list[0].element, 0); + // assert.deepEqual(list[0].collapsed, false); + // assert.deepEqual(list[0].depth, 1); + // assert.deepEqual(list[1].element, 10); + // assert.deepEqual(list[1].collapsed, false); + // assert.deepEqual(list[1].depth, 2); + // assert.deepEqual(list[2].element, 11); + // assert.deepEqual(list[2].collapsed, false); + // assert.deepEqual(list[2].depth, 2); + // assert.deepEqual(list[3].element, 12); + // assert.deepEqual(list[3].collapsed, false); + // assert.deepEqual(list[3].depth, 2); + // assert.deepEqual(list[4].element, 1); + // assert.deepEqual(list[4].collapsed, false); + // assert.deepEqual(list[4].depth, 1); + // assert.deepEqual(list[5].element, 2); + // assert.deepEqual(list[5].collapsed, false); + // assert.deepEqual(list[5].depth, 1); + // }); test('collapse should recursively adjust visible count', function () { const list = [] as ITreeNode[]; diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 3bc811d9c7b..9f7403ac236 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -24,7 +24,7 @@ import { ICodeWindow, IWindowState, WindowMode } from 'vs/platform/windows/elect import { IWorkspaceIdentifier, IWorkspacesMainService } from 'vs/platform/workspaces/common/workspaces'; import { IBackupMainService } from 'vs/platform/backup/common/backup'; import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; -import { mark, exportEntries } from 'vs/base/common/performance'; +import * as perf from 'vs/base/common/performance'; import { resolveMarketplaceHeaders } from 'vs/platform/extensionManagement/node/extensionGalleryService'; export interface IWindowCreationOptions { @@ -547,7 +547,7 @@ export class CodeWindow implements ICodeWindow { } // Load URL - mark('main:loadWindow'); + perf.mark('main:loadWindow'); this._win.loadURL(this.getUrl(configuration)); // Make window visible if it did not open in N seconds because this indicates an error @@ -621,10 +621,8 @@ export class CodeWindow implements ICodeWindow { windowConfiguration.maximized = this._win.isMaximized(); windowConfiguration.frameless = this.hasHiddenTitleBarStyle() && !isMacintosh; - // Perf Counters - windowConfiguration.perfEntries = exportEntries(); - windowConfiguration.perfStartTime = (global).perfStartTime; - windowConfiguration.perfWindowLoadTime = Date.now(); + // Dump Perf Counters + windowConfiguration.perfEntries = perf.exportEntries(); // Config (combination of process.argv and window configuration) const environment = parseArgs(process.argv); diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index 714b67fa3aa..8ab17ce6977 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -439,7 +439,7 @@ export interface IEditor { /** * Gets the current model attached to this editor. */ - getModel(): IEditorModel; + getModel(): IEditorModel | null; /** * Sets the current model attached to this editor. @@ -449,7 +449,7 @@ export interface IEditor { * will not be destroyed. * It is safe to call setModel(null) to simply detach the current model from the editor. */ - setModel(model: IEditorModel): void; + setModel(model: IEditorModel | null): void; /** * Change the decorations. All decorations added through this changeAccessor diff --git a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts index 491f5a38134..4d4b03519d1 100644 --- a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts +++ b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts @@ -1100,7 +1100,7 @@ export class PieceTreeBase { let endColumn = endOffset - this._buffers[0].lineStarts[endIndex]; let endPos = { line: endIndex, column: endColumn }; let newPiece = new Piece( - 0, /** todo */ + 0, /** todo@peng */ start, endPos, this.getLineFeedCnt(0, start, endPos), diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index 0f643685413..6a4abcffa36 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -938,6 +938,9 @@ export interface Command { arguments?: any[]; } +/** + * @internal + */ export interface CommentInfo { owner: number; threads: CommentThread[]; @@ -945,6 +948,9 @@ export interface CommentInfo { reply?: Command; } +/** + * @internal + */ export enum CommentThreadCollapsibleState { /** * Determines an item is collapsed @@ -956,6 +962,9 @@ export enum CommentThreadCollapsibleState { Expanded = 1 } +/** + * @internal + */ export interface CommentThread { threadId: string; resource: string; @@ -965,11 +974,17 @@ export interface CommentThread { reply?: Command; } +/** + * @internal + */ export interface NewCommentAction { ranges: IRange[]; actions: Command[]; } +/** + * @internal + */ export interface Comment { readonly commentId: string; readonly body: IMarkdownString; @@ -978,6 +993,9 @@ export interface Comment { readonly command?: Command; } +/** + * @internal + */ export interface CommentThreadChangedEvent { readonly owner: number; /** @@ -996,7 +1014,9 @@ export interface CommentThreadChangedEvent { readonly changed: CommentThread[]; } - +/** + * @internal + */ export interface DocumentCommentProvider { provideDocumentComments(resource: URI, token: CancellationToken): Promise; createNewCommentThread(resource: URI, range: Range, text: string, token: CancellationToken): Promise; @@ -1004,7 +1024,9 @@ export interface DocumentCommentProvider { onDidChangeCommentThreads(): Event; } - +/** + * @internal + */ export interface WorkspaceCommentProvider { provideWorkspaceComments(token: CancellationToken): Promise; createNewCommentThread(resource: URI, range: Range, text: string, token: CancellationToken): Promise; diff --git a/src/vs/editor/common/services/editorSimpleWorker.ts b/src/vs/editor/common/services/editorSimpleWorker.ts index d478fef73c6..884fba7fa02 100644 --- a/src/vs/editor/common/services/editorSimpleWorker.ts +++ b/src/vs/editor/common/services/editorSimpleWorker.ts @@ -529,6 +529,7 @@ export abstract class BaseEditorSimpleWorker { } return TPromise.as(methods); } + // ESM-comment-begin return new TPromise((c, e) => { require([moduleId], (foreignModule: { create: IForeignModuleFactory }) => { this._foreignModule = foreignModule.create(ctx, createData); @@ -544,6 +545,11 @@ export abstract class BaseEditorSimpleWorker { }, e); }); + // ESM-comment-end + + // ESM-uncomment-begin + // return TPromise.wrapError(new Error(`Unexpected usage`)); + // ESM-uncomment-end } // foreign method request diff --git a/src/vs/editor/common/standalone/standaloneBase.ts b/src/vs/editor/common/standalone/standaloneBase.ts index c4683e6d6ed..6c44f5f1fa5 100644 --- a/src/vs/editor/common/standalone/standaloneBase.ts +++ b/src/vs/editor/common/standalone/standaloneBase.ts @@ -18,12 +18,6 @@ import URI from 'vs/base/common/uri'; // This is repeated here so it can be exported // because TS inlines const enums // -------------------------------------------- -export enum Severity { - Ignore = 0, - Info = 1, - Warning = 2, - Error = 3, -} export enum MarkerTag { Unnecessary = 1, @@ -248,7 +242,6 @@ export function createMonacoBaseAPI(): typeof monaco { Range: Range, Selection: Selection, SelectionDirection: SelectionDirection, - Severity: Severity, MarkerSeverity: MarkerSeverity, MarkerTag: MarkerTag, Promise: TPromise, diff --git a/src/vs/editor/contrib/codeAction/codeActionCommands.ts b/src/vs/editor/contrib/codeAction/codeActionCommands.ts index 1f229bfbfbc..5dd721207d4 100644 --- a/src/vs/editor/contrib/codeAction/codeActionCommands.ts +++ b/src/vs/editor/contrib/codeAction/codeActionCommands.ts @@ -27,6 +27,7 @@ import { CodeActionAutoApply, CodeActionFilter, CodeActionKind } from './codeAct import { CodeActionContextMenu } from './codeActionWidget'; import { LightBulbWidget } from './lightBulbWidget'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { onUnexpectedError } from 'vs/base/common/errors'; function contextKeyForSupportedActions(kind: CodeActionKind) { return ContextKeyExpr.regex( @@ -98,7 +99,7 @@ export class QuickFixController implements IEditorContribution { } else { this._codeActionContextMenu.show(e.actions, e.position); } - }); + }).catch(onUnexpectedError); return; } diff --git a/src/vs/editor/contrib/colorPicker/colorDetector.ts b/src/vs/editor/contrib/colorPicker/colorDetector.ts index b3836d6aa68..a676d0e8c36 100644 --- a/src/vs/editor/contrib/colorPicker/colorDetector.ts +++ b/src/vs/editor/contrib/colorPicker/colorDetector.ts @@ -17,6 +17,7 @@ import { getColors, IColorData } from 'vs/editor/contrib/colorPicker/color'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; import { TimeoutTimer, CancelablePromise, createCancelablePromise } from 'vs/base/common/async'; +import { onUnexpectedError } from 'vs/base/common/errors'; const MAX_DECORATORS = 500; @@ -28,7 +29,7 @@ export class ColorDetector implements IEditorContribution { private _globalToDispose: IDisposable[] = []; private _localToDispose: IDisposable[] = []; - private _computePromise: CancelablePromise; + private _computePromise: CancelablePromise; private _timeoutTimer: TimeoutTimer; private _decorationsIds: string[] = []; @@ -127,13 +128,12 @@ export class ColorDetector implements IEditorContribution { } private beginCompute(): void { - this._computePromise = createCancelablePromise(token => { - return getColors(this._editor.getModel(), token).then(colorInfos => { - this.updateDecorations(colorInfos); - this.updateColorDecorators(colorInfos); - this._computePromise = null; - }); - }); + this._computePromise = createCancelablePromise(token => getColors(this._editor.getModel(), token)); + this._computePromise.then((colorInfos) => { + this.updateDecorations(colorInfos); + this.updateColorDecorators(colorInfos); + this._computePromise = null; + }, onUnexpectedError); } private stop(): void { diff --git a/src/vs/editor/contrib/folding/folding.ts b/src/vs/editor/contrib/folding/folding.ts index c972f6885a2..520ad0ac57d 100644 --- a/src/vs/editor/contrib/folding/folding.ts +++ b/src/vs/editor/contrib/folding/folding.ts @@ -33,6 +33,7 @@ import { SyntaxRangeProvider, ID_SYNTAX_PROVIDER } from './syntaxRangeProvider'; import { CancellationToken } from 'vs/base/common/cancellation'; import { InitializingRangeProvider, ID_INIT_PROVIDER } from 'vs/editor/contrib/folding/intializingRangeProvider'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { onUnexpectedError } from 'vs/base/common/errors'; export const ID = 'editor.contrib.folding'; @@ -166,7 +167,7 @@ export class FoldingController implements IEditorContribution { if (foldingModel) { foldingModel.applyMemento(state.collapsedRegions); } - }); + }).done(undefined, onUnexpectedError); } } @@ -312,7 +313,7 @@ export class FoldingController implements IEditorContribution { } } } - }); + }).done(undefined, onUnexpectedError); } @@ -407,7 +408,7 @@ export class FoldingController implements IEditorContribution { } } } - }); + }).done(undefined, onUnexpectedError); } public reveal(position: IPosition): void { diff --git a/src/vs/editor/contrib/hover/hoverOperation.ts b/src/vs/editor/contrib/hover/hoverOperation.ts index 16699608cd6..2b55f24057d 100644 --- a/src/vs/editor/contrib/hover/hoverOperation.ts +++ b/src/vs/editor/contrib/hover/hoverOperation.ts @@ -57,7 +57,7 @@ export class HoverOperation { private _firstWaitScheduler: RunOnceScheduler; private _secondWaitScheduler: RunOnceScheduler; private _loadingMessageScheduler: RunOnceScheduler; - private _asyncComputationPromise: CancelablePromise; + private _asyncComputationPromise: CancelablePromise; private _asyncComputationPromiseDone: boolean; private _completeCallback: (r: Result) => void; @@ -103,12 +103,11 @@ export class HoverOperation { if (this._computer.computeAsync) { this._asyncComputationPromiseDone = false; - this._asyncComputationPromise = createCancelablePromise(token => { - return this._computer.computeAsync(token).then((asyncResult: Result) => { - this._asyncComputationPromiseDone = true; - this._withAsyncResult(asyncResult); - }, (e) => this._onError(e)); - }); + this._asyncComputationPromise = createCancelablePromise(token => this._computer.computeAsync(token)); + this._asyncComputationPromise.then((asyncResult: Result) => { + this._asyncComputationPromiseDone = true; + this._withAsyncResult(asyncResult); + }, (e) => this._onError(e)); } else { this._asyncComputationPromiseDone = true; diff --git a/src/vs/editor/contrib/links/links.ts b/src/vs/editor/contrib/links/links.ts index 87fe09b073e..91adad411bd 100644 --- a/src/vs/editor/contrib/links/links.ts +++ b/src/vs/editor/contrib/links/links.ts @@ -149,7 +149,7 @@ class LinkDetector implements editorCommon.IEditorContribution { private editor: ICodeEditor; private enabled: boolean; private listenersToRemove: IDisposable[]; - private timeoutPromise: async.CancelablePromise; + private timeout: async.TimeoutTimer; private computePromise: async.CancelablePromise; private activeLinkDecorationId: string; private openerService: IOpenerService; @@ -201,7 +201,7 @@ class LinkDetector implements editorCommon.IEditorContribution { this.listenersToRemove.push(editor.onDidChangeModelLanguage((e) => this.onModelModeChanged())); this.listenersToRemove.push(LinkProviderRegistry.onDidChange((e) => this.onModelModeChanged())); - this.timeoutPromise = null; + this.timeout = new async.TimeoutTimer(); this.computePromise = null; this.currentOccurrences = {}; this.activeLinkDecorationId = null; @@ -225,13 +225,7 @@ class LinkDetector implements editorCommon.IEditorContribution { } private onChange(): void { - if (!this.timeoutPromise) { - this.timeoutPromise = async.timeout(LinkDetector.RECOMPUTE_TIME); - this.timeoutPromise.then(() => { - this.timeoutPromise = null; - this.beginCompute(); - }); - } + this.timeout.setIfNotSet(() => this.beginCompute(), LinkDetector.RECOMPUTE_TIME); } private async beginCompute(): Promise { @@ -374,10 +368,7 @@ class LinkDetector implements editorCommon.IEditorContribution { } private stop(): void { - if (this.timeoutPromise) { - this.timeoutPromise.cancel(); - this.timeoutPromise = null; - } + this.timeout.cancel(); if (this.computePromise) { this.computePromise.cancel(); this.computePromise = null; @@ -387,6 +378,7 @@ class LinkDetector implements editorCommon.IEditorContribution { public dispose(): void { this.listenersToRemove = dispose(this.listenersToRemove); this.stop(); + this.timeout.dispose(); } } diff --git a/src/vs/editor/contrib/wordHighlighter/wordHighlighter.ts b/src/vs/editor/contrib/wordHighlighter/wordHighlighter.ts index 8c852574b12..684fc6757e2 100644 --- a/src/vs/editor/contrib/wordHighlighter/wordHighlighter.ts +++ b/src/vs/editor/contrib/wordHighlighter/wordHighlighter.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import { first2, createCancelablePromise, CancelablePromise } from 'vs/base/common/async'; -import { onUnexpectedExternalError } from 'vs/base/common/errors'; +import { onUnexpectedExternalError, onUnexpectedError } from 'vs/base/common/errors'; import { Range } from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { registerEditorContribution, EditorAction, IActionOptions, registerEditorAction, registerDefaultLanguageCommand } from 'vs/editor/browser/editorExtensions'; @@ -300,7 +300,7 @@ class WordHighlighter { this.workerRequestValue = data || []; this._beginRenderDecorations(); } - }); + }, onUnexpectedError); } this._lastWordRange = currentWordRange; diff --git a/src/vs/editor/editor.api.ts b/src/vs/editor/editor.api.ts index 5594a22627c..7bd274aab60 100644 --- a/src/vs/editor/editor.api.ts +++ b/src/vs/editor/editor.api.ts @@ -35,7 +35,6 @@ export const Position = api.Position; export const Range = api.Range; export const Selection = api.Selection; export const SelectionDirection = api.SelectionDirection; -export const Severity = api.Severity; export const MarkerSeverity = api.MarkerSeverity; export const MarkerTag = api.MarkerTag; export const Promise = api.Promise; diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index d20f7346b83..b3d9dbf7f14 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -45,6 +45,7 @@ import { WorkspaceEdit, isResourceTextEdit, TextEdit } from 'vs/editor/common/mo import { IModelService } from 'vs/editor/common/services/modelService'; import { EditOperation } from 'vs/editor/common/core/editOperation'; import { localize } from 'vs/nls'; +import { IUriDisplayService, UriDisplayRules } from 'vs/platform/uriDisplay/common/uriDisplay'; export class SimpleModel implements ITextEditorModel { @@ -590,3 +591,21 @@ export class SimpleBulkEditService implements IBulkEditService { }); } } + +export class SimpleUriDisplayService implements IUriDisplayService { + _serviceBrand: any; + + private readonly _onDidRegisterFormater: Emitter<{ scheme: string, formater: UriDisplayRules }> = new Emitter<{ scheme: string, formater: UriDisplayRules }>(); + public readonly onDidRegisterFormater: Event<{ scheme: string, formater: UriDisplayRules }> = this._onDidRegisterFormater.event; + + public getLabel(resource: URI, relative?: boolean): string { + if (resource.scheme === 'file') { + return resource.fsPath; + } + return resource.path; + } + + public registerFormater(schema: string, formater: UriDisplayRules): IDisposable { + throw new Error('Not implemented'); + } +} diff --git a/src/vs/editor/standalone/browser/standalone-tokens.css b/src/vs/editor/standalone/browser/standalone-tokens.css index c5860572a8e..1396ea01d0a 100644 --- a/src/vs/editor/standalone/browser/standalone-tokens.css +++ b/src/vs/editor/standalone/browser/standalone-tokens.css @@ -9,14 +9,14 @@ font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "HelveticaNeue-Light", "Ubuntu", "Droid Sans", sans-serif; } -.monaco-menu .monaco-action-bar.vertical .action-item .action-label:focus { +.monaco-menu .monaco-action-bar.vertical .action-item .action-menu-item:focus .action-label { color: #0059AC; stroke-width: 1.2px; text-shadow: 0px 0px 0.15px #0059AC; } -.monaco-editor.vs-dark .monaco-menu .monaco-action-bar.vertical .action-item .action-label:focus, -.monaco-editor.hc-black .monaco-menu .monaco-action-bar.vertical .action-item .action-label:focus { +.monaco-editor.vs-dark .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label, +.monaco-editor.hc-black .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label { color: #ACDDFF; stroke-width: 1.2px; text-shadow: 0px 0px 0.15px #ACDDFF; @@ -211,14 +211,14 @@ } /* contextmenu */ - .monaco-editor.vs .monaco-menu .monaco-action-bar.vertical .action-item .action-label:focus, - .monaco-editor.vs-dark .monaco-menu .monaco-action-bar.vertical .action-item .action-label:focus { + .monaco-editor.vs .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label, + .monaco-editor.vs-dark .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label { -ms-high-contrast-adjust: none; color: highlighttext !important; background-color: highlight !important; } - .monaco-editor.vs .monaco-menu .monaco-action-bar.vertical .action-item .action-label:hover, - .monaco-editor.vs-dark .monaco-menu .monaco-action-bar.vertical .action-item .action-label:hover { + .monaco-editor.vs .monaco-menu .monaco-action-bar.vertical .action-menu-item:hover .action-label, + .monaco-editor.vs-dark .monaco-menu .monaco-action-bar.vertical .action-menu-item:hover .action-label { -ms-high-contrast-adjust: none; background: transparent !important; border: 1px solid highlight; diff --git a/src/vs/editor/standalone/browser/standaloneCodeEditor.ts b/src/vs/editor/standalone/browser/standaloneCodeEditor.ts index 6018f9f47d5..890b51f49bd 100644 --- a/src/vs/editor/standalone/browser/standaloneCodeEditor.ts +++ b/src/vs/editor/standalone/browser/standaloneCodeEditor.ts @@ -84,7 +84,7 @@ export interface IEditorConstructionOptions extends IEditorOptions { /** * The initial model associated with this code editor. */ - model?: ITextModel; + model?: ITextModel | null; /** * The initial value of the auto created model in the editor. * To not create automatically a model, use `model: null`. diff --git a/src/vs/editor/standalone/browser/standaloneLanguages.ts b/src/vs/editor/standalone/browser/standaloneLanguages.ts index 592e1705796..b0287953b31 100644 --- a/src/vs/editor/standalone/browser/standaloneLanguages.ts +++ b/src/vs/editor/standalone/browser/standaloneLanguages.ts @@ -880,7 +880,6 @@ export function createMonacoLanguagesAPI(): typeof monaco.languages { SymbolKind: modes.SymbolKind, IndentAction: IndentAction, SuggestTriggerKind: modes.SuggestTriggerKind, - CommentThreadCollapsibleState: modes.CommentThreadCollapsibleState, FoldingRangeKind: modes.FoldingRangeKind }; } diff --git a/src/vs/editor/standalone/browser/standaloneServices.ts b/src/vs/editor/standalone/browser/standaloneServices.ts index d3275d83f30..49375edbcff 100644 --- a/src/vs/editor/standalone/browser/standaloneServices.ts +++ b/src/vs/editor/standalone/browser/standaloneServices.ts @@ -33,7 +33,7 @@ import { StandaloneCodeEditorServiceImpl } from 'vs/editor/standalone/browser/st import { SimpleConfigurationService, SimpleResourceConfigurationService, SimpleMenuService, SimpleProgressService, StandaloneCommandService, StandaloneKeybindingService, SimpleNotificationService, - StandaloneTelemetryService, SimpleWorkspaceContextService, SimpleDialogService, SimpleBulkEditService + StandaloneTelemetryService, SimpleWorkspaceContextService, SimpleDialogService, SimpleBulkEditService, SimpleUriDisplayService } from 'vs/editor/standalone/browser/simpleServices'; import { ContextKeyService } from 'vs/platform/contextkey/browser/contextKeyService'; import { IMenuService } from 'vs/platform/actions/common/actions'; @@ -44,6 +44,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IListService, ListService } from 'vs/platform/list/browser/listService'; import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService'; +import { IUriDisplayService } from 'vs/platform/uriDisplay/common/uriDisplay'; export interface IEditorOverrideServices { [index: string]: any; @@ -121,6 +122,8 @@ export module StaticServices { export const contextService = define(IWorkspaceContextService, () => new SimpleWorkspaceContextService()); + export const uriDisplayService = define(IUriDisplayService, () => new SimpleUriDisplayService()); + export const telemetryService = define(ITelemetryService, () => new StandaloneTelemetryService()); export const dialogService = define(IDialogService, () => new SimpleDialogService()); diff --git a/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts b/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts index 61e358dc4a0..f72758ff75e 100644 --- a/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts +++ b/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts @@ -100,7 +100,7 @@ class StandaloneTheme implements IStandaloneTheme { } public defines(colorId: ColorIdentifier): boolean { - return this.getColors().hasOwnProperty(colorId); + return Object.prototype.hasOwnProperty.call(this.getColors(), colorId); } public get type() { diff --git a/src/vs/editor/test/common/standalone/standaloneBase.test.ts b/src/vs/editor/test/common/standalone/standaloneBase.test.ts index 64849eb80cb..4cec807f3c1 100644 --- a/src/vs/editor/test/common/standalone/standaloneBase.test.ts +++ b/src/vs/editor/test/common/standalone/standaloneBase.test.ts @@ -5,18 +5,8 @@ 'use strict'; import * as assert from 'assert'; -import { KeyCode as StandaloneKeyCode, Severity as StandaloneSeverity } from 'vs/editor/common/standalone/standaloneBase'; +import { KeyCode as StandaloneKeyCode } from 'vs/editor/common/standalone/standaloneBase'; import { KeyCode as RuntimeKeyCode } from 'vs/base/common/keyCodes'; -import RuntimeSeverity from 'vs/base/common/severity'; - -suite('StandaloneBase', () => { - test('exports enums correctly', () => { - assert.equal(StandaloneSeverity.Ignore, RuntimeSeverity.Ignore); - assert.equal(StandaloneSeverity.Info, RuntimeSeverity.Info); - assert.equal(StandaloneSeverity.Warning, RuntimeSeverity.Warning); - assert.equal(StandaloneSeverity.Error, RuntimeSeverity.Error); - }); -}); suite('KeyCode', () => { test('is exported correctly in standalone editor', () => { diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index b8394da57dc..64d6a8bd52a 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -25,13 +25,6 @@ declare namespace monaco { dispose(): void; } - export enum Severity { - Ignore = 0, - Info = 1, - Warning = 2, - Error = 3, - } - export enum MarkerTag { Unnecessary = 1, } @@ -1058,7 +1051,7 @@ declare namespace monaco.editor { /** * The initial model associated with this code editor. */ - model?: ITextModel; + model?: ITextModel | null; /** * The initial value of the auto created model in the editor. * To not create automatically a model, use `model: null`. @@ -2197,7 +2190,7 @@ declare namespace monaco.editor { /** * Gets the current model attached to this editor. */ - getModel(): IEditorModel; + getModel(): IEditorModel | null; /** * Sets the current model attached to this editor. * If the previous model was created by the editor via the value key in the options @@ -2206,7 +2199,7 @@ declare namespace monaco.editor { * will not be destroyed. * It is safe to call setModel(null) to simply detach the current model from the editor. */ - setModel(model: IEditorModel): void; + setModel(model: IEditorModel | null): void; } /** @@ -5309,76 +5302,6 @@ declare namespace monaco.languages { arguments?: any[]; } - export interface CommentInfo { - owner: number; - threads: CommentThread[]; - commentingRanges?: IRange[]; - reply?: Command; - } - - export enum CommentThreadCollapsibleState { - /** - * Determines an item is collapsed - */ - Collapsed = 0, - /** - * Determines an item is expanded - */ - Expanded = 1 - } - - export interface CommentThread { - threadId: string; - resource: string; - range: IRange; - comments: Comment[]; - collapsibleState?: CommentThreadCollapsibleState; - reply?: Command; - } - - export interface NewCommentAction { - ranges: IRange[]; - actions: Command[]; - } - - export interface Comment { - readonly commentId: string; - readonly body: IMarkdownString; - readonly userName: string; - readonly gravatar: string; - readonly command?: Command; - } - - export interface CommentThreadChangedEvent { - readonly owner: number; - /** - * Added comment threads. - */ - readonly added: CommentThread[]; - /** - * Removed comment threads. - */ - readonly removed: CommentThread[]; - /** - * Changed comment threads. - */ - readonly changed: CommentThread[]; - } - - export interface DocumentCommentProvider { - provideDocumentComments(resource: Uri, token: CancellationToken): Promise; - createNewCommentThread(resource: Uri, range: Range, text: string, token: CancellationToken): Promise; - replyToCommentThread(resource: Uri, range: Range, thread: CommentThread, text: string, token: CancellationToken): Promise; - onDidChangeCommentThreads(): IEvent; - } - - export interface WorkspaceCommentProvider { - provideWorkspaceComments(token: CancellationToken): Promise; - createNewCommentThread(resource: Uri, range: Range, text: string, token: CancellationToken): Promise; - replyToCommentThread(resource: Uri, range: Range, thread: CommentThread, text: string, token: CancellationToken): Promise; - onDidChangeCommentThreads(): IEvent; - } - export interface ICodeLensSymbol { range: IRange; id?: string; diff --git a/src/vs/platform/history/electron-main/historyMainService.ts b/src/vs/platform/history/electron-main/historyMainService.ts index 47f31f09499..0308dfe3063 100644 --- a/src/vs/platform/history/electron-main/historyMainService.ts +++ b/src/vs/platform/history/electron-main/historyMainService.ts @@ -271,7 +271,7 @@ export class HistoryMainService implements IHistoryMainService { } } } else if (Array.isArray(storedRecents.workspaces)) { - // TODO legacy support can be removed at some point (6 month?) + // TODO@martin legacy support can be removed at some point (6 month?) // format of 1.25 and before for (const workspace of storedRecents.workspaces) { if (typeof workspace === 'string') { diff --git a/src/vs/platform/windows/common/windows.ts b/src/vs/platform/windows/common/windows.ts index 8daee9d9578..4b199d0e3e9 100644 --- a/src/vs/platform/windows/common/windows.ts +++ b/src/vs/platform/windows/common/windows.ts @@ -14,7 +14,7 @@ import { ParsedArgs } from 'vs/platform/environment/common/environment'; import { IWorkspaceIdentifier, IWorkspaceFolderCreationData, ISingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { IRecentlyOpened } from 'vs/platform/history/common/history'; import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; -import { PerformanceEntry } from 'vs/base/common/performance'; +import { ExportData } from 'vs/base/common/performance'; import { LogLevel } from 'vs/platform/log/common/log'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import URI, { UriComponents } from 'vs/base/common/uri'; @@ -352,15 +352,13 @@ export interface IWindowConfiguration extends ParsedArgs { fullscreen?: boolean; maximized?: boolean; highContrast?: boolean; - baseTheme?: string; - backgroundColor?: string; frameless?: boolean; accessibilitySupport?: boolean; - perfEntries: PerformanceEntry[]; perfStartTime?: number; perfAppReady?: number; perfWindowLoadTime?: number; + perfEntries: ExportData; filesToOpen?: IPath[]; filesToCreate?: IPath[]; @@ -407,4 +405,4 @@ export class ActiveWindowManager implements IDisposable { dispose() { this.disposables = dispose(this.disposables); } -} \ No newline at end of file +} diff --git a/src/vs/workbench/api/electron-browser/mainThreadFileSystem.ts b/src/vs/workbench/api/electron-browser/mainThreadFileSystem.ts index 334c62d7251..691841b18de 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadFileSystem.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadFileSystem.ts @@ -11,6 +11,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { FileWriteOptions, FileSystemProviderCapabilities, IFileChange, IFileService, IFileSystemProvider, IStat, IWatchOptions, FileType, FileOverwriteOptions, FileDeleteOptions } from 'vs/platform/files/common/files'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; import { ExtHostContext, ExtHostFileSystemShape, IExtHostContext, IFileChangeDto, MainContext, MainThreadFileSystemShape } from '../node/extHost.protocol'; +import { UriDisplayRules, IUriDisplayService } from 'vs/platform/uriDisplay/common/uriDisplay'; @extHostNamedCustomer(MainContext.MainThreadFileSystem) export class MainThreadFileSystem implements MainThreadFileSystemShape { @@ -20,7 +21,8 @@ export class MainThreadFileSystem implements MainThreadFileSystemShape { constructor( extHostContext: IExtHostContext, - @IFileService private readonly _fileService: IFileService + @IFileService private readonly _fileService: IFileService, + @IUriDisplayService private readonly _uriDisplayService: IUriDisplayService ) { this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostFileSystem); } @@ -39,6 +41,10 @@ export class MainThreadFileSystem implements MainThreadFileSystemShape { this._fileProvider.delete(handle); } + $setUriFormatter(scheme: string, formatter: UriDisplayRules): void { + this._uriDisplayService.registerFormater(scheme, formatter); + } + $onFileSystemChange(handle: number, changes: IFileChangeDto[]): void { this._fileProvider.get(handle).$onFileSystemChange(changes); } diff --git a/src/vs/workbench/api/electron-browser/mainThreadTask.ts b/src/vs/workbench/api/electron-browser/mainThreadTask.ts index cafb5b305b2..a1b5243fa6c 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadTask.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadTask.ts @@ -504,7 +504,7 @@ export class MainThreadTask implements MainThreadTaskShape { this._taskService.registerTaskSystem(key, { platform: platform, uriProvider: (path: string): URI => { - return URI.parse(`${info.scheme}://${info.host}:${info.port}${path}`); + return URI.parse(`${info.scheme}://${info.authority}${path}`); }, context: this._extHostContext, resolveVariables: (workspaceFolder: IWorkspaceFolder, variables: Set): TPromise> => { diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 0afcb94f377..575bb71cb4b 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -40,6 +40,7 @@ import { IExtensionDescription } from 'vs/workbench/services/extensions/common/e import { createExtHostContextProxyIdentifier as createExtId, createMainContextProxyIdentifier as createMainId, IRPCProtocol, ProxyIdentifier } from 'vs/workbench/services/extensions/node/proxyIdentifier'; import { IProgressOptions, IProgressStep } from 'vs/workbench/services/progress/common/progress'; import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles'; +import { UriDisplayRules } from 'vs/platform/uriDisplay/common/uriDisplay'; import * as vscode from 'vscode'; export interface IEnvironment { @@ -482,6 +483,7 @@ export interface IFileChangeDto { export interface MainThreadFileSystemShape extends IDisposable { $registerFileSystemProvider(handle: number, scheme: string, capabilities: FileSystemProviderCapabilities): void; $unregisterProvider(handle: number): void; + $setUriFormatter(scheme: string, formatter: UriDisplayRules): void; $onFileSystemChange(handle: number, resource: IFileChangeDto[]): void; } diff --git a/src/vs/workbench/api/node/extHostFileSystem.ts b/src/vs/workbench/api/node/extHostFileSystem.ts index 4c29149c845..c39ffb2a3f9 100644 --- a/src/vs/workbench/api/node/extHostFileSystem.ts +++ b/src/vs/workbench/api/node/extHostFileSystem.ts @@ -15,6 +15,7 @@ import { values } from 'vs/base/common/map'; import { Range, FileChangeType } from 'vs/workbench/api/node/extHostTypes'; import { ExtHostLanguageFeatures } from 'vs/workbench/api/node/extHostLanguageFeatures'; import { Schemas } from 'vs/base/common/network'; +import { UriDisplayRules } from 'vs/platform/uriDisplay/common/uriDisplay'; class FsLinkProvider implements vscode.DocumentLinkProvider { @@ -141,6 +142,10 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape { }); } + setUriFormatter(scheme: string, formatter: UriDisplayRules): void { + this._proxy.$setUriFormatter(scheme, formatter); + } + private static _asIStat(stat: vscode.FileStat): files.IStat { const { type, ctime, mtime, size } = stat; return { type, ctime, mtime, size }; diff --git a/src/vs/workbench/api/shared/tasks.ts b/src/vs/workbench/api/shared/tasks.ts index ee98ba6cccd..c03895bfb41 100644 --- a/src/vs/workbench/api/shared/tasks.ts +++ b/src/vs/workbench/api/shared/tasks.ts @@ -107,7 +107,6 @@ export interface TaskFilterDTO { export interface TaskSystemInfoDTO { scheme: string; - host: string; - port: number; + authority: string; platform: string; } \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/views/viewsViewlet.ts b/src/vs/workbench/browser/parts/views/viewsViewlet.ts index 36268d9a636..7fbaeee1186 100644 --- a/src/vs/workbench/browser/parts/views/viewsViewlet.ts +++ b/src/vs/workbench/browser/parts/views/viewsViewlet.ts @@ -377,8 +377,9 @@ export abstract class ViewContainerViewlet extends PanelViewlet implements IView private computeInitialSizes(): { [id: string]: number } { let sizes = {}; if (this.dimension) { + const totalWeight = this.viewsModel.visibleViewDescriptors.reduce((totalWeight, { weight }) => totalWeight + (weight || 20), 0); for (const viewDescriptor of this.viewsModel.visibleViewDescriptors) { - sizes[viewDescriptor.id] = this.dimension.height * (viewDescriptor.weight || 20) / 100; + sizes[viewDescriptor.id] = this.dimension.height * (viewDescriptor.weight || 20) / totalWeight; } } return sizes; diff --git a/src/vs/workbench/common/contributions.ts b/src/vs/workbench/common/contributions.ts index 0b86ba6a484..beaec28f4c4 100644 --- a/src/vs/workbench/common/contributions.ts +++ b/src/vs/workbench/common/contributions.ts @@ -7,6 +7,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IInstantiationService, IConstructorSignature0 } from 'vs/platform/instantiation/common/instantiation'; import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; +import { mark } from 'vs/base/common/performance'; // --- Workbench Contribution Registry @@ -89,13 +90,16 @@ export class WorkbenchContributionsRegistry implements IWorkbenchContributionsRe } private doInstantiateByPhase(instantiationService: IInstantiationService, phase: LifecyclePhase): void { + mark(`LifecyclePhase/${LifecyclePhase[phase]}/createContrib:start`); const toBeInstantiated = this.toBeInstantiated.get(phase); if (toBeInstantiated) { while (toBeInstantiated.length > 0) { - instantiationService.createInstance(toBeInstantiated.shift()); + const ctor = toBeInstantiated.shift(); + instantiationService.createInstance(ctor); } } + mark(`LifecyclePhase/${LifecyclePhase[phase]}/createContrib:end`); } } -Registry.add(Extensions.Workbench, new WorkbenchContributionsRegistry()); \ No newline at end of file +Registry.add(Extensions.Workbench, new WorkbenchContributionsRegistry()); diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 8162f48a02e..0d5e2e30903 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -279,6 +279,11 @@ export interface IEditorInput extends IDisposable { */ getResource(): URI; + /** + * Unique type identifier for this inpput. + */ + getTypeId(): string; + /** * Returns the display name of this input. */ diff --git a/src/vs/workbench/electron-browser/actions.ts b/src/vs/workbench/electron-browser/actions.ts index 2f5b03fc666..91c474950c1 100644 --- a/src/vs/workbench/electron-browser/actions.ts +++ b/src/vs/workbench/electron-browser/actions.ts @@ -355,7 +355,7 @@ export class ShowStartupPerformance extends Action { (console).group('Raw Startup Timers (CSV)'); let value = `Name\tStart\n`; - let entries = getEntries('mark').slice(0).sort((a, b) => a.startTime - b.startTime); + let entries = getEntries('mark'); for (const entry of entries) { value += `${entry.name}\t${entry.startTime}\n`; } diff --git a/src/vs/workbench/electron-browser/bootstrap/index.js b/src/vs/workbench/electron-browser/bootstrap/index.js index 5d0965c6de9..b16c9e2e461 100644 --- a/src/vs/workbench/electron-browser/bootstrap/index.js +++ b/src/vs/workbench/electron-browser/bootstrap/index.js @@ -220,7 +220,6 @@ function main() { // Correctly inherit the parent's environment assign(process.env, configuration.userEnv); - perf.importEntries(configuration.perfEntries); showPartsSplash(configuration); @@ -306,14 +305,6 @@ function main() { }); } - // Perf Counters - window.MonacoEnvironment.timers = { - isInitialStartup: !!configuration.isInitialStartup, - hasAccessibilitySupport: !!configuration.accessibilitySupport, - start: configuration.perfStartTime, - windowLoad: configuration.perfWindowLoadTime - }; - perf.mark('willLoadWorkbenchMain'); require([ 'vs/workbench/workbench.main', diff --git a/src/vs/workbench/electron-browser/main.ts b/src/vs/workbench/electron-browser/main.ts index f2b0cf0d3a5..46037466246 100644 --- a/src/vs/workbench/electron-browser/main.ts +++ b/src/vs/workbench/electron-browser/main.ts @@ -24,8 +24,7 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle import { realpath } from 'vs/base/node/pfs'; import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; import * as gracefulFs from 'graceful-fs'; -import { IInitData } from 'vs/workbench/services/timer/common/timerService'; -import { TimerService } from 'vs/workbench/services/timer/node/timerService'; +import { TimerService } from 'vs/workbench/services/timer/electron-browser/timerService'; import { KeyboardMapperFactory } from 'vs/workbench/services/keybinding/electron-browser/keybindingService'; import { IWindowConfiguration, IWindowsService } from 'vs/platform/windows/common/windows'; import { WindowsChannelClient } from 'vs/platform/windows/common/windowsIpc'; @@ -57,6 +56,8 @@ export function startup(configuration: IWindowConfiguration): TPromise { revive(configuration); + perf.importEntries(configuration.perfEntries); + // Ensure others can listen to zoom level changes browser.setZoomFactor(webFrame.getZoomFactor()); @@ -104,7 +105,7 @@ function openWorkbench(configuration: IWindowConfiguration): TPromise { // Since the configuration service is one of the core services that is used in so many places, we initialize it // right before startup of the workbench shell to have its data ready for consumers return createAndInitializeWorkspaceService(configuration, environmentService).then(workspaceService => { - const timerService = new TimerService((window).MonacoEnvironment.timers as IInitData, workspaceService.getWorkbenchState() === WorkbenchState.EMPTY); + const timerService = new TimerService(configuration, workspaceService.getWorkbenchState() === WorkbenchState.EMPTY); const storageService = createStorageService(workspaceService, environmentService); return domContentLoaded().then(() => { diff --git a/src/vs/workbench/electron-browser/media/shell.css b/src/vs/workbench/electron-browser/media/shell.css index 7a2b1a8207e..05267d25b87 100644 --- a/src/vs/workbench/electron-browser/media/shell.css +++ b/src/vs/workbench/electron-browser/media/shell.css @@ -80,15 +80,18 @@ .monaco-shell .monaco-menu .monaco-action-bar.vertical .action-label:not(.separator), .monaco-shell .monaco-menu .monaco-action-bar.vertical .keybinding { + font-size: inherit; padding: 0 1.5em; } .monaco-shell .monaco-menu .monaco-action-bar.vertical .action-label.separator { + font-size: inherit; padding: 0.2em 0 0 0; margin-bottom: 0.2em; } .monaco-shell .monaco-menu .monaco-action-bar.vertical .submenu-indicator { + font-size: inherit; padding: 0 1em; } diff --git a/src/vs/workbench/parts/comments/electron-browser/commentsEditorContribution.ts b/src/vs/workbench/parts/comments/electron-browser/commentsEditorContribution.ts index aa5e8402ac2..65590c32c85 100644 --- a/src/vs/workbench/parts/comments/electron-browser/commentsEditorContribution.ts +++ b/src/vs/workbench/parts/comments/electron-browser/commentsEditorContribution.ts @@ -326,7 +326,7 @@ export class ReviewController implements IEditorContribution { public onModelChanged(): void { this.localToDispose = dispose(this.localToDispose); if (this._newCommentWidget) { - // todo store view state. + // todo@peng store view state. this._newCommentWidget.dispose(); this._newCommentWidget = null; } diff --git a/src/vs/workbench/parts/debug/browser/loadedScriptsView.ts b/src/vs/workbench/parts/debug/browser/loadedScriptsView.ts index d5f424be629..10a11ba765b 100644 --- a/src/vs/workbench/parts/debug/browser/loadedScriptsView.ts +++ b/src/vs/workbench/parts/debug/browser/loadedScriptsView.ts @@ -364,13 +364,18 @@ export class LoadedScriptsView extends TreeViewsViewletPanel { clearTimeout(timeout); timeout = setTimeout(() => { - this.tree.refresh(root, true); + if (this.tree) { + this.tree.refresh(root, true); + } }, 300); })); this.disposables.push(this.debugService.onDidEndSession(session => { + clearTimeout(timeout); root.remove(session.getId()); - this.tree.refresh(root, false); + if (this.tree) { + this.tree.refresh(root, false); + } })); } diff --git a/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts index c8faf5c0e38..d34c404a4ca 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debug.contribution.ts @@ -205,7 +205,7 @@ configurationRegistry.registerConfiguration({ 'debug.internalConsoleOptions': INTERNAL_CONSOLE_OPTIONS_SCHEMA, 'debug.openDebug': { enum: ['neverOpen', 'openOnSessionStart', 'openOnFirstSessionStart', 'openOnDebugBreak'], - default: 'openOnFirstSessionStart', + default: 'openOnSessionStart', description: nls.localize('openDebug', "Controls when the debug view should open.") }, 'debug.enableAllHovers': { diff --git a/src/vs/workbench/parts/debug/node/terminals.ts b/src/vs/workbench/parts/debug/node/terminals.ts index 00ff6960cb4..221a8bd7bc2 100644 --- a/src/vs/workbench/parts/debug/node/terminals.ts +++ b/src/vs/workbench/parts/debug/node/terminals.ts @@ -312,7 +312,7 @@ export function prepareCommand(args: DebugProtocol.RunInTerminalRequestArguments // try to determine the shell type shell = shell.trim().toLowerCase(); - if (shell.indexOf('powershell') >= 0) { + if (shell.indexOf('powershell') >= 0 || shell.indexOf('pwsh') >= 0) { shellType = ShellType.powershell; } else if (shell.indexOf('cmd.exe') >= 0) { shellType = ShellType.cmd; diff --git a/src/vs/workbench/parts/feedback/electron-browser/media/feedback.css b/src/vs/workbench/parts/feedback/electron-browser/media/feedback.css index 3a390da8f70..3c69f00d995 100644 --- a/src/vs/workbench/parts/feedback/electron-browser/media/feedback.css +++ b/src/vs/workbench/parts/feedback/electron-browser/media/feedback.css @@ -48,7 +48,6 @@ padding-left: 3px; } -/* TODO @C5 review link color */ .monaco-shell .feedback-form .content .channels a { padding: 2px 0; } diff --git a/src/vs/workbench/parts/files/electron-browser/fileActions.ts b/src/vs/workbench/parts/files/electron-browser/fileActions.ts index ba7e84bb2f5..4fa6d796f55 100644 --- a/src/vs/workbench/parts/files/electron-browser/fileActions.ts +++ b/src/vs/workbench/parts/files/electron-browser/fileActions.ts @@ -1048,7 +1048,7 @@ export function incrementFileName(name: string, isFolder: boolean): string { } // 1.file.txt=>2.file.txt - let prefixFileRegex = RegExp('(\\d+)(' + separators + '.*)(\\..*)$'); + let prefixFileRegex = RegExp('^(\\d+)(' + separators + '.*)(\\..*)$'); if (!isFolder && name.match(prefixFileRegex)) { return name.replace(prefixFileRegex, (match, g1?, g2?, g3?) => { let number = parseInt(g1); @@ -1059,7 +1059,7 @@ export function incrementFileName(name: string, isFolder: boolean): string { } // 1.txt=>2.txt - let prefixFileNoNameRegex = RegExp('(\\d+)(\\..*)$'); + let prefixFileNoNameRegex = RegExp('^(\\d+)(\\..*)$'); if (!isFolder && name.match(prefixFileNoNameRegex)) { return name.replace(prefixFileNoNameRegex, (match, g1?, g2?) => { let number = parseInt(g1); diff --git a/src/vs/workbench/parts/files/electron-browser/fileCommands.ts b/src/vs/workbench/parts/files/electron-browser/fileCommands.ts index 5be4ed15f03..39bcd8cc6cf 100644 --- a/src/vs/workbench/parts/files/electron-browser/fileCommands.ts +++ b/src/vs/workbench/parts/files/electron-browser/fileCommands.ts @@ -79,7 +79,6 @@ export const ResourceSelectedForCompareContext = new RawContextKey('res export const REMOVE_ROOT_FOLDER_COMMAND_ID = 'removeRootFolder'; export const REMOVE_ROOT_FOLDER_LABEL = nls.localize('removeFolderFromWorkspace', "Remove Folder from Workspace"); -//TODO #54483 support string paths for backward compatibility. check with @bpasero and remove if not necessary export const openWindowCommand = (accessor: ServicesAccessor, paths: (string | URI)[], forceNewWindow: boolean) => { const windowService = accessor.get(IWindowService); windowService.openWindow(paths.map(p => typeof p === 'string' ? URI.file(p) : p), { forceNewWindow }); diff --git a/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts index af257952938..e0204febe1f 100644 --- a/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts @@ -502,7 +502,7 @@ export class FileController extends WorkbenchTreeController implements IDisposab sideBySide = tree.useAltAsMultipleSelectionModifier ? (event.ctrlKey || event.metaKey) : event.altKey; } - this.openEditor(stat, { preserveFocus, sideBySide, pinned: isDoubleClick }); + this.openEditor(stat, { preserveFocus, sideBySide, pinned: isDoubleClick || (event && event.middleButton) }); } } diff --git a/src/vs/workbench/parts/files/test/electron-browser/fileActions.test.ts b/src/vs/workbench/parts/files/test/electron-browser/fileActions.test.ts index 48bd1f7cc23..60120a22edd 100644 --- a/src/vs/workbench/parts/files/test/electron-browser/fileActions.test.ts +++ b/src/vs/workbench/parts/files/test/electron-browser/fileActions.test.ts @@ -106,12 +106,24 @@ suite('Files - Increment file name', () => { assert.strictEqual(result, '2.test.js'); }); + test('Increment file name with prefix version - check if starting from digit', function () { + const name = 'F1.test.js'; + const result = incrementFileName(name, false); + assert.strictEqual(result, 'F1.test.1.js'); + }); + test('Increment file name with just version in name', function () { const name = '1.js'; const result = incrementFileName(name, false); assert.strictEqual(result, '2.js'); }); + test('Increment file name with just version in name - check if starting from digit', function () { + const name = 'F1.js'; + const result = incrementFileName(name, false); + assert.strictEqual(result, 'F1.1.js'); + }); + test('Increment file name with just version in name, too big number', function () { const name = '9007199254740992.js'; const result = incrementFileName(name, false); diff --git a/src/vs/workbench/parts/performance/electron-browser/startupTimings.ts b/src/vs/workbench/parts/performance/electron-browser/startupTimings.ts index 047c038d75b..25ae117b18e 100644 --- a/src/vs/workbench/parts/performance/electron-browser/startupTimings.ts +++ b/src/vs/workbench/parts/performance/electron-browser/startupTimings.ts @@ -23,6 +23,55 @@ import { ILogService } from 'vs/platform/log/common/log'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IUpdateService } from 'vs/platform/update/common/update'; +/* __GDPR__FRAGMENT__ + "IStartupReflections" : { + "isLatestVersion": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, + "didUseCachedData": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, + "windowKind": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, + "windowCount": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, + "viewletId": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, + "panelId": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }, + "editorIds": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" } + } +*/ +interface IStartupReflections { + /** + * This is the latest (stable/insider) version. Iff not we should ignore this + * measurement. + */ + isLatestVersion: boolean; + + /** + * Whether we asked for and V8 accepted cached data. + */ + didUseCachedData: boolean; + + /** + * How/why the window was created. See https://github.com/Microsoft/vscode/blob/d1f57d871722f4d6ba63e4ef6f06287121ceb045/src/vs/platform/lifecycle/common/lifecycle.ts#L50 + */ + windowKind: number; + + /** + * The total number of windows that have been restored/created + */ + windowCount: number; + + /** + * The active viewlet id or `undedined` + */ + viewletId: string; + + /** + * The active panel id or `undefined` + */ + panelId: string; + + /** + * The editor input types or `[]` + */ + editorIds: string[]; +} + class StartupTimings implements IWorkbenchContribution { constructor( @@ -40,6 +89,7 @@ class StartupTimings implements IWorkbenchContribution { this._reportVariedStartupTimes().then(undefined, onUnexpectedError); this._reportStandardStartupTimes().then(undefined, onUnexpectedError); + this._reportStartupReflections().then(undefined, onUnexpectedError); } private async _reportVariedStartupTimes(): Promise { @@ -110,6 +160,48 @@ class StartupTimings implements IWorkbenchContribution { this._logService.info('standard startup', this._timerService.startupMetrics); } + private async _reportStartupReflections(): Promise { + await Promise.all([ + this._extensionService.whenInstalledExtensionsRegistered(), + this._lifecycleService.when(LifecyclePhase.Eventually) + ]); + + //todo@joh/ramya decide how to send this data, as single event merged with the timing or + // separate. + + /* __GDPR__ + "startupReflections" : { + "${include}": [ + "${IStartupReflections}" + ] + } + */ + this._telemetryService.publicLog('startupReflections', await this._createStartupReflections()); + } + + private async _createStartupReflections(): Promise { + + const isLatestVersion = Boolean(await this._updateService.isLatestVersion()); + const didUseCachedData = this._didUseCachedData(); + + const windowKind = this._lifecycleService.startupKind; + const windowCount = await this._windowsService.getWindowCount(); + + const viewletId = this._viewletService.getActiveViewlet() ? this._viewletService.getActiveViewlet().getId() : undefined; + const editorIds = this._editorService.visibleEditors.map(input => input.getTypeId()); + const panelId = this._panelService.getActivePanel() ? this._panelService.getActivePanel().getId() : undefined; + + return { + isLatestVersion, + didUseCachedData, + windowKind, + windowCount, + viewletId, + panelId, + editorIds + }; + } + private _didUseCachedData(): boolean { // We surely don't use cached data when we don't tell the loader to do so if (!Boolean((global).require.getConfig().nodeCachedDataDir)) { @@ -117,7 +209,7 @@ class StartupTimings implements IWorkbenchContribution { } // whenever cached data is produced or rejected a onNodeCachedData-callback is invoked. That callback // stores data in the `MonacoEnvironment.onNodeCachedData` global. See: - // https://github.com/Microsoft/vscode/blob/master/src/vs/workbench/electron-browser/bootstrap/index.js#L219 + // https://github.com/Microsoft/vscode/blob/efe424dfe76a492eab032343e2fa4cfe639939f0/src/vs/workbench/electron-browser/bootstrap/index.js#L299 if (!isFalsyOrEmpty(MonacoEnvironment.onNodeCachedData)) { return false; } diff --git a/src/vs/workbench/parts/preferences/browser/keybindingsEditor.ts b/src/vs/workbench/parts/preferences/browser/keybindingsEditor.ts index c071be384ec..0f25d0a34a6 100644 --- a/src/vs/workbench/parts/preferences/browser/keybindingsEditor.ts +++ b/src/vs/workbench/parts/preferences/browser/keybindingsEditor.ts @@ -439,7 +439,7 @@ export class KeybindingsEditor extends BaseEditor implements IKeybindingsEditor private getAriaLabel(keybindingsEntries: IKeybindingItemEntry[]): string { if (this.sortByPrecedence.checked) { - return localize('show sorted keybindings', "Showing {0} Keybindings in precendence order", keybindingsEntries.length); + return localize('show sorted keybindings', "Showing {0} Keybindings in precedence order", keybindingsEntries.length); } else { return localize('show keybindings', "Showing {0} Keybindings in alphabetical order", keybindingsEntries.length); } diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts index e72d4340789..e30e323957d 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts @@ -38,7 +38,14 @@ import { INotificationService, Severity } from 'vs/platform/notification/common/ import { getPathFromAmdModule } from 'vs/base/common/amd'; import { timeout } from 'vs/base/common/async'; -export class ExtensionHostProcessWorker { +export interface IExtensionHostStarter { + readonly onCrashed: Event<[number, string]>; + start(): TPromise; + getInspectPort(): number; + dispose(): void; +} + +export class ExtensionHostProcessWorker implements IExtensionHostStarter { private readonly _onCrashed: Emitter<[number, string]> = new Emitter<[number, string]>(); public readonly onCrashed: Event<[number, string]> = this._onCrashed.event; diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts index a46a116e22e..6e8576b4e4d 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts @@ -27,7 +27,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { ExtensionHostProcessWorker } from 'vs/workbench/services/extensions/electron-browser/extensionHost'; +import { ExtensionHostProcessWorker, IExtensionHostStarter } from 'vs/workbench/services/extensions/electron-browser/extensionHost'; import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc'; import { ExtHostCustomersRegistry } from 'vs/workbench/api/electron-browser/extHostCustomers'; import { IWindowService } from 'vs/platform/windows/common/windows'; @@ -119,14 +119,14 @@ export class ExtensionHostProcessManager extends Disposable { private readonly _extensionHostProcessFinishedActivateEvents: { [activationEvent: string]: boolean; }; private _extensionHostProcessRPCProtocol: RPCProtocol; private readonly _extensionHostProcessCustomers: IDisposable[]; - private readonly _extensionHostProcessWorker: ExtensionHostProcessWorker; + private readonly _extensionHostProcessWorker: IExtensionHostStarter; /** * winjs believes a proxy is a promise because it has a `then` method, so wrap the result in an object. */ private _extensionHostProcessProxy: TPromise<{ value: ExtHostExtensionServiceShape; }>; constructor( - extensionHostProcessWorker: ExtensionHostProcessWorker, + extensionHostProcessWorker: IExtensionHostStarter, initialActivationEvents: string[], @IInstantiationService private readonly _instantiationService: IInstantiationService, @IEnvironmentService private readonly _environmentService: IEnvironmentService, diff --git a/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts b/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts index c7e655da6e1..76cd245f08a 100644 --- a/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts +++ b/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts @@ -86,7 +86,6 @@ class ResourceModelCollection extends ReferenceCollection { if (!model) { - console.error(`Unable to open '${resource}' resource is not available.`); // TODO PII return TPromise.wrapError(new Error('resource is not available')); } diff --git a/src/vs/workbench/services/timer/common/timerService.ts b/src/vs/workbench/services/timer/common/timerService.ts index 84842c4eb00..8605a39e58f 100644 --- a/src/vs/workbench/services/timer/common/timerService.ts +++ b/src/vs/workbench/services/timer/common/timerService.ts @@ -55,21 +55,152 @@ export interface IMemoryInfo { } */ export interface IStartupMetrics { - version: number; + + /** + * The version of these metrics. + */ + version: 1; + + /** + * The time it took to create the workbench. + * + * * Happens in the main-process *and* the renderer-process + * * Measured with the *start* and `didStartWorkbench`-performance mark. The *start* is either the start of the + * main process or the start of the renderer. + * * This should be looked at carefully because times vary depending on + * * This being the first window, the only window, or a reloaded window + * * Cached data being present and used or not + * * The numbers and types of editors being restored + * * The numbers of windows being restored (when starting 'fresh') + * * The viewlet being restored (esp. when it's a contributed viewlet) + */ ellapsed: number; + + /** + * If this started the main process and renderer or just a renderer (new or reloaded). + */ + initialStartup: boolean; + + /** + * No folder, no file, no workspace has been opened + */ + emptyWorkbench: boolean; + timers: { + /** + * The time it took to receieve the [`ready`](https://electronjs.org/docs/api/app#event-ready)-event. Measured from the first line + * of JavaScript code till receiving that event. + * + * * Happens in the main-process + * * Measured with the `main:started` and `main:appReady` performance marks. + * * This can be compared between insider and stable builds. + * * This should be looked at per OS version and per electron version. + * * This is often affected by AV software (and can change with AV software updates outside of our release-cycle). + * * It is not our code running here and we can only observe what's happening. + */ ellapsedAppReady?: number; - ellapsedWindowLoad?: number; - ellapsedWindowLoadToRequire: number; - ellapsedExtensions: number; - ellapsedExtensionsReady: number; - ellapsedRequire: number; - ellapsedViewletRestore: number; - ellapsedEditorRestore: number; - ellapsedWorkbench: number; - ellapsedTimersToTimersComputed: number; + + /** + * The time it took to generate NLS data. + * + * * Happens in the main-process + * * Measured with the `nlsGeneration:start` and `nlsGeneration:end` performance marks. + * * This only happens when a non-english locale is being used. + * * It is our code running here and we should monitor this carefully for regressions. + */ ellapsedNlsGeneration: number; + + /** + * The time it took to tell electron to open/restore a renderer (browser window). + * + * * Happens in the main-process + * * Measured with the `main:appReady` and `main:loadWindow` performance marks. + * * This can be compared between insider and stable builds. + * * It is our code running here and we should monitor this carefully for regressions. + */ + ellapsedWindowLoad?: number; + + /** + * The time it took to create a new renderer (browser window) and to initialize that to the point + * of load the main-bundle (`workbench.main.js`). + * + * * Happens in the main-process *and* the renderer-process + * * Measured with the `main:loadWindow` and `willLoadWorkbenchMain` performance marks. + * * This can be compared between insider and stable builds. + * * It is mostly not our code running here and we can only observe what's happening. + * + */ + ellapsedWindowLoadToRequire: number; + + /** + * The time it took to load the main-bundle of the workbench, e.g `workbench.main.js`. + * + * * Happens in the renderer-process + * * Measured with the `willLoadWorkbenchMain` and `didLoadWorkbenchMain` performance marks. + * * This varies *a lot* when V8 cached data could be used or not + * * This should be looked at with and without V8 cached data usage and per electron/v8 version + * * This is affected by the size of our code bundle (which grows about 3-5% per release) + */ + ellapsedRequire: number; + + /** + * The time it took to read extensions' package.json-files *and* interpret them (invoking + * the contribution points). + * + * * Happens in the renderer-process + * * Measured with the `willLoadExtensions` and `didLoadExtensions` performance marks. + * * Reading of package.json-files is avoided by caching them all in a single file (after the read, + * until another extension is installed) + * * Happens in parallel to other things, depends on async timing + * + * todo@joh/ramya this measures an artifical dealy we have added, see https://github.com/Microsoft/vscode/blob/2f07ddae8bf56e969e3f4ba1447258ebc999672f/src/vs/workbench/services/extensions/electron-browser/extensionService.ts#L311-L326 + */ + ellapsedExtensions: number; + + // the time from start till `didLoadExtensions` + // remove? + ellapsedExtensionsReady: number; + + /** + * The time it took to restore the viewlet. + * + * * Happens in the renderer-process + * * Measured with the `willRestoreViewlet` and `didRestoreViewlet` performance marks. + * * This should be looked at per viewlet-type/id. + * * Happens in parallel to other things, depends on async timing + */ + ellapsedViewletRestore: number; + + /** + * The time it took to restore editors - that is text editor and complex editor likes the settings UI + * or webviews (markdown preview). + * + * * Happens in the renderer-process + * * Measured with the `willRestoreEditors` and `didRestoreEditors` performance marks. + * * This should be looked at per editor and per editor type. + * * Happens in parallel to other things, depends on async timing + * + * todo@joh/ramya We should probably measures each editor individually? + */ + ellapsedEditorRestore: number; + + /** + * The time it took to create the workbench. + * + * * Happens in the renderer-process + * * Measured with the `willStartWorkbench` and `didStartWorkbench` performance marks. + * + * todo@joh/ramya Not sure if this is useful because this includes too much + */ + ellapsedWorkbench: number; + + // the time it took to generate this object. + // remove? + ellapsedTimersToTimersComputed: number; }; + + hasAccessibilitySupport: boolean; + isVMLikelyhood: number; platform: string; release: string; arch: string; @@ -77,21 +208,10 @@ export interface IStartupMetrics { freemem: number; meminfo: IMemoryInfo; cpus: { count: number; speed: number; model: string; }; - initialStartup: boolean; - hasAccessibilitySupport: boolean; - isVMLikelyhood: number; - emptyWorkbench: boolean; loadavg: number[]; } -export interface IInitData { - start: number; - windowLoad: number; - isInitialStartup: boolean; - hasAccessibilitySupport: boolean; -} - -export interface ITimerService extends IInitData { +export interface ITimerService { _serviceBrand: any; readonly startupMetrics: IStartupMetrics; diff --git a/src/vs/workbench/services/timer/node/timerService.ts b/src/vs/workbench/services/timer/electron-browser/timerService.ts similarity index 60% rename from src/vs/workbench/services/timer/node/timerService.ts rename to src/vs/workbench/services/timer/electron-browser/timerService.ts index 1de3ba8f6cc..a1f75b791ce 100644 --- a/src/vs/workbench/services/timer/node/timerService.ts +++ b/src/vs/workbench/services/timer/electron-browser/timerService.ts @@ -4,29 +4,25 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import { ITimerService, IStartupMetrics, IInitData, IMemoryInfo } from 'vs/workbench/services/timer/common/timerService'; +import { ITimerService, IStartupMetrics, IMemoryInfo } from 'vs/workbench/services/timer/common/timerService'; import { virtualMachineHint } from 'vs/base/node/id'; import * as perf from 'vs/base/common/performance'; import * as os from 'os'; +import { getAccessibilitySupport } from 'vs/base/browser/browser'; +import { AccessibilitySupport } from 'vs/base/common/platform'; +import { IWindowConfiguration } from 'vs/platform/windows/common/windows'; export class TimerService implements ITimerService { public _serviceBrand: any; - public readonly start: number; - public readonly windowLoad: number; - - public readonly isInitialStartup: boolean; - public readonly hasAccessibilitySupport: boolean; - private _startupMetrics: IStartupMetrics; - constructor(initData: IInitData, private isEmptyWorkbench: boolean) { - this.start = initData.start; - this.windowLoad = initData.windowLoad; - - this.isInitialStartup = initData.isInitialStartup; - this.hasAccessibilitySupport = initData.hasAccessibilitySupport; + constructor( + private readonly _configuration: IWindowConfiguration, + private readonly _isEmptyWorkbench: boolean + ) { + // } get startupMetrics(): IStartupMetrics { @@ -38,8 +34,8 @@ export class TimerService implements ITimerService { public _computeStartupMetrics(): void { const now = Date.now(); - const initialStartup = !!this.isInitialStartup; - const start = initialStartup ? this.start : this.windowLoad; + const initialStartup = !!this._configuration.isInitialStartup; + const startMark = initialStartup ? 'main:started' : 'main:loadWindow'; let totalmem: number; let freemem: number; @@ -70,22 +66,21 @@ export class TimerService implements ITimerService { // ignore, be on the safe side with these hardware method calls } - let nlsStart = perf.getEntry('mark', 'nlsGeneration:start'); - let nlsEnd = perf.getEntry('mark', 'nlsGeneration:end'); - let nlsTime = nlsStart && nlsEnd ? nlsEnd.startTime - nlsStart.startTime : 0; this._startupMetrics = { version: 1, - ellapsed: perf.getEntry('mark', 'didStartWorkbench').startTime - start, + ellapsed: perf.getDuration(startMark, 'didStartWorkbench'), timers: { - ellapsedExtensions: perf.getDuration('willLoadExtensions', 'didLoadExtensions'), - ellapsedExtensionsReady: perf.getEntry('mark', 'didLoadExtensions').startTime - start, + ellapsedAppReady: initialStartup ? perf.getDuration('main:started', 'main:appReady') : undefined, + ellapsedNlsGeneration: perf.getDuration('nlsGeneration:start', 'nlsGeneration:end'), + ellapsedWindowLoad: initialStartup ? perf.getDuration('main:appReady', 'main:loadWindow') : undefined, + ellapsedWindowLoadToRequire: perf.getDuration('main:loadWindow', 'willLoadWorkbenchMain'), ellapsedRequire: perf.getDuration('willLoadWorkbenchMain', 'didLoadWorkbenchMain'), + ellapsedExtensions: perf.getDuration('willLoadExtensions', 'didLoadExtensions'), ellapsedEditorRestore: perf.getDuration('willRestoreEditors', 'didRestoreEditors'), ellapsedViewletRestore: perf.getDuration('willRestoreViewlet', 'didRestoreViewlet'), ellapsedWorkbench: perf.getDuration('willStartWorkbench', 'didStartWorkbench'), - ellapsedWindowLoadToRequire: perf.getEntry('mark', 'willLoadWorkbenchMain').startTime - this.windowLoad, + ellapsedExtensionsReady: perf.getDuration(startMark, 'didLoadExtensions'), ellapsedTimersToTimersComputed: Date.now() - now, - ellapsedNlsGeneration: nlsTime }, platform, release, @@ -97,13 +92,8 @@ export class TimerService implements ITimerService { loadavg, initialStartup, isVMLikelyhood, - hasAccessibilitySupport: !!this.hasAccessibilitySupport, - emptyWorkbench: this.isEmptyWorkbench + hasAccessibilitySupport: getAccessibilitySupport() === AccessibilitySupport.Enabled, + emptyWorkbench: this._isEmptyWorkbench }; - - if (initialStartup) { - this._startupMetrics.timers.ellapsedAppReady = perf.getDuration('main:started', 'main:appReady'); - this._startupMetrics.timers.ellapsedWindowLoad = this.windowLoad - perf.getEntry('mark', 'main:appReady').startTime; - } } }