mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 21:09:43 +00:00
Merge remote-tracking branch 'origin/master' into alex/tokenization
This commit is contained in:
commit
ebc43b3e8b
|
@ -40,7 +40,7 @@ const nodeModules = ['electron', 'original-fs']
|
|||
|
||||
const builtInExtensions = [
|
||||
{ name: 'ms-vscode.node-debug', version: '1.9.0' },
|
||||
{ name: 'ms-vscode.node-debug2', version: '1.9.0' }
|
||||
{ name: 'ms-vscode.node-debug2', version: '1.9.1' }
|
||||
];
|
||||
|
||||
const vscodeEntryPoints = _.flatten([
|
||||
|
@ -110,7 +110,7 @@ const config = {
|
|||
version: packageJson.electronVersion,
|
||||
productAppName: product.nameLong,
|
||||
companyName: 'Microsoft Corporation',
|
||||
copyright: 'Copyright (C) 2016 Microsoft. All rights reserved',
|
||||
copyright: 'Copyright (C) 2017 Microsoft. All rights reserved',
|
||||
darwinIcon: 'resources/darwin/code.icns',
|
||||
darwinBundleIdentifier: product.darwinBundleIdentifier,
|
||||
darwinApplicationCategoryType: 'public.app-category.developer-tools',
|
||||
|
|
|
@ -318,9 +318,6 @@
|
|||
{
|
||||
"include": "#preprocessor-rule-other-block"
|
||||
},
|
||||
{
|
||||
"include": "#sizeof"
|
||||
},
|
||||
{
|
||||
"include": "#access"
|
||||
},
|
||||
|
@ -458,7 +455,7 @@
|
|||
"line_continuation_character": {
|
||||
"patterns": [
|
||||
{
|
||||
"match": "(\\\\)\\s*\\n",
|
||||
"match": "(\\\\)\\n",
|
||||
"captures": {
|
||||
"1": {
|
||||
"name": "constant.character.escape.line-continuation.c"
|
||||
|
@ -891,6 +888,15 @@
|
|||
}
|
||||
},
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#access"
|
||||
},
|
||||
{
|
||||
"include": "#libc"
|
||||
},
|
||||
{
|
||||
"include": "#c_function_call"
|
||||
},
|
||||
{
|
||||
"include": "$self"
|
||||
}
|
||||
|
@ -976,5 +982,5 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
"version": "https://github.com/atom/language-c/commit/2a5fafe1d86f690b5ab2c877cea2fc6a598e001a"
|
||||
"version": "https://github.com/atom/language-c/commit/0d0f32388e73fc91a86f4c31ff59c36191869d63"
|
||||
}
|
|
@ -141,6 +141,16 @@
|
|||
"default": true,
|
||||
"description": "%html.suggest.html5.desc%"
|
||||
},
|
||||
"html.validate.scripts": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "%html.validate.scripts%"
|
||||
},
|
||||
"html.validate.styles": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "%html.validate.styles%"
|
||||
},
|
||||
"html.trace.server": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
|
|
|
@ -10,5 +10,7 @@
|
|||
"html.format.extraLiners.desc": "List of tags, comma separated, that should have an extra newline before them. 'null' defaults to \"head, body, /html\".",
|
||||
"html.suggest.angular1.desc": "Configures if the built-in HTML language support suggests Angular V1 tags and properties.",
|
||||
"html.suggest.ionic.desc": "Configures if the built-in HTML language support suggests Ionic tags, properties and values.",
|
||||
"html.suggest.html5.desc":"Configures if the built-in HTML language support suggests HTML5 tags, properties and values."
|
||||
"html.suggest.html5.desc":"Configures if the built-in HTML language support suggests HTML5 tags, properties and values.",
|
||||
"html.validate.scripts": "Configures if the built-in HTML language support validates embedded scripts.",
|
||||
"html.validate.styles": "Configures if the built-in HTML language support validates embedded styles."
|
||||
}
|
|
@ -6,9 +6,11 @@
|
|||
|
||||
import { createConnection, IConnection, TextDocuments, InitializeParams, InitializeResult, RequestType } from 'vscode-languageserver';
|
||||
import { DocumentContext } from 'vscode-html-languageservice';
|
||||
import { TextDocument, Diagnostic, DocumentLink, Range, TextEdit, SymbolInformation } from 'vscode-languageserver-types';
|
||||
import { TextDocument, Diagnostic, DocumentLink, Range, SymbolInformation } from 'vscode-languageserver-types';
|
||||
import { getLanguageModes, LanguageModes } from './modes/languageModes';
|
||||
|
||||
import { format } from './modes/formatting';
|
||||
|
||||
import * as url from 'url';
|
||||
import * as path from 'path';
|
||||
import uri from 'vscode-uri';
|
||||
|
@ -69,9 +71,18 @@ connection.onInitialize((params: InitializeParams): InitializeResult => {
|
|||
};
|
||||
});
|
||||
|
||||
let validation = {
|
||||
html: true,
|
||||
css: true,
|
||||
javascript: true
|
||||
};
|
||||
|
||||
// The settings have changed. Is send on server activation as well.
|
||||
connection.onDidChangeConfiguration((change) => {
|
||||
settings = change.settings;
|
||||
let validationSettings = settings && settings.html && settings.html.validate || {};
|
||||
validation.css = validationSettings.styles !== false;
|
||||
validation.javascript = validationSettings.scripts !== false;
|
||||
|
||||
languageModes.getAllModes().forEach(m => {
|
||||
if (m.configure) {
|
||||
|
@ -115,7 +126,7 @@ function triggerValidation(textDocument: TextDocument): void {
|
|||
function validateTextDocument(textDocument: TextDocument): void {
|
||||
let diagnostics: Diagnostic[] = [];
|
||||
languageModes.getAllModesInDocument(textDocument).forEach(mode => {
|
||||
if (mode.doValidation) {
|
||||
if (mode.doValidation && validation[mode.getId()]) {
|
||||
pushAll(diagnostics, mode.doValidation(textDocument));
|
||||
}
|
||||
});
|
||||
|
@ -201,18 +212,11 @@ connection.onSignatureHelp(signatureHelpParms => {
|
|||
|
||||
connection.onDocumentRangeFormatting(formatParams => {
|
||||
let document = documents.get(formatParams.textDocument.uri);
|
||||
let ranges = languageModes.getModesInRange(document, formatParams.range);
|
||||
let result: TextEdit[] = [];
|
||||
|
||||
let unformattedTags: string = settings && settings.html && settings.html.format && settings.html.format.unformatted || '';
|
||||
let enabledModes = { css: !unformattedTags.match(/\bstyle\b/), javascript: !unformattedTags.match(/\bscript\b/), html: true };
|
||||
ranges.forEach(r => {
|
||||
let mode = r.mode;
|
||||
if (mode && mode.format && enabledModes[mode.getId()] && !r.attributeValue) {
|
||||
let edits = mode.format(document, r, formatParams.options);
|
||||
pushAll(result, edits);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
let enabledModes = { css: !unformattedTags.match(/\bstyle\b/), javascript: !unformattedTags.match(/\bscript\b/) };
|
||||
|
||||
return format(languageModes, document, formatParams.range, formatParams.options, enabledModes);
|
||||
});
|
||||
|
||||
connection.onDocumentLinks(documentLinkParam => {
|
||||
|
|
55
extensions/html/server/src/modes/formatting.ts
Normal file
55
extensions/html/server/src/modes/formatting.ts
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { applyEdits } from '../utils/edits';
|
||||
import { TextDocument, Range, TextEdit, FormattingOptions } from 'vscode-languageserver-types';
|
||||
import { LanguageModes } from './languageModes';
|
||||
|
||||
export function format(languageModes: LanguageModes, document: TextDocument, formatRange: Range, formattingOptions: FormattingOptions, enabledModes: { [mode: string]: boolean }) {
|
||||
// run the html formatter on the full range and pass the result content to the embedded formatters.
|
||||
// from the final content create a single edit
|
||||
// advantages of this approach are
|
||||
// - correct indents in the html document
|
||||
// - correct initial indent for embedded formatters
|
||||
// - no worrying of overlapping edits
|
||||
|
||||
// perform a html format and apply changes to a new document
|
||||
let htmlMode = languageModes.getMode('html');
|
||||
let htmlEdits = htmlMode.format(document, formatRange, formattingOptions);
|
||||
let htmlFormattedContent = applyEdits(document, htmlEdits);
|
||||
let newDocument = TextDocument.create(document.uri + '.tmp', document.languageId, document.version, htmlFormattedContent);
|
||||
try {
|
||||
// run embedded formatters on html formatted content: - formatters see correct initial indent
|
||||
let afterFormatRangeLength = document.getText().length - document.offsetAt(formatRange.end); // length of unchanged content after replace range
|
||||
let newFormatRange = Range.create(formatRange.start, newDocument.positionAt(htmlFormattedContent.length - afterFormatRangeLength));
|
||||
let embeddedRanges = languageModes.getModesInRange(newDocument, newFormatRange);
|
||||
|
||||
let embeddedEdits: TextEdit[] = [];
|
||||
|
||||
for (let r of embeddedRanges) {
|
||||
let mode = r.mode;
|
||||
if (mode && mode.format && enabledModes[mode.getId()] && !r.attributeValue) {
|
||||
let edits = mode.format(newDocument, r, formattingOptions);
|
||||
for (let edit of edits) {
|
||||
embeddedEdits.push(edit);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (embeddedEdits.length === 0) {
|
||||
return htmlEdits;
|
||||
}
|
||||
|
||||
// apply all embedded format edits and create a single edit for all changes
|
||||
let resultContent = applyEdits(newDocument, embeddedEdits);
|
||||
let resultReplaceText = resultContent.substring(document.offsetAt(formatRange.start), resultContent.length - afterFormatRangeLength);
|
||||
|
||||
return [TextEdit.replace(formatRange, resultReplaceText)];
|
||||
} finally {
|
||||
languageModes.onDocumentRemoved(newDocument);
|
||||
}
|
||||
|
||||
}
|
|
@ -20,7 +20,7 @@ export function getHTMLMode(htmlLanguageService: HTMLLanguageService): LanguageM
|
|||
settings = options && options.html;
|
||||
},
|
||||
doComplete(document: TextDocument, position: Position) {
|
||||
let options = settings && settings.html && settings.html.suggest;
|
||||
let options = settings && settings.suggest;
|
||||
return htmlLanguageService.doComplete(document, position, htmlDocuments.get(document), options);
|
||||
},
|
||||
doHover(document: TextDocument, position: Position) {
|
||||
|
|
|
@ -8,6 +8,8 @@ import * as assert from 'assert';
|
|||
import { getLanguageModes } from '../modes/languageModes';
|
||||
import { TextDocument, Range, TextEdit, FormattingOptions } from 'vscode-languageserver-types';
|
||||
|
||||
import { format } from '../modes/formatting';
|
||||
|
||||
suite('HTML Embedded Formatting', () => {
|
||||
|
||||
function assertFormat(value: string, expected: string, options?: any): void {
|
||||
|
@ -31,15 +33,8 @@ suite('HTML Embedded Formatting', () => {
|
|||
let range = Range.create(document.positionAt(rangeStartOffset), document.positionAt(rangeEndOffset));
|
||||
let formatOptions = FormattingOptions.create(2, true);
|
||||
|
||||
let ranges = languageModes.getModesInRange(document, range);
|
||||
let result: TextEdit[] = [];
|
||||
ranges.forEach(r => {
|
||||
let mode = r.mode;
|
||||
if (mode && mode.format) {
|
||||
let edits = mode.format(document, r, formatOptions);
|
||||
pushAll(result, edits);
|
||||
}
|
||||
});
|
||||
let result = format(languageModes, document, range, formatOptions, { css: true, javascript: true });
|
||||
|
||||
let actual = applyEdits(document, result);
|
||||
assert.equal(actual, expected);
|
||||
}
|
||||
|
@ -52,38 +47,38 @@ suite('HTML Embedded Formatting', () => {
|
|||
|
||||
test('HTML & Scripts', function (): any {
|
||||
assertFormat('<html><head><script></script></head></html>', '<html>\n\n<head>\n <script></script>\n</head>\n\n</html>');
|
||||
assertFormat('<html><head><script>var x=1;</script></head></html>', '<html>\n\n<head>\n <script>var x = 1;</script>\n</head>\n\n</html>');
|
||||
assertFormat('<html><head><script>\nvar x=2;\n</script></head></html>', '<html>\n\n<head>\n <script>\n var x = 2;\n</script>\n</head>\n\n</html>');
|
||||
assertFormat('<html><head>\n <script>\nvar x=3;\n</script></head></html>', '<html>\n\n<head>\n <script>\n var x = 3;\n </script>\n</head>\n\n</html>');
|
||||
assertFormat('<html><head>\n <script>\nvar x=4;\nconsole.log("Hi");\n</script></head></html>', '<html>\n\n<head>\n <script>\n var x = 4;\n console.log("Hi");\n </script>\n</head>\n\n</html>');
|
||||
assertFormat('<html><head><script>var x=1;</script></head></html>', '<html>\n\n<head>\n <script>\n var x = 1;\n </script>\n</head>\n\n</html>');
|
||||
assertFormat('<html><head><script>\nvar x=2;\n</script></head></html>', '<html>\n\n<head>\n <script>\n var x = 2;\n\n </script>\n</head>\n\n</html>');
|
||||
assertFormat('<html><head>\n <script>\nvar x=3;\n</script></head></html>', '<html>\n\n<head>\n <script>\n var x = 3;\n\n </script>\n</head>\n\n</html>');
|
||||
assertFormat('<html><head>\n <script>\nvar x=4;\nconsole.log("Hi");\n</script></head></html>', '<html>\n\n<head>\n <script>\n var x = 4;\n console.log("Hi");\n\n </script>\n</head>\n\n</html>');
|
||||
|
||||
assertFormat('<html><head>\n |<script>\nvar x=5;\n</script>|</head></html>', '<html><head>\n <script>\n var x = 5;\n </script></head></html>');
|
||||
assertFormat('<html><head>\n |<script>\nvar x=5;\n</script>|</head></html>', '<html><head>\n <script>\n var x = 5;\n\n </script></head></html>');
|
||||
assertFormat('<html><head>\n <script>\n|var x=6;|\n</script></head></html>', '<html><head>\n <script>\n var x = 6;\n</script></head></html>');
|
||||
});
|
||||
|
||||
test('Script end tag', function (): any {
|
||||
assertFormat('<html>\n<head>\n <script>\nvar x = 0;\n</script></head></html>', '<html>\n\n<head>\n <script>\n var x = 0;\n </script>\n</head>\n\n</html>');
|
||||
assertFormat('<html>\n<head>\n <script>\nvar x = 0;\n</script></head></html>', '<html>\n\n<head>\n <script>\n var x = 0;\n\n </script>\n</head>\n\n</html>');
|
||||
});
|
||||
|
||||
test('HTML & Multiple Scripts', function (): any {
|
||||
assertFormat('<html><head>\n<script>\nif(x){\nbar(); }\n</script><script>\nfunction(x){}\n</script></head></html>', '<html>\n\n<head>\n <script>\n if (x) {\n bar();\n }\n</script>\n<script>\n function(x) { }\n</script>\n</head>\n\n</html>');
|
||||
assertFormat('<html><head>\n<script>\nif(x){\nbar(); }\n</script><script>\nfunction(x){}\n</script></head></html>', '<html>\n\n<head>\n <script>\n if (x) {\n bar();\n }\n\n </script>\n <script>\n function(x) { }\n\n </script>\n</head>\n\n</html>');
|
||||
});
|
||||
|
||||
test('HTML & Styles', function (): any {
|
||||
assertFormat('<html><head>\n<style>\n.foo{display:none;}\n</style></head></html>', '<html>\n\n<head>\n <style>\n.foo{display:none;}\n</style>\n</head>\n\n</html>');
|
||||
assertFormat('<html><head>\n<style>\n.foo{display:none;}\n</style></head></html>', '<html>\n\n<head>\n <style>\n .foo {\n display: none;\n }\n </style>\n</head>\n\n</html>');
|
||||
});
|
||||
|
||||
test('EndWithNewline', function (): any {
|
||||
let options = {
|
||||
html: {
|
||||
format: {
|
||||
endWithNewline : true
|
||||
endWithNewline: true
|
||||
}
|
||||
}
|
||||
};
|
||||
assertFormat('<html><body><p>Hello</p></body></html>', '<html>\n\n<body>\n <p>Hello</p>\n</body>\n\n</html>\n', options);
|
||||
assertFormat('<html>|<body><p>Hello</p></body>|</html>', '<html><body>\n <p>Hello</p>\n</body></html>', options);
|
||||
assertFormat('<html><head><script>\nvar x=1;\n</script></head></html>', '<html>\n\n<head>\n <script>\n var x = 1;\n</script>\n</head>\n\n</html>\n', options);
|
||||
assertFormat('<html><head><script>\nvar x=1;\n</script></head></html>', '<html>\n\n<head>\n <script>\n var x = 1;\n\n </script>\n</head>\n\n</html>\n', options);
|
||||
});
|
||||
|
||||
});
|
||||
|
|
34
extensions/html/server/src/utils/edits.ts
Normal file
34
extensions/html/server/src/utils/edits.ts
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { TextDocument, TextEdit, Position } from 'vscode-languageserver-types';
|
||||
|
||||
export function applyEdits(document: TextDocument, edits: TextEdit[]): string {
|
||||
let text = document.getText();
|
||||
let sortedEdits = edits.sort((a, b) => {
|
||||
let startDiff = comparePositions(a.range.start, b.range.start);
|
||||
if (startDiff === 0) {
|
||||
return comparePositions(a.range.end, b.range.end);
|
||||
}
|
||||
return startDiff;
|
||||
});
|
||||
let lastOffset = text.length;
|
||||
sortedEdits.forEach(e => {
|
||||
let startOffset = document.offsetAt(e.range.start);
|
||||
let endOffset = document.offsetAt(e.range.end);
|
||||
text = text.substring(0, startOffset) + e.newText + text.substring(endOffset, text.length);
|
||||
lastOffset = startOffset;
|
||||
});
|
||||
return text;
|
||||
}
|
||||
|
||||
function comparePositions(p1: Position, p2: Position) {
|
||||
let diff = p2.line - p1.line;
|
||||
if (diff === 0) {
|
||||
return p2.character - p1.character;
|
||||
}
|
||||
return diff;
|
||||
}
|
|
@ -67,7 +67,7 @@ export class PackageJSONContribution implements IJSONContribution {
|
|||
let name = keys[0];
|
||||
let insertText = new SnippetString().appendText(JSON.stringify(name));
|
||||
if (addValue) {
|
||||
insertText.appendText(': ').appendPlaceholder('*');
|
||||
insertText.appendText(': "').appendPlaceholder('').appendText('"');
|
||||
if (!isLast) {
|
||||
insertText.appendText(',');
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ export class PackageJSONContribution implements IJSONContribution {
|
|||
this.mostDependedOn.forEach((name) => {
|
||||
let insertText = new SnippetString().appendText(JSON.stringify(name));
|
||||
if (addValue) {
|
||||
insertText.appendText(': ').appendPlaceholder('*');
|
||||
insertText.appendText(': "').appendPlaceholder('').appendText('"');
|
||||
if (!isLast) {
|
||||
insertText.appendText(',');
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1584,8 +1584,19 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"c": "````application/json",
|
||||
"t": "text.html.markdown meta.paragraph.markdown",
|
||||
"c": "````",
|
||||
"t": "text.html.markdown markup.fenced_code.block.markdown punctuation.definition.markdown",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "application/json",
|
||||
"t": "text.html.markdown markup.fenced_code.block.markdown fenced_code.block.language",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
|
@ -1596,7 +1607,7 @@
|
|||
},
|
||||
{
|
||||
"c": " { value: [\"or with a mime type\"] }",
|
||||
"t": "text.html.markdown meta.paragraph.markdown",
|
||||
"t": "text.html.markdown markup.fenced_code.block.markdown",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
|
@ -1607,7 +1618,7 @@
|
|||
},
|
||||
{
|
||||
"c": "````",
|
||||
"t": "text.html.markdown meta.paragraph.markdown",
|
||||
"t": "text.html.markdown markup.fenced_code.block.markdown punctuation.definition.markdown",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
|
@ -1838,7 +1849,7 @@
|
|||
},
|
||||
{
|
||||
"c": "~~~",
|
||||
"t": "text.html.markdown meta.paragraph.markdown",
|
||||
"t": "text.html.markdown markup.fenced_code.block.markdown punctuation.definition.markdown",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
|
@ -1849,7 +1860,7 @@
|
|||
},
|
||||
{
|
||||
"c": "// Markdown extra adds un-indented code blocks too",
|
||||
"t": "text.html.markdown meta.paragraph.markdown",
|
||||
"t": "text.html.markdown markup.fenced_code.block.markdown",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
|
@ -1859,74 +1870,8 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"c": "if (this",
|
||||
"t": "text.html.markdown meta.paragraph.markdown",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "_",
|
||||
"t": "text.html.markdown meta.paragraph.markdown markup.italic.markdown punctuation.definition.italic.markdown",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "is",
|
||||
"t": "text.html.markdown meta.paragraph.markdown markup.italic.markdown",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "_",
|
||||
"t": "text.html.markdown meta.paragraph.markdown markup.italic.markdown punctuation.definition.italic.markdown",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "more_code == true ",
|
||||
"t": "text.html.markdown meta.paragraph.markdown",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "&&",
|
||||
"t": "text.html.markdown meta.paragraph.markdown meta.other.valid-ampersand.markdown",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " !indented) {",
|
||||
"t": "text.html.markdown meta.paragraph.markdown",
|
||||
"c": "if (this_is_more_code == true && !indented) {",
|
||||
"t": "text.html.markdown markup.fenced_code.block.markdown",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
|
@ -1937,7 +1882,7 @@
|
|||
},
|
||||
{
|
||||
"c": " // tild wrapped code blocks, also not indented",
|
||||
"t": "text.html.markdown meta.paragraph.markdown",
|
||||
"t": "text.html.markdown markup.fenced_code.block.markdown",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
|
@ -1948,7 +1893,7 @@
|
|||
},
|
||||
{
|
||||
"c": "}",
|
||||
"t": "text.html.markdown meta.paragraph.markdown",
|
||||
"t": "text.html.markdown markup.fenced_code.block.markdown",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
|
@ -1959,7 +1904,7 @@
|
|||
},
|
||||
{
|
||||
"c": "~~~",
|
||||
"t": "text.html.markdown meta.paragraph.markdown",
|
||||
"t": "text.html.markdown markup.fenced_code.block.markdown punctuation.definition.markdown",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
|
|
|
@ -220,7 +220,6 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP
|
|||
// Don't complete function calls inside of destructive assigments or imports
|
||||
return this.client.execute('quickinfo', args).then(infoResponse => {
|
||||
const info = infoResponse.body;
|
||||
console.log(info && info.kind);
|
||||
switch (info && info.kind) {
|
||||
case 'var':
|
||||
case 'let':
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "code-oss-dev",
|
||||
"version": "1.9.0",
|
||||
"electronVersion": "1.4.6",
|
||||
"distro": "2eecc8b68318fba1fc5b62930287914ac9225e8a",
|
||||
"distro": "ef07477c3bbf2aa2f274b13093cbe0d96fa59fdd",
|
||||
"author": {
|
||||
"name": "Microsoft Corporation"
|
||||
},
|
||||
|
@ -116,4 +116,4 @@
|
|||
"windows-mutex": "^0.2.0",
|
||||
"fsevents": "0.3.8"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@
|
|||
# Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
# If root, ensure that --user-data-dir is specified
|
||||
ARGS=$@
|
||||
if [ "$(id -u)" = "0" ]; then
|
||||
while test $# -gt 0
|
||||
do
|
||||
|
@ -34,5 +33,5 @@ fi
|
|||
|
||||
ELECTRON="$VSCODE_PATH/@@NAME@@"
|
||||
CLI="$VSCODE_PATH/resources/app/out/cli.js"
|
||||
ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" $ARGS
|
||||
ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" "$@"
|
||||
exit $?
|
||||
|
|
|
@ -692,7 +692,7 @@ export class Builder implements IDisposable {
|
|||
}
|
||||
};
|
||||
|
||||
return this.on(arg1, fn, listenerToUnbindContainer);
|
||||
return this.on(arg1, fn, listenerToUnbindContainer, useCapture);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -114,14 +114,14 @@ export interface IDomEvent {
|
|||
(element: EventHandler, type: string, useCapture?: boolean): _Event<any>;
|
||||
}
|
||||
|
||||
export const domEvent: IDomEvent = (element: EventHandler, type: string, useCapture?) => {
|
||||
export const domEvent: IDomEvent = (element: EventHandler, type: string, useCapture?: boolean) => {
|
||||
const fn = e => emitter.fire(e);
|
||||
const emitter = new Emitter<any>({
|
||||
onFirstListenerAdd: () => {
|
||||
element.addEventListener(type, fn);
|
||||
element.addEventListener(type, fn, useCapture);
|
||||
},
|
||||
onLastListenerRemove: () => {
|
||||
element.removeEventListener(type, fn);
|
||||
element.removeEventListener(type, fn, useCapture);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ function _renderHtml(content: IHTMLContentElement, options: RenderOptions = {}):
|
|||
|
||||
const renderer = new marked.Renderer();
|
||||
renderer.image = (href: string, title: string, text: string) => {
|
||||
let dimensions = [];
|
||||
let dimensions: string[] = [];
|
||||
if (href) {
|
||||
const splitted = href.split('|').map(s => s.trim());
|
||||
href = splitted[0];
|
||||
|
|
|
@ -7,7 +7,7 @@ import 'vs/css!./list';
|
|||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { range } from 'vs/base/common/arrays';
|
||||
import { IDelegate, IRenderer, IFocusChangeEvent, ISelectionChangeEvent } from './list';
|
||||
import { List } from './listWidget';
|
||||
import { List, IListOptions } from './listWidget';
|
||||
import { IPagedModel } from 'vs/base/common/paging';
|
||||
import Event, { mapEvent } from 'vs/base/common/event';
|
||||
|
||||
|
@ -67,10 +67,11 @@ export class PagedList<T> {
|
|||
constructor(
|
||||
container: HTMLElement,
|
||||
delegate: IDelegate<number>,
|
||||
renderers: IPagedRenderer<T, any>[]
|
||||
renderers: IPagedRenderer<T, any>[],
|
||||
options: IListOptions = {}
|
||||
) {
|
||||
const pagedRenderers = renderers.map(r => new PagedRenderer<T, ITemplateData<T>>(r, () => this.model));
|
||||
this.list = new List(container, delegate, pagedRenderers);
|
||||
this.list = new List(container, delegate, pagedRenderers, options);
|
||||
}
|
||||
|
||||
get onFocusChange(): Event<IFocusChangeEvent<T>> {
|
||||
|
|
|
@ -240,7 +240,7 @@ export class ListView<T> implements IDisposable {
|
|||
return DOM.addDisposableListener(domNode, type, handler, useCapture);
|
||||
}
|
||||
|
||||
private fireScopedEvent(handler: (event: any) => void, index) {
|
||||
private fireScopedEvent(handler: (event: any) => void, index: number) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ class Trait<T> implements IDisposable {
|
|||
splice(start: number, deleteCount: number, insertCount: number): void {
|
||||
const diff = insertCount - deleteCount;
|
||||
const end = start + deleteCount;
|
||||
const indexes = [];
|
||||
const indexes: number[] = [];
|
||||
|
||||
for (let index of indexes) {
|
||||
if (index >= start && index < end) {
|
||||
|
@ -110,13 +110,13 @@ class Trait<T> implements IDisposable {
|
|||
|
||||
class FocusTrait<T> extends Trait<T> {
|
||||
|
||||
constructor(private getElementId: (number) => string) {
|
||||
constructor(private getElementId: (number: number) => string) {
|
||||
super('focused');
|
||||
}
|
||||
|
||||
renderElement(element: T, index: number, container: HTMLElement): void {
|
||||
super.renderElement(element, index, container);
|
||||
container.setAttribute('role', 'option');
|
||||
container.setAttribute('role', 'treeitem');
|
||||
container.setAttribute('id', this.getElementId(index));
|
||||
}
|
||||
}
|
||||
|
@ -201,6 +201,7 @@ class Controller<T> implements IDisposable {
|
|||
}
|
||||
|
||||
export interface IListOptions extends IListViewOptions {
|
||||
ariaLabel?: string;
|
||||
}
|
||||
|
||||
const DefaultOptions: IListOptions = {};
|
||||
|
@ -245,13 +246,17 @@ export class List<T> implements IDisposable {
|
|||
});
|
||||
|
||||
this.view = new ListView(container, delegate, renderers, options);
|
||||
this.view.domNode.setAttribute('role', 'listbox');
|
||||
this.view.domNode.setAttribute('role', 'tree');
|
||||
this.view.domNode.tabIndex = 0;
|
||||
this.controller = new Controller(this, this.view);
|
||||
this.disposables = [this.focus, this.selection, this.view, this.controller];
|
||||
|
||||
this._onDOMFocus = domEvent(this.view.domNode, 'focus');
|
||||
this.onFocusChange(this._onFocusChange, this, this.disposables);
|
||||
|
||||
if (options.ariaLabel) {
|
||||
this.view.domNode.setAttribute('aria-label', options.ariaLabel);
|
||||
}
|
||||
}
|
||||
|
||||
splice(start: number, deleteCount: number, ...elements: T[]): void {
|
||||
|
@ -418,7 +423,16 @@ export class List<T> implements IDisposable {
|
|||
}
|
||||
|
||||
private _onFocusChange(): void {
|
||||
DOM.toggleClass(this.view.domNode, 'element-focused', this.focus.get().length > 0);
|
||||
const focus = this.focus.get();
|
||||
|
||||
if (focus.length > 0) {
|
||||
this.view.domNode.setAttribute('aria-activedescendant', this.getElementId(focus[0]));
|
||||
} else {
|
||||
this.view.domNode.removeAttribute('aria-activedescendant');
|
||||
}
|
||||
|
||||
this.view.domNode.setAttribute('role', 'tree');
|
||||
DOM.toggleClass(this.view.domNode, 'element-focused', focus.length > 0);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
|
|
|
@ -13,25 +13,12 @@ export function tail<T>(array: T[], n: number = 0): T {
|
|||
return array[array.length - (1 + n)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates the provided array and allows to remove
|
||||
* elements while iterating.
|
||||
*/
|
||||
export function forEach<T>(array: T[], callback: (element: T, remove: Function) => void): void {
|
||||
for (var i = 0, len = array.length; i < len; i++) {
|
||||
callback(array[i], function () {
|
||||
array.splice(i, 1);
|
||||
i--; len--;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function equals<T>(one: T[], other: T[], itemEquals: (a: T, b: T) => boolean = (a, b) => a === b): boolean {
|
||||
if (one.length !== other.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0, len = one.length; i < len; i++) {
|
||||
for (let i = 0, len = one.length; i < len; i++) {
|
||||
if (!itemEquals(one[i], other[i])) {
|
||||
return false;
|
||||
}
|
||||
|
@ -105,29 +92,6 @@ export function top<T>(array: T[], compare: (a: T, b: T) => number, n: number):
|
|||
return result;
|
||||
}
|
||||
|
||||
export function merge<T>(arrays: T[][], hashFn?: (element: T) => string): T[] {
|
||||
const result = new Array<T>();
|
||||
if (!hashFn) {
|
||||
for (let i = 0, len = arrays.length; i < len; i++) {
|
||||
result.push.apply(result, arrays[i]);
|
||||
}
|
||||
} else {
|
||||
const map: { [k: string]: boolean } = {};
|
||||
for (let i = 0; i < arrays.length; i++) {
|
||||
for (let j = 0; j < arrays[i].length; j++) {
|
||||
let element = arrays[i][j],
|
||||
hash = hashFn(element);
|
||||
|
||||
if (!map.hasOwnProperty(hash)) {
|
||||
map[hash] = true;
|
||||
result.push(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns a new array with all undefined or null values removed. The original array is not modified at all.
|
||||
*/
|
||||
|
@ -139,24 +103,6 @@ export function coalesce<T>(array: T[]): T[] {
|
|||
return array.filter(e => !!e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns true if the given item is contained in the array.
|
||||
*/
|
||||
export function contains<T>(array: T[], item: T): boolean {
|
||||
return array.indexOf(item) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Swaps the elements in the array for the provided positions.
|
||||
*/
|
||||
export function swap(array: any[], pos1: number, pos2: number): void {
|
||||
const element1 = array[pos1];
|
||||
const element2 = array[pos2];
|
||||
|
||||
array[pos1] = element2;
|
||||
array[pos2] = element1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the element in the array for the provided positions.
|
||||
*/
|
||||
|
@ -231,7 +177,7 @@ export function first<T>(array: T[], fn: (item: T) => boolean, notFoundValue: T
|
|||
export function commonPrefixLength<T>(one: T[], other: T[], equals: (a: T, b: T) => boolean = (a, b) => a === b): number {
|
||||
let result = 0;
|
||||
|
||||
for (var i = 0, len = Math.min(one.length, other.length); i < len && equals(one[i], other[i]); i++) {
|
||||
for (let i = 0, len = Math.min(one.length, other.length); i < len && equals(one[i], other[i]); i++) {
|
||||
result++;
|
||||
}
|
||||
|
||||
|
@ -283,4 +229,4 @@ export function insert<T>(array: T[], element: T): () => void {
|
|||
array.splice(index, 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,8 +71,8 @@ export interface ITask<T> {
|
|||
* The throttler implements this via the queue() method, by providing it a task
|
||||
* factory. Following the example:
|
||||
*
|
||||
* var throttler = new Throttler();
|
||||
* var letters = [];
|
||||
* const throttler = new Throttler();
|
||||
* const letters = [];
|
||||
*
|
||||
* function deliver() {
|
||||
* const lettersToDeliver = letters;
|
||||
|
@ -166,8 +166,8 @@ export class SimpleThrottler {
|
|||
* to be executed and the waiting period (delay) must be passed in as arguments. Following
|
||||
* the example:
|
||||
*
|
||||
* var delayer = new Delayer(WAITING_PERIOD);
|
||||
* var letters = [];
|
||||
* const delayer = new Delayer(WAITING_PERIOD);
|
||||
* const letters = [];
|
||||
*
|
||||
* function letterReceived(l) {
|
||||
* letters.push(l);
|
||||
|
@ -402,7 +402,7 @@ export function sequence<T>(promiseFactories: ITask<TPromise<T>>[]): TPromise<T[
|
|||
export function first<T>(promiseFactories: ITask<TPromise<T>>[], shouldStop: (t: T) => boolean = t => !!t): TPromise<T> {
|
||||
promiseFactories = [...promiseFactories.reverse()];
|
||||
|
||||
const loop = () => {
|
||||
const loop: () => TPromise<T> = () => {
|
||||
if (promiseFactories.length === 0) {
|
||||
return TPromise.as(null);
|
||||
}
|
||||
|
|
|
@ -65,12 +65,12 @@ function hsla2rgba(hsla: HSLA): RGBA {
|
|||
let s = Math.min(hsla.s, 1);
|
||||
let l = Math.min(hsla.l, 1);
|
||||
let a = hsla.a === void 0 ? hsla.a : 1;
|
||||
let r, g, b;
|
||||
let r: number, g: number, b: number;
|
||||
|
||||
if (s === 0) {
|
||||
r = g = b = l; // achromatic
|
||||
} else {
|
||||
let hue2rgb = function hue2rgb(p, q, t) {
|
||||
let hue2rgb = function hue2rgb(p: number, q: number, t: number) {
|
||||
if (t < 0) {
|
||||
t += 1;
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ export class Color {
|
|||
* Returns the number in the set [0, 1]. O => Darkest Black. 1 => Lightest white.
|
||||
*/
|
||||
public getLuminosity(): number {
|
||||
let luminosityFor = function (color): number {
|
||||
let luminosityFor = function (color: number): number {
|
||||
let c = color / 255;
|
||||
return (c <= 0.03928) ? c / 12.92 : Math.pow(((c + 0.055) / 1.055), 2.4);
|
||||
};
|
||||
|
|
|
@ -83,8 +83,8 @@ export function compareByPrefix(one: string, other: string, lookFor: string): nu
|
|||
}
|
||||
|
||||
export interface IScorableResourceAccessor<T> {
|
||||
getLabel(T): string;
|
||||
getResourcePath(T): string;
|
||||
getLabel(t: T): string;
|
||||
getResourcePath(t: T): string;
|
||||
}
|
||||
|
||||
export function compareByScore<T>(elementA: T, elementB: T, accessor: IScorableResourceAccessor<T>, lookFor: string, lookForNormalizedLower: string, scorerCache?: { [key: string]: number }): number {
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import nls = require('vs/nls');
|
||||
|
||||
export function since(date: Date): string {
|
||||
var seconds = (new Date().getTime() - date.getTime()) / 1000;
|
||||
if (seconds < 60) {
|
||||
return nls.localize('diff.seconds.verbose', "just now");
|
||||
}
|
||||
|
||||
var minutes = seconds / 60;
|
||||
if (minutes < 60) {
|
||||
return Math.floor(minutes) === 1 ? nls.localize('diff.minute.verbose', "1 minute ago") : nls.localize('diff.minutes.verbose', "{0} minutes ago", Math.floor(minutes));
|
||||
}
|
||||
|
||||
var hours = minutes / 60;
|
||||
if (hours < 24) {
|
||||
return Math.floor(hours) === 1 ? nls.localize('diff.hour.verbose', "1 hour ago") : nls.localize('diff.hours.verbose', "{0} hours ago", Math.floor(hours));
|
||||
}
|
||||
|
||||
var days = hours / 24;
|
||||
if (Math.floor(days) === 1) {
|
||||
return nls.localize('diff.days.yesterday', "yesterday");
|
||||
}
|
||||
|
||||
if (days > 6 && days < 8) {
|
||||
return nls.localize('diff.days.week', "a week ago");
|
||||
}
|
||||
|
||||
if (days > 30 && days < 40) {
|
||||
return nls.localize('diff.days.month', "a month ago");
|
||||
}
|
||||
|
||||
return nls.localize('diff.days.verbose', "{0} days ago", Math.floor(days));
|
||||
}
|
|
@ -23,7 +23,7 @@ export function memoize(target: any, key: string, descriptor: any) {
|
|||
|
||||
const memoizeKey = `$memoize$${key}`;
|
||||
|
||||
descriptor[fnKey] = function (...args) {
|
||||
descriptor[fnKey] = function (...args: any[]) {
|
||||
if (!this.hasOwnProperty(memoizeKey)) {
|
||||
Object.defineProperty(this, memoizeKey, {
|
||||
configurable: false,
|
||||
|
|
|
@ -19,7 +19,7 @@ globals.Monaco.Diagnostics = {};
|
|||
|
||||
var switches = globals.Monaco.Diagnostics;
|
||||
var map = {};
|
||||
var data = [];
|
||||
var data: any[] = [];
|
||||
|
||||
function fifo(array: any[], size: number) {
|
||||
while (array.length > size) {
|
||||
|
|
|
@ -148,8 +148,8 @@ export class LcsDiff2 {
|
|||
// Construct the changes
|
||||
let i = 0;
|
||||
let j = 0;
|
||||
let xChangeStart, yChangeStart;
|
||||
let changes = [];
|
||||
let xChangeStart: number, yChangeStart: number;
|
||||
let changes: DiffChange[] = [];
|
||||
while (i < xLength && j < yLength) {
|
||||
if (this.resultX[i] && this.resultY[j]) {
|
||||
// No change
|
||||
|
|
|
@ -218,7 +218,7 @@ export function once<T>(event: Event<T>): Event<T> {
|
|||
}
|
||||
|
||||
export function any<T>(...events: Event<T>[]): Event<T> {
|
||||
let listeners = [];
|
||||
let listeners: IDisposable[] = [];
|
||||
|
||||
const emitter = new Emitter<T>({
|
||||
onFirstListenerAdd() {
|
||||
|
@ -297,7 +297,7 @@ export class EventBufferer {
|
|||
}
|
||||
|
||||
bufferEvents(fn: () => void): void {
|
||||
const buffer = [];
|
||||
const buffer: Function[] = [];
|
||||
this.buffers.push(buffer);
|
||||
fn();
|
||||
this.buffers.pop();
|
||||
|
@ -334,7 +334,7 @@ class ChainableEvent<T> implements IChainableEvent<T> {
|
|||
return new ChainableEvent(filterEvent(this._event, fn));
|
||||
}
|
||||
|
||||
on(listener, thisArgs, disposables) {
|
||||
on(listener, thisArgs, disposables: IDisposable[]) {
|
||||
return this._event(listener, thisArgs, disposables);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -209,7 +209,7 @@ function analyzeCamelCaseWord(word: string): ICamelCaseAnalysis {
|
|||
}
|
||||
|
||||
function isUpperCaseWord(analysis: ICamelCaseAnalysis): boolean {
|
||||
const { upperPercent, lowerPercent, alphaPercent, numericPercent } = analysis;
|
||||
const { upperPercent, lowerPercent } = analysis;
|
||||
return lowerPercent === 0 && upperPercent > 0.6;
|
||||
}
|
||||
|
||||
|
@ -272,10 +272,11 @@ export function matchesCamelCase(word: string, camelCaseWord: string): IMatch[]
|
|||
}
|
||||
|
||||
// Matches beginning of words supporting non-ASCII languages
|
||||
// E.g. "gp" or "g p" will match "Git: Pull"
|
||||
// If `contiguous` is true then matches word with beginnings of the words in the target. E.g. "pul" will match "Git: Pull"
|
||||
// Otherwise also matches sub string of the word with beginnings of the words in the target. E.g. "gp" or "g p" will match "Git: Pull"
|
||||
// Useful in cases where the target is words (e.g. command labels)
|
||||
|
||||
export function matchesWords(word: string, target: string): IMatch[] {
|
||||
export function matchesWords(word: string, target: string, contiguous: boolean = false): IMatch[] {
|
||||
if (!target || target.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
@ -283,14 +284,14 @@ export function matchesWords(word: string, target: string): IMatch[] {
|
|||
let result: IMatch[] = null;
|
||||
let i = 0;
|
||||
|
||||
while (i < target.length && (result = _matchesWords(word.toLowerCase(), target, 0, i)) === null) {
|
||||
while (i < target.length && (result = _matchesWords(word.toLowerCase(), target, 0, i, contiguous)) === null) {
|
||||
i = nextWord(target, i + 1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function _matchesWords(word: string, target: string, i: number, j: number): IMatch[] {
|
||||
function _matchesWords(word: string, target: string, i: number, j: number, contiguous: boolean): IMatch[] {
|
||||
if (i === word.length) {
|
||||
return [];
|
||||
} else if (j === target.length) {
|
||||
|
@ -298,12 +299,14 @@ function _matchesWords(word: string, target: string, i: number, j: number): IMat
|
|||
} else if (word[i] !== target[j].toLowerCase()) {
|
||||
return null;
|
||||
} else {
|
||||
let result = null;
|
||||
let result: IMatch[] = null;
|
||||
let nextWordIndex = j + 1;
|
||||
result = _matchesWords(word, target, i + 1, j + 1);
|
||||
while (!result && (nextWordIndex = nextWord(target, nextWordIndex)) < target.length) {
|
||||
result = _matchesWords(word, target, i + 1, nextWordIndex);
|
||||
nextWordIndex++;
|
||||
result = _matchesWords(word, target, i + 1, j + 1, contiguous);
|
||||
if (!contiguous) {
|
||||
while (!result && (nextWordIndex = nextWord(target, nextWordIndex)) < target.length) {
|
||||
result = _matchesWords(word, target, i + 1, nextWordIndex, contiguous);
|
||||
nextWordIndex++;
|
||||
}
|
||||
}
|
||||
return result === null ? null : join({ start: j, end: j + 1 }, result);
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ export interface JSONScanner {
|
|||
/**
|
||||
* Sets the scan position to a new offset. A call to 'scan' is needed to get the first token.
|
||||
*/
|
||||
setPosition(pos: number);
|
||||
setPosition(pos: number): void;
|
||||
/**
|
||||
* Read the next token. Returns the tolen code.
|
||||
*/
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { isArray } from './types';
|
||||
|
||||
export const empty: IDisposable = Object.freeze({
|
||||
dispose() { }
|
||||
});
|
||||
|
@ -14,17 +12,24 @@ export interface IDisposable {
|
|||
dispose(): void;
|
||||
}
|
||||
|
||||
export function dispose<T extends IDisposable>(...disposables: T[]): T;
|
||||
export function dispose<T extends IDisposable>(disposable: T): T;
|
||||
export function dispose<T extends IDisposable>(...disposables: T[]): T[];
|
||||
export function dispose<T extends IDisposable>(disposables: T[]): T[];
|
||||
export function dispose<T extends IDisposable>(...disposables: T[]): T[] {
|
||||
const first = disposables[0];
|
||||
export function dispose<T extends IDisposable>(first: T | T[], ...rest: T[]): T | T[] {
|
||||
|
||||
if (isArray(first)) {
|
||||
disposables = first as any as T[];
|
||||
if (Array.isArray(first)) {
|
||||
first.forEach(d => d && d.dispose());
|
||||
return [];
|
||||
} else if (rest.length === 0) {
|
||||
if (first) {
|
||||
first.dispose();
|
||||
return first;
|
||||
}
|
||||
} else {
|
||||
dispose(first);
|
||||
dispose(rest);
|
||||
return [];
|
||||
}
|
||||
|
||||
disposables.forEach(d => d && d.dispose());
|
||||
return [];
|
||||
}
|
||||
|
||||
export function combinedDisposable(disposables: IDisposable[]): IDisposable {
|
||||
|
@ -105,4 +110,4 @@ export abstract class ReferenceCollection<T> {
|
|||
export class ImmortalReference<T> implements IReference<T> {
|
||||
constructor(public object: T) { }
|
||||
dispose(): void { /* noop */ }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ export class LinkedMap<K extends Key, T> {
|
|||
}
|
||||
|
||||
public keys(): K[] {
|
||||
var keys: K[] = [];
|
||||
const keys: K[] = [];
|
||||
for (let key in this.map) {
|
||||
keys.push(this.map[key].key);
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ export class LinkedMap<K extends Key, T> {
|
|||
}
|
||||
|
||||
public values(): T[] {
|
||||
var values: T[] = [];
|
||||
const values: T[] = [];
|
||||
for (let key in this.map) {
|
||||
values.push(this.map[key].value);
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ export class LinkedMap<K extends Key, T> {
|
|||
}
|
||||
|
||||
public entries(): Entry<K, T>[] {
|
||||
var entries: Entry<K, T>[] = [];
|
||||
const entries: Entry<K, T>[] = [];
|
||||
for (let key in this.map) {
|
||||
entries.push(this.map[key]);
|
||||
}
|
||||
|
@ -310,7 +310,7 @@ class Node<E> {
|
|||
*/
|
||||
export class TrieMap<E> {
|
||||
|
||||
static PathSplitter = s => s.split(/[\\/]/).filter(s => !!s);
|
||||
static PathSplitter = (s: string) => s.split(/[\\/]/).filter(s => !!s);
|
||||
|
||||
private _splitter: (s: string) => string[];
|
||||
private _root = new Node<E>();
|
||||
|
|
|
@ -143,7 +143,7 @@ function guessMimeTypeByPath(path: string, filename: string, associations: IText
|
|||
let patternMatch: ITextMimeAssociationItem;
|
||||
let extensionMatch: ITextMimeAssociationItem;
|
||||
|
||||
for (var i = 0; i < associations.length; i++) {
|
||||
for (let i = 0; i < associations.length; i++) {
|
||||
let association = associations[i];
|
||||
|
||||
// First exact name match
|
||||
|
@ -243,7 +243,7 @@ export function isUnspecific(mime: string[] | string): boolean {
|
|||
}
|
||||
|
||||
export function suggestFilename(langId: string, prefix: string): string {
|
||||
for (var i = 0; i < registeredAssociations.length; i++) {
|
||||
for (let i = 0; i < registeredAssociations.length; i++) {
|
||||
let association = registeredAssociations[i];
|
||||
if (association.userConfigured) {
|
||||
continue; // only support registered ones
|
||||
|
|
|
@ -12,23 +12,23 @@ export namespace Schemas {
|
|||
* A schema that is used for models that exist in memory
|
||||
* only and that have no correspondence on a server or such.
|
||||
*/
|
||||
export var inMemory: string = 'inmemory';
|
||||
export const inMemory: string = 'inmemory';
|
||||
|
||||
/**
|
||||
* A schema that is used for setting files
|
||||
*/
|
||||
export var vscode: string = 'vscode';
|
||||
export const vscode: string = 'vscode';
|
||||
|
||||
/**
|
||||
* A schema that is used for internal private files
|
||||
*/
|
||||
export var internal: string = 'private';
|
||||
export const internal: string = 'private';
|
||||
|
||||
export var http: string = 'http';
|
||||
export const http: string = 'http';
|
||||
|
||||
export var https: string = 'https';
|
||||
export const https: string = 'https';
|
||||
|
||||
export var file: string = 'file';
|
||||
export const file: string = 'file';
|
||||
}
|
||||
|
||||
export interface IXHROptions {
|
||||
|
|
|
@ -11,12 +11,12 @@ import { CharCode } from 'vs/base/common/charCode';
|
|||
/**
|
||||
* The forward slash path separator.
|
||||
*/
|
||||
export var sep = '/';
|
||||
export const sep = '/';
|
||||
|
||||
/**
|
||||
* The native path separator depending on the OS.
|
||||
*/
|
||||
export var nativeSep = isWindows ? '\\' : '/';
|
||||
export const nativeSep = isWindows ? '\\' : '/';
|
||||
|
||||
export function relative(from: string, to: string): string {
|
||||
const originalNormalizedFrom = normalize(from);
|
||||
|
@ -50,7 +50,7 @@ export function relative(from: string, to: string): string {
|
|||
* @returns the directory name of a path.
|
||||
*/
|
||||
export function dirname(path: string): string {
|
||||
var idx = ~path.lastIndexOf('/') || ~path.lastIndexOf('\\');
|
||||
const idx = ~path.lastIndexOf('/') || ~path.lastIndexOf('\\');
|
||||
if (idx === 0) {
|
||||
return '.';
|
||||
} else if (~idx === 0) {
|
||||
|
@ -64,7 +64,7 @@ export function dirname(path: string): string {
|
|||
* @returns the base name of a path.
|
||||
*/
|
||||
export function basename(path: string): string {
|
||||
var idx = ~path.lastIndexOf('/') || ~path.lastIndexOf('\\');
|
||||
const idx = ~path.lastIndexOf('/') || ~path.lastIndexOf('\\');
|
||||
if (idx === 0) {
|
||||
return path;
|
||||
} else if (~idx === path.length - 1) {
|
||||
|
@ -79,7 +79,7 @@ export function basename(path: string): string {
|
|||
*/
|
||||
export function extname(path: string): string {
|
||||
path = basename(path);
|
||||
var idx = ~path.lastIndexOf('.');
|
||||
const idx = ~path.lastIndexOf('.');
|
||||
return idx ? path.substring(~idx) : '';
|
||||
}
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@ let _isRootUser = false;
|
|||
let _isNative = false;
|
||||
let _isWeb = false;
|
||||
let _isQunit = false;
|
||||
let _locale = undefined;
|
||||
let _language = undefined;
|
||||
let _locale: string = undefined;
|
||||
let _language: string = undefined;
|
||||
|
||||
interface NLSConfig {
|
||||
locale: string;
|
||||
|
@ -124,7 +124,7 @@ interface IGlobals {
|
|||
clearTimeout(token: TimeoutToken): void;
|
||||
|
||||
setInterval(callback: (...args: any[]) => void, delay: number, ...args: any[]): IntervalToken;
|
||||
clearInterval(token: IntervalToken);
|
||||
clearInterval(token: IntervalToken): void;
|
||||
}
|
||||
|
||||
const _globals = <IGlobals>(typeof self === 'object' ? self : global);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { globals } from 'vs/base/common/platform';
|
||||
|
||||
var hasPerformanceNow = (globals.performance && typeof globals.performance.now === 'function');
|
||||
const hasPerformanceNow = (globals.performance && typeof globals.performance.now === 'function');
|
||||
|
||||
export class StopWatch {
|
||||
|
||||
|
|
|
@ -607,8 +607,8 @@ export function safeBtoa(str: string): string {
|
|||
}
|
||||
|
||||
export function repeat(s: string, count: number): string {
|
||||
var result = '';
|
||||
for (var i = 0; i < count; i++) {
|
||||
let result = '';
|
||||
for (let i = 0; i < count; i++) {
|
||||
result += s;
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -106,7 +106,7 @@ function read(zipPath: string, filePath: string): TPromise<Readable> {
|
|||
export function buffer(zipPath: string, filePath: string): TPromise<Buffer> {
|
||||
return read(zipPath, filePath).then(stream => {
|
||||
return new TPromise<Buffer>((c, e) => {
|
||||
const buffers = [];
|
||||
const buffers: Buffer[] = [];
|
||||
stream.once('error', e);
|
||||
stream.on('data', b => buffers.push(b));
|
||||
stream.on('end', () => c(Buffer.concat(buffers)));
|
||||
|
|
|
@ -689,15 +689,15 @@ export class QuickOpenModel implements
|
|||
return this._entries;
|
||||
}
|
||||
|
||||
getId(entry: QuickOpenEntry): string {
|
||||
public getId(entry: QuickOpenEntry): string {
|
||||
return entry.getId();
|
||||
}
|
||||
|
||||
getLabel(entry: QuickOpenEntry): string {
|
||||
public getLabel(entry: QuickOpenEntry): string {
|
||||
return entry.getLabel();
|
||||
}
|
||||
|
||||
getAriaLabel(entry: QuickOpenEntry): string {
|
||||
public getAriaLabel(entry: QuickOpenEntry): string {
|
||||
const ariaLabel = entry.getAriaLabel();
|
||||
if (ariaLabel) {
|
||||
return nls.localize('quickOpenAriaLabelEntry', "{0}, picker", entry.getAriaLabel());
|
||||
|
@ -706,11 +706,11 @@ export class QuickOpenModel implements
|
|||
return nls.localize('quickOpenAriaLabel', "picker");
|
||||
}
|
||||
|
||||
isVisible(entry: QuickOpenEntry): boolean {
|
||||
public isVisible(entry: QuickOpenEntry): boolean {
|
||||
return !entry.isHidden();
|
||||
}
|
||||
|
||||
run(entry: QuickOpenEntry, mode: Mode, context: IContext): boolean {
|
||||
public run(entry: QuickOpenEntry, mode: Mode, context: IContext): boolean {
|
||||
return entry.run(mode, context);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -328,7 +328,7 @@ export interface ITree extends Events.IEventEmitter {
|
|||
* Returns a navigator which allows to discover the visible and
|
||||
* expanded elements in the tree.
|
||||
*/
|
||||
getNavigator(): INavigator<any>;
|
||||
getNavigator(fromElement?: any, subTreeOnly?: boolean): INavigator<any>;
|
||||
|
||||
/**
|
||||
* Disposes the tree
|
||||
|
|
|
@ -318,8 +318,8 @@ export class Tree extends Events.EventEmitter implements _.ITree {
|
|||
return this.model.hasTrait(trait, element);
|
||||
}
|
||||
|
||||
getNavigator(): INavigator<any> {
|
||||
return new MappedNavigator(this.model.getNavigator(), i => i && i.getElement());
|
||||
getNavigator(fromElement?: any, subTreeOnly?: boolean): INavigator<any> {
|
||||
return new MappedNavigator(this.model.getNavigator(fromElement, subTreeOnly), i => i && i.getElement());
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
|
|
|
@ -186,5 +186,8 @@ suite('Filters', () => {
|
|||
filterOk(matchesWords, 'git プル', 'git: プル', [{ start: 0, end: 3 }, { start: 4, end: 7 }]);
|
||||
|
||||
filterOk(matchesWords, 'öäk', 'Öhm: Älles Klar', [{ start: 0, end: 1 }, { start: 5, end: 6 }, { start: 11, end: 12 }]);
|
||||
|
||||
assert.ok(matchesWords('gipu', 'Category: Git: Pull', true) === null);
|
||||
assert.deepEqual(matchesWords('pu', 'Category: Git: Pull', true), [{ start: 15, end: 17 }]);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
import { IWindowsMainService } from 'vs/code/electron-main/windows';
|
||||
import { IWindowsMainService, OpenContext } from 'vs/code/electron-main/windows';
|
||||
import { VSCodeWindow } from 'vs/code/electron-main/window';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
|
@ -82,6 +82,7 @@ export class LaunchService implements ILaunchService {
|
|||
|
||||
const openUrlArg = args['open-url'] || [];
|
||||
const openUrl = typeof openUrlArg === 'string' ? [openUrlArg] : openUrlArg;
|
||||
const context = !!userEnv['VSCODE_CLI'] ? OpenContext.CLI : OpenContext.OTHER;
|
||||
|
||||
if (openUrl.length > 0) {
|
||||
openUrl.forEach(url => this.urlService.open(url));
|
||||
|
@ -91,17 +92,19 @@ export class LaunchService implements ILaunchService {
|
|||
// Otherwise handle in windows service
|
||||
let usedWindows: VSCodeWindow[];
|
||||
if (!!args.extensionDevelopmentPath) {
|
||||
this.windowsService.openExtensionDevelopmentHostWindow({ cli: args, userEnv });
|
||||
this.windowsService.openExtensionDevelopmentHostWindow({ context, cli: args, userEnv });
|
||||
} else if (args._.length === 0 && args['new-window']) {
|
||||
usedWindows = this.windowsService.open({ cli: args, userEnv, forceNewWindow: true, forceEmpty: true });
|
||||
usedWindows = this.windowsService.open({ context, cli: args, userEnv, forceNewWindow: true, forceEmpty: true });
|
||||
} else if (args._.length === 0) {
|
||||
usedWindows = [this.windowsService.focusLastActive(args)];
|
||||
usedWindows = [this.windowsService.focusLastActive(args, context)];
|
||||
} else {
|
||||
usedWindows = this.windowsService.open({
|
||||
context,
|
||||
cli: args,
|
||||
userEnv,
|
||||
forceNewWindow: args.wait || args['new-window'],
|
||||
preferNewWindow: !args['reuse-window'],
|
||||
forceReuseWindow: args['reuse-window'],
|
||||
diffMode: args.diff
|
||||
});
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import * as platform from 'vs/base/common/platform';
|
|||
import { parseMainProcessArgv } from 'vs/platform/environment/node/argv';
|
||||
import { mkdirp } from 'vs/base/node/pfs';
|
||||
import { validatePaths } from 'vs/code/electron-main/paths';
|
||||
import { IWindowsMainService, WindowsManager } from 'vs/code/electron-main/windows';
|
||||
import { IWindowsMainService, WindowsManager, OpenContext } from 'vs/code/electron-main/windows';
|
||||
import { IWindowsService } from 'vs/platform/windows/common/windows';
|
||||
import { WindowsChannel } from 'vs/platform/windows/common/windowsIpc';
|
||||
import { WindowsService } from 'vs/platform/windows/electron-main/windowsService';
|
||||
|
@ -251,12 +251,13 @@ function main(accessor: ServicesAccessor, mainIpcServer: Server, userEnv: platfo
|
|||
windowsMainService.ready(userEnv);
|
||||
|
||||
// Open our first window
|
||||
const context = !!process.env['VSCODE_CLI'] ? OpenContext.CLI : OpenContext.OTHER;
|
||||
if (environmentService.args['new-window'] && environmentService.args._.length === 0) {
|
||||
windowsMainService.open({ cli: environmentService.args, forceNewWindow: true, forceEmpty: true, initialStartup: true }); // new window if "-n" was used without paths
|
||||
windowsMainService.open({ context, cli: environmentService.args, forceNewWindow: true, forceEmpty: true, initialStartup: true }); // new window if "-n" was used without paths
|
||||
} else if (global.macOpenFiles && global.macOpenFiles.length && (!environmentService.args._ || !environmentService.args._.length)) {
|
||||
windowsMainService.open({ cli: environmentService.args, pathsToOpen: global.macOpenFiles, initialStartup: true }); // mac: open-file event received on startup
|
||||
windowsMainService.open({ context: OpenContext.DOCK, cli: environmentService.args, pathsToOpen: global.macOpenFiles, initialStartup: true }); // mac: open-file event received on startup
|
||||
} else {
|
||||
windowsMainService.open({ cli: environmentService.args, forceNewWindow: environmentService.args['new-window'], diffMode: environmentService.args.diff, initialStartup: true }); // default: read paths from cli
|
||||
windowsMainService.open({ context, cli: environmentService.args, forceNewWindow: environmentService.args['new-window'], diffMode: environmentService.args.diff, initialStartup: true }); // default: read paths from cli
|
||||
}
|
||||
|
||||
// Install Menu
|
||||
|
|
|
@ -10,7 +10,7 @@ import * as platform from 'vs/base/common/platform';
|
|||
import * as arrays from 'vs/base/common/arrays';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { ipcMain as ipc, app, shell, dialog, Menu, MenuItem } from 'electron';
|
||||
import { IWindowsMainService } from 'vs/code/electron-main/windows';
|
||||
import { IWindowsMainService, OpenContext } from 'vs/code/electron-main/windows';
|
||||
import { VSCodeWindow } from 'vs/code/electron-main/window';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IStorageService } from 'vs/code/electron-main/storage';
|
||||
|
@ -315,7 +315,7 @@ export class VSCodeMenu {
|
|||
this.appMenuInstalled = true;
|
||||
|
||||
const dockMenu = new Menu();
|
||||
dockMenu.append(new MenuItem({ label: mnemonicLabel(nls.localize({ key: 'miNewWindow', comment: ['&& denotes a mnemonic'] }, "New &&Window")), click: () => this.windowsService.openNewWindow() }));
|
||||
dockMenu.append(new MenuItem({ label: mnemonicLabel(nls.localize({ key: 'miNewWindow', comment: ['&& denotes a mnemonic'] }, "New &&Window")), click: () => this.windowsService.openNewWindow(OpenContext.DOCK) }));
|
||||
|
||||
app.dock.setMenu(dockMenu);
|
||||
}
|
||||
|
@ -351,19 +351,19 @@ export class VSCodeMenu {
|
|||
|
||||
let newFile: Electron.MenuItem;
|
||||
if (hasNoWindows) {
|
||||
newFile = new MenuItem(this.likeAction('workbench.action.files.newUntitledFile', { label: mnemonicLabel(nls.localize({ key: 'miNewFile', comment: ['&& denotes a mnemonic'] }, "&&New File")), click: () => this.windowsService.openNewWindow() }));
|
||||
newFile = new MenuItem(this.likeAction('workbench.action.files.newUntitledFile', { label: mnemonicLabel(nls.localize({ key: 'miNewFile', comment: ['&& denotes a mnemonic'] }, "&&New File")), click: () => this.windowsService.openNewWindow(OpenContext.MENU) }));
|
||||
} else {
|
||||
newFile = this.createMenuItem(nls.localize({ key: 'miNewFile', comment: ['&& denotes a mnemonic'] }, "&&New File"), 'workbench.action.files.newUntitledFile');
|
||||
}
|
||||
|
||||
const open = new MenuItem(this.likeAction('workbench.action.files.openFileFolder', { label: mnemonicLabel(nls.localize({ key: 'miOpen', comment: ['&& denotes a mnemonic'] }, "&&Open...")), click: () => this.windowsService.openFileFolderPicker() }));
|
||||
const openFolder = new MenuItem(this.likeAction('workbench.action.files.openFolder', { label: mnemonicLabel(nls.localize({ key: 'miOpenFolder', comment: ['&& denotes a mnemonic'] }, "Open &&Folder...")), click: () => this.windowsService.openFolderPicker() }));
|
||||
const open = new MenuItem(this.likeAction('workbench.action.files.openFileFolder', { label: mnemonicLabel(nls.localize({ key: 'miOpen', comment: ['&& denotes a mnemonic'] }, "&&Open...")), click: (menuItem, win, event) => this.windowsService.openFileFolderPicker(this.isOptionClick(event)) }));
|
||||
const openFolder = new MenuItem(this.likeAction('workbench.action.files.openFolder', { label: mnemonicLabel(nls.localize({ key: 'miOpenFolder', comment: ['&& denotes a mnemonic'] }, "Open &&Folder...")), click: (menuItem, win, event) => this.windowsService.openFolderPicker(this.isOptionClick(event)) }));
|
||||
|
||||
let openFile: Electron.MenuItem;
|
||||
if (hasNoWindows) {
|
||||
openFile = new MenuItem(this.likeAction('workbench.action.files.openFile', { label: mnemonicLabel(nls.localize({ key: 'miOpenFile', comment: ['&& denotes a mnemonic'] }, "&&Open File...")), click: () => this.windowsService.openFilePicker() }));
|
||||
openFile = new MenuItem(this.likeAction('workbench.action.files.openFile', { label: mnemonicLabel(nls.localize({ key: 'miOpenFile', comment: ['&& denotes a mnemonic'] }, "&&Open File...")), click: (menuItem, win, event) => this.windowsService.openFilePicker(this.isOptionClick(event)) }));
|
||||
} else {
|
||||
openFile = this.createMenuItem(nls.localize({ key: 'miOpenFile', comment: ['&& denotes a mnemonic'] }, "&&Open File..."), 'workbench.action.files.openFile');
|
||||
openFile = this.createMenuItem(nls.localize({ key: 'miOpenFile', comment: ['&& denotes a mnemonic'] }, "&&Open File..."), ['workbench.action.files.openFile', 'workbench.action.files.openFileInNewWindow']);
|
||||
}
|
||||
|
||||
const openRecentMenu = new Menu();
|
||||
|
@ -379,7 +379,7 @@ export class VSCodeMenu {
|
|||
|
||||
const preferences = this.getPreferencesMenu();
|
||||
|
||||
const newWindow = new MenuItem(this.likeAction('workbench.action.newWindow', { label: mnemonicLabel(nls.localize({ key: 'miNewWindow', comment: ['&& denotes a mnemonic'] }, "New &&Window")), click: () => this.windowsService.openNewWindow() }));
|
||||
const newWindow = new MenuItem(this.likeAction('workbench.action.newWindow', { label: mnemonicLabel(nls.localize({ key: 'miNewWindow', comment: ['&& denotes a mnemonic'] }, "New &&Window")), click: () => this.windowsService.openNewWindow(OpenContext.MENU) }));
|
||||
const revertFile = this.createMenuItem(nls.localize({ key: 'miRevert', comment: ['&& denotes a mnemonic'] }, "Re&&vert File"), 'workbench.action.files.revert', this.windowsService.getWindowCount() > 0);
|
||||
const closeWindow = new MenuItem(this.likeAction('workbench.action.closeWindow', { label: mnemonicLabel(nls.localize({ key: 'miCloseWindow', comment: ['&& denotes a mnemonic'] }, "Clos&&e Window")), click: () => this.windowsService.getLastActiveWindow().win.close(), enabled: this.windowsService.getWindowCount() > 0 }));
|
||||
|
||||
|
@ -468,10 +468,15 @@ export class VSCodeMenu {
|
|||
}
|
||||
|
||||
private createOpenRecentMenuItem(path: string, actionId: string): Electron.MenuItem {
|
||||
let label = path;
|
||||
if ((platform.isMacintosh || platform.isLinux) && path.indexOf(this.environmentService.userHome) === 0) {
|
||||
label = `~${path.substr(this.environmentService.userHome.length)}`;
|
||||
}
|
||||
|
||||
return new MenuItem(this.likeAction(actionId, {
|
||||
label: unMnemonicLabel(path), click: (menuItem, win, event) => {
|
||||
const openInNewWindow = event && ((!platform.isMacintosh && event.ctrlKey) || (platform.isMacintosh && event.metaKey));
|
||||
const success = !!this.windowsService.open({ cli: this.environmentService.args, pathsToOpen: [path], forceNewWindow: openInNewWindow });
|
||||
label: unMnemonicLabel(label), click: (menuItem, win, event) => {
|
||||
const openInNewWindow = this.isOptionClick(event);
|
||||
const success = !!this.windowsService.open({ context: OpenContext.MENU, cli: this.environmentService.args, pathsToOpen: [path], forceNewWindow: openInNewWindow });
|
||||
if (!success) {
|
||||
this.windowsService.removeFromRecentPathsList(path);
|
||||
}
|
||||
|
@ -479,6 +484,10 @@ export class VSCodeMenu {
|
|||
}, false));
|
||||
}
|
||||
|
||||
private isOptionClick(event: Electron.Event): boolean {
|
||||
return event && ((!platform.isMacintosh && (event.ctrlKey || event.shiftKey)) || (platform.isMacintosh && (event.metaKey || event.altKey)));
|
||||
}
|
||||
|
||||
private createRoleMenuItem(label: string, actionId: string, role: Electron.MenuItemRole): Electron.MenuItem {
|
||||
const options: Electron.MenuItemOptions = {
|
||||
label: mnemonicLabel(label),
|
||||
|
@ -890,11 +899,18 @@ export class VSCodeMenu {
|
|||
}
|
||||
}
|
||||
|
||||
private createMenuItem(label: string, actionId: string, enabled?: boolean, checked?: boolean): Electron.MenuItem;
|
||||
private createMenuItem(label: string, actionId: string | string[], enabled?: boolean, checked?: boolean): Electron.MenuItem;
|
||||
private createMenuItem(label: string, click: () => void, enabled?: boolean, checked?: boolean): Electron.MenuItem;
|
||||
private createMenuItem(arg1: string, arg2: any, arg3?: boolean, arg4?: boolean): Electron.MenuItem {
|
||||
const label = mnemonicLabel(arg1);
|
||||
const click: () => void = (typeof arg2 === 'function') ? arg2 : () => this.windowsService.sendToFocused('vscode:runAction', arg2);
|
||||
const click: () => void = (typeof arg2 === 'function') ? arg2 : (menuItem, win, event) => {
|
||||
let actionId = arg2;
|
||||
if (Array.isArray(arg2)) {
|
||||
actionId = this.isOptionClick(event) ? arg2[1] : arg2[0]; // support alternative action if we got multiple action Ids and the option key was pressed while invoking
|
||||
}
|
||||
|
||||
this.windowsService.sendToFocused('vscode:runAction', actionId);
|
||||
};
|
||||
const enabled = typeof arg3 === 'boolean' ? arg3 : this.windowsService.getWindowCount() > 0;
|
||||
const checked = typeof arg4 === 'boolean' ? arg4 : false;
|
||||
|
||||
|
|
|
@ -205,21 +205,6 @@ export class VSCodeWindow implements IVSCodeWindow {
|
|||
this._win = new BrowserWindow(options);
|
||||
this._id = this._win.id;
|
||||
|
||||
// TODO@joao: hook this up to some initialization routine
|
||||
// this causes a race between setting the headers and doing
|
||||
// a request that needs them. chances are low
|
||||
getCommonHTTPHeaders().done(headers => {
|
||||
if (!this._win) {
|
||||
return;
|
||||
}
|
||||
|
||||
const urls = ['https://marketplace.visualstudio.com/*', 'https://*.vsassets.io/*'];
|
||||
|
||||
this._win.webContents.session.webRequest.onBeforeSendHeaders({ urls }, (details, cb) => {
|
||||
cb({ cancel: false, requestHeaders: objects.assign(details.requestHeaders, headers) });
|
||||
});
|
||||
});
|
||||
|
||||
if (isFullscreenOrMaximized) {
|
||||
this.win.maximize();
|
||||
|
||||
|
@ -238,9 +223,28 @@ export class VSCodeWindow implements IVSCodeWindow {
|
|||
this.setMenuBarVisibility(false); // respect configured menu bar visibility
|
||||
}
|
||||
|
||||
// TODO@joao: hook this up to some initialization routine
|
||||
// this causes a race between setting the headers and doing
|
||||
// a request that needs them. chances are low
|
||||
this.setCommonHTTPHeaders();
|
||||
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
private setCommonHTTPHeaders(): void {
|
||||
getCommonHTTPHeaders().done(headers => {
|
||||
if (!this._win) {
|
||||
return;
|
||||
}
|
||||
|
||||
const urls = ['https://marketplace.visualstudio.com/*', 'https://*.vsassets.io/*'];
|
||||
|
||||
this._win.webContents.session.webRequest.onBeforeSendHeaders({ urls }, (details, cb) => {
|
||||
cb({ cancel: false, requestHeaders: objects.assign(details.requestHeaders, headers) });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public hasHiddenTitleBarStyle(): boolean {
|
||||
return this.hiddenTitleBarStyle;
|
||||
}
|
||||
|
@ -478,7 +482,7 @@ export class VSCodeWindow implements IVSCodeWindow {
|
|||
windowConfiguration.fullscreen = this._win.isFullScreen();
|
||||
|
||||
// Set Accessibility Config
|
||||
windowConfiguration.highContrast = platform.isWindows && systemPreferences.isInvertedColorScheme();
|
||||
windowConfiguration.highContrast = platform.isWindows && systemPreferences.isInvertedColorScheme() && (!windowConfig || windowConfig.autoDetectHighContrast);
|
||||
windowConfiguration.accessibilitySupport = app.isAccessibilitySupportEnabled();
|
||||
|
||||
// Perf Counters
|
||||
|
|
|
@ -34,12 +34,32 @@ enum WindowError {
|
|||
CRASHED
|
||||
}
|
||||
|
||||
export enum OpenContext {
|
||||
|
||||
// opening when running from the command line
|
||||
CLI,
|
||||
|
||||
// macOS only: opening from the dock (also when opening files to a running instance from desktop)
|
||||
DOCK,
|
||||
|
||||
// opening from the main application window
|
||||
MENU,
|
||||
|
||||
// opening from a file or folder dialog
|
||||
DIALOG,
|
||||
|
||||
// any other way of opening
|
||||
OTHER
|
||||
}
|
||||
|
||||
export interface IOpenConfiguration {
|
||||
context: OpenContext;
|
||||
cli: ParsedArgs;
|
||||
userEnv?: platform.IProcessEnvironment;
|
||||
pathsToOpen?: string[];
|
||||
preferNewWindow?: boolean;
|
||||
forceNewWindow?: boolean;
|
||||
forceReuseWindow?: boolean;
|
||||
forceEmpty?: boolean;
|
||||
windowToUse?: VSCodeWindow;
|
||||
diffMode?: boolean;
|
||||
|
@ -96,10 +116,10 @@ export interface IWindowsMainService {
|
|||
openFilePicker(forceNewWindow?: boolean, path?: string, window?: VSCodeWindow): void;
|
||||
openFolderPicker(forceNewWindow?: boolean, window?: VSCodeWindow): void;
|
||||
openAccessibilityOptions(): void;
|
||||
focusLastActive(cli: ParsedArgs): VSCodeWindow;
|
||||
focusLastActive(cli: ParsedArgs, context: OpenContext): VSCodeWindow;
|
||||
getLastActiveWindow(): VSCodeWindow;
|
||||
findWindow(workspacePath: string, filePath?: string, extensionDevelopmentPath?: string): VSCodeWindow;
|
||||
openNewWindow(): void;
|
||||
openNewWindow(context: OpenContext): void;
|
||||
sendToFocused(channel: string, ...args: any[]): void;
|
||||
sendToAll(channel: string, payload: any, windowIdsToIgnore?: number[]): void;
|
||||
getFocusedWindow(): VSCodeWindow;
|
||||
|
@ -166,7 +186,7 @@ export class WindowsManager implements IWindowsMainService {
|
|||
|
||||
// Mac only event: open new window when we get activated
|
||||
if (!hasVisibleWindows) {
|
||||
this.openNewWindow();
|
||||
this.openNewWindow(OpenContext.DOCK);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -187,7 +207,12 @@ export class WindowsManager implements IWindowsMainService {
|
|||
|
||||
// Handle paths delayed in case more are coming!
|
||||
runningTimeout = setTimeout(() => {
|
||||
this.open({ cli: this.environmentService.args, pathsToOpen: macOpenFiles, preferNewWindow: true /* dropping on the dock prefers to open in a new window */ });
|
||||
this.open({
|
||||
context: OpenContext.DOCK /* can also be opening from finder while app is running */,
|
||||
cli: this.environmentService.args,
|
||||
pathsToOpen: macOpenFiles,
|
||||
preferNewWindow: true /* dropping on the dock or opening from finder prefers to open in a new window */
|
||||
});
|
||||
macOpenFiles = [];
|
||||
runningTimeout = null;
|
||||
}, 100);
|
||||
|
@ -272,6 +297,8 @@ export class WindowsManager implements IWindowsMainService {
|
|||
}
|
||||
|
||||
public open(openConfig: IOpenConfiguration): VSCodeWindow[] {
|
||||
const windowConfig = this.configurationService.getConfiguration<IWindowSettings>('window');
|
||||
|
||||
let iPathsToOpen: IPath[];
|
||||
const usedWindows: VSCodeWindow[] = [];
|
||||
|
||||
|
@ -345,22 +372,26 @@ export class WindowsManager implements IWindowsMainService {
|
|||
filesToOpen = candidates;
|
||||
}
|
||||
|
||||
let openInNewWindow = openConfig.preferNewWindow || openConfig.forceNewWindow;
|
||||
// let the user settings override how folders are open in a new window or same window unless we are forced
|
||||
let openFolderInNewWindow = (openConfig.preferNewWindow || openConfig.forceNewWindow) && !openConfig.forceReuseWindow;
|
||||
if (!openConfig.forceNewWindow && !openConfig.forceReuseWindow && windowConfig && (windowConfig.openFoldersInNewWindow === 'on' || windowConfig.openFoldersInNewWindow === 'off')) {
|
||||
openFolderInNewWindow = (windowConfig.openFoldersInNewWindow === 'on');
|
||||
}
|
||||
|
||||
// Handle files to open/diff or to create when we dont open a folder
|
||||
if (!foldersToOpen.length && (filesToOpen.length > 0 || filesToCreate.length > 0 || filesToDiff.length > 0)) {
|
||||
|
||||
// const the user settings override how files are open in a new window or same window unless we are forced
|
||||
// let the user settings override how files are open in a new window or same window unless we are forced (not for extension development though)
|
||||
let openFilesInNewWindow: boolean;
|
||||
if (openConfig.forceNewWindow) {
|
||||
openFilesInNewWindow = true;
|
||||
if (openConfig.forceNewWindow || openConfig.forceReuseWindow) {
|
||||
openFilesInNewWindow = openConfig.forceNewWindow && !openConfig.forceReuseWindow;
|
||||
} else {
|
||||
openFilesInNewWindow = openConfig.preferNewWindow;
|
||||
if (openFilesInNewWindow && !openConfig.cli.extensionDevelopmentPath) { // can be overriden via settings (not for PDE though!)
|
||||
const windowConfig = this.configurationService.getConfiguration<IWindowSettings>('window');
|
||||
if (windowConfig && !windowConfig.openFilesInNewWindow) {
|
||||
openFilesInNewWindow = false; // do not open in new window if user configured this explicitly
|
||||
}
|
||||
if (openConfig.context === OpenContext.DOCK) {
|
||||
openFilesInNewWindow = true; // only on macOS do we allow to open files in a new window if this is triggered via DOCK context
|
||||
}
|
||||
|
||||
if (!openConfig.cli.extensionDevelopmentPath && windowConfig && (windowConfig.openFilesInNewWindow === 'on' || windowConfig.openFilesInNewWindow === 'off' || <any>windowConfig.openFilesInNewWindow === false /* TODO@Ben migration */)) {
|
||||
openFilesInNewWindow = (windowConfig.openFilesInNewWindow === 'on');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -368,8 +399,9 @@ export class WindowsManager implements IWindowsMainService {
|
|||
const lastActiveWindow = this.getLastActiveWindow();
|
||||
if (!openFilesInNewWindow && lastActiveWindow) {
|
||||
lastActiveWindow.focus();
|
||||
const files = { filesToOpen, filesToCreate, filesToDiff }; // copy to object because they get reset shortly after
|
||||
lastActiveWindow.ready().then(readyWindow => {
|
||||
readyWindow.send('vscode:openFiles', { filesToOpen, filesToCreate, filesToDiff });
|
||||
readyWindow.send('vscode:openFiles', files);
|
||||
});
|
||||
|
||||
usedWindows.push(lastActiveWindow);
|
||||
|
@ -381,7 +413,7 @@ export class WindowsManager implements IWindowsMainService {
|
|||
const browserWindow = this.openInBrowserWindow(configuration, true /* new window */);
|
||||
usedWindows.push(browserWindow);
|
||||
|
||||
openInNewWindow = true; // any other folders to open must open in new window then
|
||||
openFolderInNewWindow = true; // any other folders to open must open in new window then
|
||||
}
|
||||
|
||||
// Reset these because we handled them
|
||||
|
@ -399,8 +431,9 @@ export class WindowsManager implements IWindowsMainService {
|
|||
if (windowsOnWorkspacePath.length > 0) {
|
||||
const browserWindow = windowsOnWorkspacePath[0];
|
||||
browserWindow.focus(); // just focus one of them
|
||||
const files = { filesToOpen, filesToCreate, filesToDiff }; // copy to object because they get reset shortly after
|
||||
browserWindow.ready().then(readyWindow => {
|
||||
readyWindow.send('vscode:openFiles', { filesToOpen, filesToCreate, filesToDiff });
|
||||
readyWindow.send('vscode:openFiles', files);
|
||||
});
|
||||
|
||||
usedWindows.push(browserWindow);
|
||||
|
@ -410,7 +443,7 @@ export class WindowsManager implements IWindowsMainService {
|
|||
filesToCreate = [];
|
||||
filesToDiff = [];
|
||||
|
||||
openInNewWindow = true; // any other folders to open must open in new window then
|
||||
openFolderInNewWindow = true; // any other folders to open must open in new window then
|
||||
}
|
||||
|
||||
// Open remaining ones
|
||||
|
@ -420,7 +453,7 @@ export class WindowsManager implements IWindowsMainService {
|
|||
}
|
||||
|
||||
const configuration = this.toConfiguration(openConfig, folderToOpen, filesToOpen, filesToCreate, filesToDiff);
|
||||
const browserWindow = this.openInBrowserWindow(configuration, openInNewWindow, openInNewWindow ? void 0 : openConfig.windowToUse);
|
||||
const browserWindow = this.openInBrowserWindow(configuration, openFolderInNewWindow, openFolderInNewWindow ? void 0 : openConfig.windowToUse);
|
||||
usedWindows.push(browserWindow);
|
||||
|
||||
// Reset these because we handled them
|
||||
|
@ -428,7 +461,7 @@ export class WindowsManager implements IWindowsMainService {
|
|||
filesToCreate = [];
|
||||
filesToDiff = [];
|
||||
|
||||
openInNewWindow = true; // any other folders to open must open in new window then
|
||||
openFolderInNewWindow = true; // any other folders to open must open in new window then
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -439,7 +472,7 @@ export class WindowsManager implements IWindowsMainService {
|
|||
const browserWindow = this.openInBrowserWindow(configuration, true /* new window */, null, emptyWorkspaceBackupFolder);
|
||||
usedWindows.push(browserWindow);
|
||||
|
||||
openInNewWindow = true; // any other folders to open must open in new window then
|
||||
openFolderInNewWindow = true; // any other folders to open must open in new window then
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -447,10 +480,10 @@ export class WindowsManager implements IWindowsMainService {
|
|||
else if (emptyToOpen.length > 0) {
|
||||
emptyToOpen.forEach(() => {
|
||||
const configuration = this.toConfiguration(openConfig);
|
||||
const browserWindow = this.openInBrowserWindow(configuration, openInNewWindow, openInNewWindow ? void 0 : openConfig.windowToUse);
|
||||
const browserWindow = this.openInBrowserWindow(configuration, openFolderInNewWindow, openFolderInNewWindow ? void 0 : openConfig.windowToUse);
|
||||
usedWindows.push(browserWindow);
|
||||
|
||||
openInNewWindow = true; // any other folders to open must open in new window then
|
||||
openFolderInNewWindow = true; // any other folders to open must open in new window then
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -609,7 +642,7 @@ export class WindowsManager implements IWindowsMainService {
|
|||
}
|
||||
|
||||
// Open it
|
||||
this.open({ cli: openConfig.cli, forceNewWindow: true, forceEmpty: openConfig.cli._.length === 0 });
|
||||
this.open({ context: openConfig.context, cli: openConfig.cli, forceNewWindow: true, forceEmpty: openConfig.cli._.length === 0 });
|
||||
}
|
||||
|
||||
private toConfiguration(config: IOpenConfiguration, workspacePath?: string, filesToOpen?: IPath[], filesToCreate?: IPath[], filesToDiff?: IPath[]): IWindowConfiguration {
|
||||
|
@ -889,7 +922,7 @@ export class WindowsManager implements IWindowsMainService {
|
|||
private doPickAndOpen(options: INativeOpenDialogOptions): void {
|
||||
this.getFileOrFolderPaths(options, (paths: string[]) => {
|
||||
if (paths && paths.length) {
|
||||
this.open({ cli: this.environmentService.args, pathsToOpen: paths, forceNewWindow: options.forceNewWindow });
|
||||
this.open({ context: OpenContext.DIALOG, cli: this.environmentService.args, pathsToOpen: paths, forceNewWindow: options.forceNewWindow });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -922,7 +955,7 @@ export class WindowsManager implements IWindowsMainService {
|
|||
});
|
||||
}
|
||||
|
||||
public focusLastActive(cli: ParsedArgs): VSCodeWindow {
|
||||
public focusLastActive(cli: ParsedArgs, context: OpenContext): VSCodeWindow {
|
||||
const lastActive = this.getLastActiveWindow();
|
||||
if (lastActive) {
|
||||
lastActive.focus();
|
||||
|
@ -932,7 +965,7 @@ export class WindowsManager implements IWindowsMainService {
|
|||
|
||||
// No window - open new one
|
||||
this.windowsState.openedFolders = []; // make sure we do not open too much
|
||||
const res = this.open({ cli: cli });
|
||||
const res = this.open({ context, cli });
|
||||
|
||||
return res && res[0];
|
||||
}
|
||||
|
@ -994,8 +1027,8 @@ export class WindowsManager implements IWindowsMainService {
|
|||
return null;
|
||||
}
|
||||
|
||||
public openNewWindow(): void {
|
||||
this.open({ cli: this.environmentService.args, forceNewWindow: true, forceEmpty: true });
|
||||
public openNewWindow(context: OpenContext): void {
|
||||
this.open({ context, cli: this.environmentService.args, forceNewWindow: true, forceEmpty: true });
|
||||
}
|
||||
|
||||
public sendToFocused(channel: string, ...args: any[]): void {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
'use strict';
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { merge } from 'vs/base/common/arrays';
|
||||
import { flatten } from 'vs/base/common/arrays';
|
||||
import { IStringDictionary, forEach, values } from 'vs/base/common/collections';
|
||||
import { IDisposable, dispose, IReference } from 'vs/base/common/lifecycle';
|
||||
import URI from 'vs/base/common/uri';
|
||||
|
@ -34,7 +34,7 @@ class ChangeRecorder {
|
|||
|
||||
private _fileService: IFileService;
|
||||
|
||||
constructor(fileService: IFileService) {
|
||||
constructor(fileService?: IFileService) {
|
||||
this._fileService = fileService;
|
||||
}
|
||||
|
||||
|
@ -42,24 +42,27 @@ class ChangeRecorder {
|
|||
|
||||
const changes: IStringDictionary<IFileChange[]> = Object.create(null);
|
||||
|
||||
const stop = this._fileService.onFileChanges((event) => {
|
||||
event.changes.forEach(change => {
|
||||
let stop: IDisposable;
|
||||
if (this._fileService) {
|
||||
stop = this._fileService.onFileChanges((event) => {
|
||||
event.changes.forEach(change => {
|
||||
|
||||
const key = String(change.resource);
|
||||
let array = changes[key];
|
||||
const key = String(change.resource);
|
||||
let array = changes[key];
|
||||
|
||||
if (!array) {
|
||||
changes[key] = array = [];
|
||||
}
|
||||
if (!array) {
|
||||
changes[key] = array = [];
|
||||
}
|
||||
|
||||
array.push(change);
|
||||
array.push(change);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
stop: () => { stop.dispose(); },
|
||||
stop: () => { return stop && stop.dispose(); },
|
||||
hasChanged: (resource: URI) => !!changes[resource.toString()],
|
||||
allChanges: () => merge(values(changes))
|
||||
allChanges: () => flatten(values(changes))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -273,14 +276,14 @@ export interface BulkEdit {
|
|||
finish(): TPromise<ISelection>;
|
||||
}
|
||||
|
||||
export function bulkEdit(fileService: IFileService, textModelResolverService: ITextModelResolverService, editor: ICommonCodeEditor, edits: IResourceEdit[], progress: IProgressRunner = null): TPromise<any> {
|
||||
let bulk = createBulkEdit(fileService, textModelResolverService, editor);
|
||||
export function bulkEdit(textModelResolverService: ITextModelResolverService, editor: ICommonCodeEditor, edits: IResourceEdit[], fileService?: IFileService, progress: IProgressRunner = null): TPromise<any> {
|
||||
let bulk = createBulkEdit(textModelResolverService, editor, fileService);
|
||||
bulk.add(edits);
|
||||
bulk.progress(progress);
|
||||
return bulk.finish();
|
||||
}
|
||||
|
||||
export function createBulkEdit(fileService: IFileService, textModelResolverService: ITextModelResolverService, editor: ICommonCodeEditor): BulkEdit {
|
||||
export function createBulkEdit(textModelResolverService: ITextModelResolverService, editor?: ICommonCodeEditor, fileService?: IFileService): BulkEdit {
|
||||
|
||||
let all: IResourceEdit[] = [];
|
||||
let recording = new ChangeRecorder(fileService).start();
|
||||
|
|
|
@ -11,12 +11,11 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
|||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { ActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ActionItem, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IMenuService, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { fillInActions } from 'vs/platform/actions/browser/menuItemActionItem';
|
||||
import { ICommonCodeEditor, IEditorContribution, MouseTargetType, EditorContextKeys, IScrollEvent } from 'vs/editor/common/editorCommon';
|
||||
import { editorAction, ServicesAccessor, EditorAction } from 'vs/editor/common/editorCommonExtensions';
|
||||
import { ICodeEditor, IEditorMouseEvent } from 'vs/editor/browser/editorBrowser';
|
||||
|
@ -125,9 +124,17 @@ export class ContextMenuController implements IEditorContribution {
|
|||
|
||||
private _getMenuActions(): IAction[] {
|
||||
const result: IAction[] = [];
|
||||
const contextMenu = this._menuService.createMenu(MenuId.EditorContext, this._contextKeyService);
|
||||
fillInActions(contextMenu, this._editor.getModel().uri, result);
|
||||
|
||||
let contextMenu = this._menuService.createMenu(MenuId.EditorContext, this._contextKeyService);
|
||||
const groups = contextMenu.getActions(this._editor.getModel().uri);
|
||||
contextMenu.dispose();
|
||||
|
||||
for (let group of groups) {
|
||||
const [, actions] = group;
|
||||
result.push(...actions);
|
||||
result.push(new Separator());
|
||||
}
|
||||
result.pop(); // remove last separator
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -105,10 +105,12 @@
|
|||
}
|
||||
|
||||
.monaco-editor .find-widget.no-results .matchesCount {
|
||||
background-color: rgba(255,0,0,0.5);
|
||||
color: #A1260D;
|
||||
}
|
||||
.monaco-editor.vs-dark .find-widget.no-results .matchesCount {
|
||||
background-color: rgba(255,0,0,0.3);
|
||||
|
||||
.monaco-editor.vs-dark .find-widget.no-results .matchesCount,
|
||||
.monaco-editor.hc-black .find-widget.no-results .matchesCount {
|
||||
color: #F48771
|
||||
}
|
||||
|
||||
.monaco-editor .find-widget .matchesCount {
|
||||
|
|
|
@ -43,7 +43,7 @@ const NLS_REPLACE_ALL_BTN_LABEL = nls.localize('label.replaceAllButton', "Replac
|
|||
const NLS_TOGGLE_REPLACE_MODE_BTN_LABEL = nls.localize('label.toggleReplaceButton', "Toggle Replace mode");
|
||||
const NLS_MATCHES_COUNT_LIMIT_TITLE = nls.localize('title.matchesCountLimit', "Only the first 999 results are highlighted, but all find operations work on the entire text.");
|
||||
const NLS_MATCHES_LOCATION = nls.localize('label.matchesLocation', "{0} of {1}");
|
||||
const NLS_NO_RESULTS = nls.localize('label.noResults', "No results");
|
||||
const NLS_NO_RESULTS = nls.localize('label.noResults', "No Results");
|
||||
|
||||
let MAX_MATCHES_COUNT_WIDTH = 69;
|
||||
const WIDGET_FIXED_WIDTH = 411 - 69;
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
.monaco-editor .lightbulb-glyph:hover {
|
||||
|
@ -16,12 +18,18 @@
|
|||
|
||||
.monaco-editor.vs .lightbulb-glyph {
|
||||
background: url('lightbulb.svg') center center no-repeat;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
.monaco-editor.vs-dark .lightbulb-glyph, .monaco-editor.hc-black .lightbulb-glyph {
|
||||
background: url('lightbulb-dark.svg') center center no-repeat;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
.monaco-editor.vs .lightbulb-glyph[data-severity="high"]{
|
||||
background: url('lightbulb.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.monaco-editor.vs-dark .lightbulb-glyph,
|
||||
.monaco-editor.hc-black .lightbulb-glyph {
|
||||
background: url('lightbulb-dark.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.monaco-editor.vs-dark .lightbulb-glyph[data-severity="high"],
|
||||
.monaco-editor.hc-black .lightbulb-glyph[data-severity="high"] {
|
||||
background: url('lightbulb-dark.svg') center center no-repeat;
|
||||
}
|
||||
|
|
|
@ -7,9 +7,10 @@
|
|||
import 'vs/css!./lightBulbWidget';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import Event, { Emitter, any } from 'vs/base/common/event';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { ICodeEditor, IOverlayWidget, IOverlayWidgetPosition } from 'vs/editor/browser/editorBrowser';
|
||||
import { QuickFixComputeEvent } from './quickFixModel';
|
||||
import { QuickFixComputeEvent } from 'vs/editor/contrib/quickFix/common/quickFixModel';
|
||||
|
||||
|
||||
export class LightBulbWidget implements IOverlayWidget, IDisposable {
|
||||
|
@ -86,7 +87,7 @@ export class LightBulbWidget implements IOverlayWidget, IDisposable {
|
|||
const modelNow = this._model;
|
||||
e.fixes.done(fixes => {
|
||||
if (modelNow === this._model && fixes && fixes.length > 0) {
|
||||
this.show(e.range.startLineNumber);
|
||||
this.show(e);
|
||||
} else {
|
||||
this.hide();
|
||||
}
|
||||
|
@ -99,7 +100,8 @@ export class LightBulbWidget implements IOverlayWidget, IDisposable {
|
|||
return this._model;
|
||||
}
|
||||
|
||||
show(line: number): void {
|
||||
show(e: QuickFixComputeEvent): void {
|
||||
const line = e.range.startLineNumber;
|
||||
if (!this._hasSpaceInGlyphMargin(line)) {
|
||||
return;
|
||||
}
|
||||
|
@ -107,6 +109,7 @@ export class LightBulbWidget implements IOverlayWidget, IDisposable {
|
|||
this._line = line;
|
||||
this._visible = true;
|
||||
this._layout();
|
||||
this._domNode.dataset['severity'] = e.severity >= Severity.Warning ? 'high' : '';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,9 +16,9 @@ import { ICommonCodeEditor, EditorContextKeys, ModeContextKeys, IEditorContribut
|
|||
import { editorAction, ServicesAccessor, EditorAction } from 'vs/editor/common/editorCommonExtensions';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions';
|
||||
import { QuickFixContextMenu } from './quickFixWidget';
|
||||
import { LightBulbWidget } from './lightBulbWidget';
|
||||
import { QuickFixModel, QuickFixComputeEvent } from './quickFixModel';
|
||||
import { QuickFixContextMenu } from 'vs/editor/contrib/quickFix/browser/quickFixWidget';
|
||||
import { LightBulbWidget } from 'vs/editor/contrib/quickFix/browser/lightBulbWidget';
|
||||
import { QuickFixModel, QuickFixComputeEvent } from 'vs/editor/contrib/quickFix/common/quickFixModel';
|
||||
|
||||
@editorContribution
|
||||
export class QuickFixController implements IEditorContribution {
|
||||
|
@ -88,7 +88,7 @@ export class QuickFixController implements IEditorContribution {
|
|||
}
|
||||
|
||||
public triggerFromEditorSelection(): void {
|
||||
this._model.triggerManual(this._editor.getSelection());
|
||||
this._model.triggerManual();
|
||||
}
|
||||
|
||||
private _updateLightBulbTitle(): void {
|
||||
|
|
|
@ -6,21 +6,21 @@
|
|||
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IMarker, IMarkerService } from 'vs/platform/markers/common/markers';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { ICommonCodeEditor, IPosition, IRange } from 'vs/editor/common/editorCommon';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { CodeActionProviderRegistry, CodeAction } from 'vs/editor/common/modes';
|
||||
import { getCodeActions } from '../common/quickFix';
|
||||
|
||||
|
||||
class QuickFixOracle {
|
||||
export class QuickFixOracle {
|
||||
|
||||
private _disposables: IDisposable[] = [];
|
||||
private _currentRange: IRange;
|
||||
|
||||
constructor(private _editor: ICommonCodeEditor, private _markerService: IMarkerService, private _signalChange: (e: QuickFixComputeEvent) => any) {
|
||||
|
||||
|
@ -34,29 +34,57 @@ class QuickFixOracle {
|
|||
this._disposables = dispose(this._disposables);
|
||||
}
|
||||
|
||||
private _onMarkerChanges(resources: URI[]): void {
|
||||
const {uri} = this._editor.getModel();
|
||||
let affectedBy = false;
|
||||
for (const resource of resources) {
|
||||
if (resource.toString() === uri.toString()) {
|
||||
affectedBy = true;
|
||||
break;
|
||||
}
|
||||
trigger(): void {
|
||||
let {range, severity} = this._rangeAtPosition();
|
||||
if (!range) {
|
||||
range = this._editor.getSelection();
|
||||
}
|
||||
if (affectedBy) {
|
||||
this._onCursorChange();
|
||||
}
|
||||
}
|
||||
|
||||
private _onCursorChange(): void {
|
||||
const range = this._markerAtPosition() || this._wordAtPosition();
|
||||
|
||||
this._signalChange({
|
||||
type: 'auto',
|
||||
type: 'manual',
|
||||
severity,
|
||||
range,
|
||||
position: this._editor.getPosition(),
|
||||
fixes: range && getCodeActions(this._editor.getModel(), this._editor.getModel().validateRange(range))
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private _onMarkerChanges(resources: URI[]): void {
|
||||
const {uri} = this._editor.getModel();
|
||||
for (const resource of resources) {
|
||||
if (resource.toString() === uri.toString()) {
|
||||
this._onCursorChange();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _onCursorChange(): void {
|
||||
const {range, severity} = this._rangeAtPosition();
|
||||
if (!Range.equalsRange(this._currentRange, range)) {
|
||||
this._currentRange = range;
|
||||
this._signalChange({
|
||||
type: 'auto',
|
||||
severity,
|
||||
range,
|
||||
position: this._editor.getPosition(),
|
||||
fixes: range && getCodeActions(this._editor.getModel(), this._editor.getModel().validateRange(range))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private _rangeAtPosition(): { range: IRange, severity: Severity; } {
|
||||
let range: IRange;
|
||||
let severity: Severity;
|
||||
const marker = this._markerAtPosition();
|
||||
if (marker) {
|
||||
range = Range.lift(marker);
|
||||
severity = marker.severity;
|
||||
} else {
|
||||
range = this._wordAtPosition();
|
||||
severity = Severity.Info;
|
||||
}
|
||||
return { range, severity };
|
||||
}
|
||||
|
||||
private _markerAtPosition(): IMarker {
|
||||
|
@ -76,26 +104,23 @@ class QuickFixOracle {
|
|||
}
|
||||
|
||||
private _wordAtPosition(): IRange {
|
||||
return;
|
||||
// todo@joh - enable once we decide to eagerly show the
|
||||
// light bulb as the cursor moves
|
||||
// const {positionLineNumber, positionColumn} = this._editor.getSelection();
|
||||
// const model = this._editor.getModel();
|
||||
|
||||
// const info = model.getWordAtPosition({ lineNumber: positionLineNumber, column: positionColumn });
|
||||
// if (info) {
|
||||
// return {
|
||||
// startLineNumber: positionLineNumber,
|
||||
// startColumn: info.startColumn,
|
||||
// endLineNumber: positionLineNumber,
|
||||
// endColumn: info.endColumn
|
||||
// };
|
||||
// }
|
||||
const {positionLineNumber, positionColumn} = this._editor.getSelection();
|
||||
const model = this._editor.getModel();
|
||||
const info = model.getWordAtPosition({ lineNumber: positionLineNumber, column: positionColumn });
|
||||
if (info) {
|
||||
return {
|
||||
startLineNumber: positionLineNumber,
|
||||
startColumn: info.startColumn,
|
||||
endLineNumber: positionLineNumber,
|
||||
endColumn: info.endColumn
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface QuickFixComputeEvent {
|
||||
type: 'auto' | 'manual';
|
||||
severity: Severity;
|
||||
range: IRange;
|
||||
position: IPosition;
|
||||
fixes: TPromise<CodeAction[]>;
|
||||
|
@ -109,7 +134,7 @@ export class QuickFixModel {
|
|||
private _onDidChangeFixes = new Emitter<QuickFixComputeEvent>();
|
||||
private _disposables: IDisposable[] = [];
|
||||
|
||||
constructor(editor: ICodeEditor, markerService: IMarkerService) {
|
||||
constructor(editor: ICommonCodeEditor, markerService: IMarkerService) {
|
||||
this._editor = editor;
|
||||
this._markerService = markerService;
|
||||
|
||||
|
@ -132,7 +157,8 @@ export class QuickFixModel {
|
|||
private _update(): void {
|
||||
|
||||
if (this._quickFixOracle) {
|
||||
dispose(this._quickFixOracle);
|
||||
this._quickFixOracle.dispose();
|
||||
this._quickFixOracle = undefined;
|
||||
this._onDidChangeFixes.fire(undefined);
|
||||
}
|
||||
|
||||
|
@ -144,16 +170,9 @@ export class QuickFixModel {
|
|||
}
|
||||
}
|
||||
|
||||
triggerManual(selection: Selection): void {
|
||||
const model = this._editor.getModel();
|
||||
if (model) {
|
||||
const fixes = getCodeActions(model, selection);
|
||||
this._onDidChangeFixes.fire({
|
||||
type: 'manual',
|
||||
range: selection,
|
||||
position: { lineNumber: selection.positionLineNumber, column: selection.positionColumn },
|
||||
fixes
|
||||
});
|
||||
triggerManual(): void {
|
||||
if (this._quickFixOracle) {
|
||||
this._quickFixOracle.trigger();
|
||||
}
|
||||
}
|
||||
}
|
130
src/vs/editor/contrib/quickFix/test/common/quickFixModel.test.ts
Normal file
130
src/vs/editor/contrib/quickFix/test/common/quickFixModel.test.ts
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { ICommonCodeEditor } from 'vs/editor/common/editorCommon';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { Model } from 'vs/editor/common/model/model';
|
||||
import { mockCodeEditor } from 'vs/editor/test/common/mocks/mockCodeEditor';
|
||||
import { MarkerService } from 'vs/platform/markers/common/markerService';
|
||||
import { QuickFixOracle } from 'vs/editor/contrib/quickFix/common/quickFixModel';
|
||||
import { CodeActionProviderRegistry, LanguageIdentifier } from 'vs/editor/common/modes';
|
||||
|
||||
|
||||
suite('QuickFix', () => {
|
||||
const languageIdentifier = new LanguageIdentifier('foo-lang', 3);
|
||||
|
||||
let uri = URI.parse('fake:path');
|
||||
let model = Model.createFromString('foobar foo bar\nfarboo far boo', undefined, languageIdentifier, uri);
|
||||
let markerService: MarkerService;
|
||||
let editor: ICommonCodeEditor;
|
||||
|
||||
let reg = CodeActionProviderRegistry.register(languageIdentifier.sid, {
|
||||
provideCodeActions() {
|
||||
return [{ command: { id: 'test-command', title: 'test', arguments: [] }, score: 1 }];
|
||||
}
|
||||
});
|
||||
|
||||
setup(() => {
|
||||
markerService = new MarkerService();
|
||||
editor = mockCodeEditor([], { model });
|
||||
editor.setPosition({ lineNumber: 1, column: 1 });
|
||||
});
|
||||
|
||||
suiteTeardown(() => {
|
||||
reg.dispose();
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
test('Orcale -> marker added', done => {
|
||||
|
||||
const oracle = new QuickFixOracle(editor, markerService, e => {
|
||||
assert.equal(e.type, 'auto');
|
||||
assert.ok(e.fixes);
|
||||
|
||||
e.fixes.then(fixes => {
|
||||
oracle.dispose();
|
||||
assert.equal(fixes.length, 1);
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
// start here
|
||||
markerService.changeOne('fake', uri, [{
|
||||
startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 6,
|
||||
message: 'error',
|
||||
severity: 1,
|
||||
code: '',
|
||||
source: ''
|
||||
}]);
|
||||
|
||||
});
|
||||
|
||||
test('Orcale -> position changed', done => {
|
||||
|
||||
markerService.changeOne('fake', uri, [{
|
||||
startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 6,
|
||||
message: 'error',
|
||||
severity: 1,
|
||||
code: '',
|
||||
source: ''
|
||||
}]);
|
||||
|
||||
editor.setPosition({ lineNumber: 2, column: 1 });
|
||||
|
||||
const oracle = new QuickFixOracle(editor, markerService, e => {
|
||||
assert.equal(e.type, 'auto');
|
||||
assert.ok(e.fixes);
|
||||
|
||||
e.fixes.then(fixes => {
|
||||
oracle.dispose();
|
||||
assert.equal(fixes.length, 1);
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
// start here
|
||||
editor.setPosition({ lineNumber: 1, column: 1 });
|
||||
|
||||
});
|
||||
|
||||
test('Oracle -> ask once per marker/word', () => {
|
||||
let counter = 0;
|
||||
let reg = CodeActionProviderRegistry.register(languageIdentifier.sid, {
|
||||
provideCodeActions() {
|
||||
counter += 1;
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
markerService.changeOne('fake', uri, [{
|
||||
startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 6,
|
||||
message: 'error',
|
||||
severity: 1,
|
||||
code: '',
|
||||
source: ''
|
||||
}]);
|
||||
|
||||
let fixes: TPromise<any>[] = [];
|
||||
let oracle = new QuickFixOracle(editor, markerService, e => {
|
||||
fixes.push(e.fixes);
|
||||
});
|
||||
|
||||
editor.setPosition({ lineNumber: 1, column: 3 }); // marker
|
||||
editor.setPosition({ lineNumber: 1, column: 6 }); // (same) marker
|
||||
editor.setPosition({ lineNumber: 1, column: 8 }); // whitespace
|
||||
editor.setPosition({ lineNumber: 2, column: 2 }); // word
|
||||
editor.setPosition({ lineNumber: 2, column: 6 }); // (same) word
|
||||
|
||||
return TPromise.join(fixes).then(_ => {
|
||||
reg.dispose();
|
||||
oracle.dispose();
|
||||
assert.equal(counter, 2);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
|
@ -50,8 +50,8 @@ class DecorationsManager implements IDisposable {
|
|||
private _callOnDispose: IDisposable[] = [];
|
||||
private _callOnModelChange: IDisposable[] = [];
|
||||
|
||||
constructor(private editor: ICodeEditor, private model: ReferencesModel) {
|
||||
this._callOnDispose.push(this.editor.onDidChangeModel(() => this._onModelChanged()));
|
||||
constructor(private _editor: ICodeEditor, private _model: ReferencesModel) {
|
||||
this._callOnDispose.push(this._editor.onDidChangeModel(() => this._onModelChanged()));
|
||||
this._onModelChanged();
|
||||
}
|
||||
|
||||
|
@ -62,30 +62,25 @@ class DecorationsManager implements IDisposable {
|
|||
}
|
||||
|
||||
private _onModelChanged(): void {
|
||||
|
||||
this.removeDecorations();
|
||||
this._callOnModelChange = dispose(this._callOnModelChange);
|
||||
|
||||
var model = this.editor.getModel();
|
||||
if (!model) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0, len = this.model.groups.length; i < len; i++) {
|
||||
if (this.model.groups[i].uri.toString() === model.uri.toString()) {
|
||||
this._addDecorations(this.model.groups[i]);
|
||||
return;
|
||||
const model = this._editor.getModel();
|
||||
if (model) {
|
||||
for (const ref of this._model.groups) {
|
||||
if (ref.uri.toString() === model.uri.toString()) {
|
||||
this._addDecorations(ref);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _addDecorations(reference: FileReferences): void {
|
||||
this._callOnModelChange.push(this.editor.getModel().onDidChangeDecorations((event) => this._onDecorationChanged(event)));
|
||||
this._callOnModelChange.push(this._editor.getModel().onDidChangeDecorations((event) => this._onDecorationChanged(event)));
|
||||
|
||||
this.editor.changeDecorations(accessor => {
|
||||
this._editor.changeDecorations(accessor => {
|
||||
|
||||
var newDecorations: editorCommon.IModelDeltaDecoration[] = [];
|
||||
var newDecorationsActualIndex: number[] = [];
|
||||
const newDecorations: editorCommon.IModelDeltaDecoration[] = [];
|
||||
const newDecorationsActualIndex: number[] = [];
|
||||
|
||||
for (let i = 0, len = reference.children.length; i < len; i++) {
|
||||
let oneReference = reference.children[i];
|
||||
|
@ -99,26 +94,25 @@ class DecorationsManager implements IDisposable {
|
|||
newDecorationsActualIndex.push(i);
|
||||
}
|
||||
|
||||
var decorations = accessor.deltaDecorations([], newDecorations);
|
||||
|
||||
for (var i = 0; i < decorations.length; i++) {
|
||||
const decorations = accessor.deltaDecorations([], newDecorations);
|
||||
for (let i = 0; i < decorations.length; i++) {
|
||||
this._decorations.set(decorations[i], reference.children[newDecorationsActualIndex[i]]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _onDecorationChanged(event: editorCommon.IModelDecorationsChangedEvent): void {
|
||||
var changedDecorations = event.changedDecorations,
|
||||
const changedDecorations = event.changedDecorations,
|
||||
toRemove: string[] = [];
|
||||
|
||||
for (var i = 0, len = changedDecorations.length; i < len; i++) {
|
||||
for (let i = 0, len = changedDecorations.length; i < len; i++) {
|
||||
let reference = this._decorations.get(changedDecorations[i]);
|
||||
if (!reference) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var newRange = this.editor.getModel().getDecorationRange(changedDecorations[i]),
|
||||
ignore = false;
|
||||
const newRange = this._editor.getModel().getDecorationRange(changedDecorations[i]);
|
||||
let ignore = false;
|
||||
|
||||
if (Range.equalsRange(newRange, reference.range)) {
|
||||
continue;
|
||||
|
@ -127,8 +121,8 @@ class DecorationsManager implements IDisposable {
|
|||
ignore = true;
|
||||
|
||||
} else {
|
||||
var lineLength = reference.range.endColumn - reference.range.startColumn,
|
||||
newLineLength = newRange.endColumn - newRange.startColumn;
|
||||
const lineLength = reference.range.endColumn - reference.range.startColumn;
|
||||
const newLineLength = newRange.endColumn - newRange.startColumn;
|
||||
|
||||
if (lineLength !== newLineLength) {
|
||||
ignore = true;
|
||||
|
@ -143,7 +137,7 @@ class DecorationsManager implements IDisposable {
|
|||
}
|
||||
}
|
||||
|
||||
this.editor.changeDecorations((accessor) => {
|
||||
this._editor.changeDecorations((accessor) => {
|
||||
for (let i = 0, len = toRemove.length; i < len; i++) {
|
||||
delete this._decorations[toRemove[i]];
|
||||
}
|
||||
|
@ -152,7 +146,7 @@ class DecorationsManager implements IDisposable {
|
|||
}
|
||||
|
||||
public removeDecorations(): void {
|
||||
this.editor.changeDecorations(accessor => {
|
||||
this._editor.changeDecorations(accessor => {
|
||||
this._decorations.forEach((value, key) => {
|
||||
accessor.removeDecoration(key);
|
||||
});
|
||||
|
|
|
@ -22,6 +22,7 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
|||
import { rename } from '../common/rename';
|
||||
import RenameInputField from './renameInputField';
|
||||
import { ITextModelResolverService } from 'vs/editor/common/services/resolverService';
|
||||
import { optional } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
// --- register actions and commands
|
||||
|
||||
|
@ -42,10 +43,10 @@ class RenameController implements IEditorContribution {
|
|||
constructor(
|
||||
private editor: ICodeEditor,
|
||||
@IMessageService private _messageService: IMessageService,
|
||||
@IFileService private _fileService: IFileService,
|
||||
@ITextModelResolverService private _textModelResolverService: ITextModelResolverService,
|
||||
@IProgressService private _progressService: IProgressService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@optional(IFileService) private _fileService: IFileService
|
||||
) {
|
||||
this._renameInputField = new RenameInputField(editor);
|
||||
this._renameInputVisible = CONTEXT_RENAME_INPUT_VISIBLE.bindTo(contextKeyService);
|
||||
|
@ -132,7 +133,7 @@ class RenameController implements IEditorContribution {
|
|||
|
||||
// start recording of file changes so that we can figure out if a file that
|
||||
// is to be renamed conflicts with another (concurrent) modification
|
||||
let edit = createBulkEdit(this._fileService, this._textModelResolverService, <ICodeEditor>this.editor);
|
||||
let edit = createBulkEdit(this._textModelResolverService, <ICodeEditor>this.editor, this._fileService);
|
||||
|
||||
return rename(this.editor.getModel(), this.editor.getPosition(), newName).then(result => {
|
||||
if (result.rejectReason) {
|
||||
|
|
|
@ -122,15 +122,15 @@ export class CodeSnippet implements ICodeSnippet {
|
|||
|
||||
for (let {startLineNumber, startColumn, endLineNumber, endColumn} of originalPlaceHolder.occurences) {
|
||||
|
||||
if (startColumn > 1) {
|
||||
// placeholders that aren't at the beginning of the snippet line
|
||||
if (startColumn > 1 || startLineNumber === 1) {
|
||||
// placeholders that aren't at the beginning of new snippet lines
|
||||
// will be moved by how many characters the indentation has been
|
||||
// adjusted
|
||||
startColumn = startColumn + deltaColumns[startLineNumber];
|
||||
endColumn = endColumn + deltaColumns[endLineNumber];
|
||||
|
||||
} else {
|
||||
// placeholders at the beginning of the snippet line
|
||||
// placeholders at the beginning of new snippet lines
|
||||
// will be indented by the reference indentation
|
||||
startColumn += referenceIndentation.length;
|
||||
endColumn += referenceIndentation.length;
|
||||
|
@ -140,7 +140,7 @@ export class CodeSnippet implements ICodeSnippet {
|
|||
startLineNumber: startLineNumber + deltaLine,
|
||||
startColumn,
|
||||
endLineNumber: endLineNumber + deltaLine,
|
||||
endColumn
|
||||
endColumn,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -225,7 +225,7 @@ suite('Editor Contrib - Snippets', () => {
|
|||
});
|
||||
|
||||
|
||||
test('issue #11890: Bad cursor position', () => {
|
||||
test('issue #11890: Bad cursor position 1/2', () => {
|
||||
|
||||
let snippet = CodeSnippet.fromTextmate([
|
||||
'afterEach((done) => {',
|
||||
|
@ -242,6 +242,7 @@ suite('Editor Contrib - Snippets', () => {
|
|||
assert.equal(boundSnippet.lines[1], ' test');
|
||||
assert.equal(boundSnippet.placeHolders.length, 3);
|
||||
assert.equal(boundSnippet.finishPlaceHolderIndex, 2);
|
||||
|
||||
let [first, second] = boundSnippet.placeHolders;
|
||||
assert.equal(first.occurences.length, 1);
|
||||
assert.equal(first.occurences[0].startColumn, 1);
|
||||
|
@ -249,6 +250,49 @@ suite('Editor Contrib - Snippets', () => {
|
|||
assert.equal(second.occurences[0].startColumn, 7);
|
||||
});
|
||||
|
||||
test('issue #11890: Bad cursor position 2/2', () => {
|
||||
|
||||
let snippet = CodeSnippet.fromTextmate('${1}\ttest');
|
||||
|
||||
let boundSnippet = snippet.bind('abc abc abc prefix3', 0, 12, {
|
||||
normalizeIndentation(str: string): string {
|
||||
return str.replace(/\t/g, ' ');
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(boundSnippet.lines[0], '\ttest');
|
||||
assert.equal(boundSnippet.placeHolders.length, 2);
|
||||
assert.equal(boundSnippet.finishPlaceHolderIndex, 1);
|
||||
|
||||
let [first, second] = boundSnippet.placeHolders;
|
||||
assert.equal(first.occurences.length, 1);
|
||||
assert.equal(first.occurences[0].startColumn, 13);
|
||||
assert.equal(second.occurences.length, 1);
|
||||
assert.equal(second.occurences[0].startColumn, 18);
|
||||
});
|
||||
|
||||
test('issue #17989: Bad selection', () => {
|
||||
|
||||
let snippet = CodeSnippet.fromTextmate('${1:HoldMeTight}');
|
||||
|
||||
let boundSnippet = snippet.bind('abc abc abc prefix3', 0, 12, {
|
||||
normalizeIndentation(str: string): string {
|
||||
return str.replace(/\t/g, ' ');
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(boundSnippet.lines[0], 'HoldMeTight');
|
||||
assert.equal(boundSnippet.placeHolders.length, 2);
|
||||
assert.equal(boundSnippet.finishPlaceHolderIndex, 1);
|
||||
let [first, second] = boundSnippet.placeHolders;
|
||||
assert.equal(first.occurences.length, 1);
|
||||
assert.equal(first.occurences[0].startColumn, 13);
|
||||
|
||||
assert.equal(second.occurences.length, 1);
|
||||
assert.equal(second.occurences[0].startColumn, 24);
|
||||
|
||||
});
|
||||
|
||||
test('variables, simple', () => {
|
||||
|
||||
const resolver: ISnippetVariableResolver = {
|
||||
|
|
|
@ -19,23 +19,32 @@ interface ISnippetPick extends IPickOpenEntry {
|
|||
snippet: ISnippet;
|
||||
}
|
||||
|
||||
class NameAndLangId {
|
||||
class Args {
|
||||
|
||||
static fromArg(arg: any): NameAndLangId {
|
||||
static fromUser(arg: any): Args {
|
||||
if (typeof arg !== 'object') {
|
||||
return new NameAndLangId(undefined, undefined);
|
||||
return Args._empty;
|
||||
}
|
||||
let {snippet, name, langId} = arg;
|
||||
if (typeof snippet !== 'string') {
|
||||
snippet = undefined;
|
||||
}
|
||||
let {name, langId} = arg;
|
||||
if (typeof name !== 'string') {
|
||||
name = undefined;
|
||||
}
|
||||
if (typeof langId !== 'string') {
|
||||
langId = undefined;
|
||||
}
|
||||
return new NameAndLangId(name, langId);
|
||||
return new Args(snippet, name, langId);
|
||||
}
|
||||
|
||||
private constructor(public readonly name: string, public readonly langId: string) {
|
||||
private static _empty = new Args(undefined, undefined, undefined);
|
||||
|
||||
private constructor(
|
||||
public readonly snippet: string,
|
||||
public readonly name: string,
|
||||
public readonly langId: string
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -62,16 +71,28 @@ class InsertSnippetAction extends EditorAction {
|
|||
|
||||
const quickOpenService = accessor.get(IQuickOpenService);
|
||||
const {lineNumber, column} = editor.getPosition();
|
||||
let {name, langId} = NameAndLangId.fromArg(arg);
|
||||
let {snippet, name, langId} = Args.fromUser(arg);
|
||||
|
||||
let languageId: LanguageId;
|
||||
if (langId) {
|
||||
languageId = modeService.getLanguageIdentifier(langId).iid;
|
||||
} else {
|
||||
languageId = editor.getModel().getLanguageIdAtPosition(lineNumber, column);
|
||||
}
|
||||
|
||||
return new TPromise<ISnippet>((resolve, reject) => {
|
||||
|
||||
if (snippet) {
|
||||
return resolve({
|
||||
codeSnippet: snippet,
|
||||
description: undefined,
|
||||
name: undefined,
|
||||
owner: undefined,
|
||||
prefix: undefined
|
||||
});
|
||||
}
|
||||
|
||||
let languageId: LanguageId;
|
||||
if (langId) {
|
||||
languageId = modeService.getLanguageIdentifier(langId).iid;
|
||||
} else {
|
||||
languageId = editor.getModel().getLanguageIdAtPosition(lineNumber, column);
|
||||
}
|
||||
|
||||
if (name) {
|
||||
// take selected snippet
|
||||
Registry.as<ISnippetsRegistry>(Extensions.Snippets).visitSnippets(languageId, snippet => {
|
||||
|
|
|
@ -9,9 +9,8 @@ import { isFalsyOrEmpty } from 'vs/base/common/arrays';
|
|||
import { forEach } from 'vs/base/common/collections';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { startsWith } from 'vs/base/common/strings';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { ICommonCodeEditor, ICursorSelectionChangedEvent, CursorChangeReason, IModel, IPosition } from 'vs/editor/common/editorCommon';
|
||||
import { ICommonCodeEditor, ICursorSelectionChangedEvent, CursorChangeReason, IModel, IPosition, IWordAtPosition } from 'vs/editor/common/editorCommon';
|
||||
import { ISuggestSupport, SuggestRegistry } from 'vs/editor/common/modes';
|
||||
import { provideSuggestionItems, getSuggestionComparator, ISuggestionItem } from './suggest';
|
||||
import { CompletionModel } from './completionModel';
|
||||
|
@ -30,104 +29,51 @@ export interface ISuggestEvent {
|
|||
auto: boolean;
|
||||
}
|
||||
|
||||
export class Context {
|
||||
export class LineContext {
|
||||
|
||||
static shouldAutoTrigger(editor: ICommonCodeEditor): boolean {
|
||||
const model = editor.getModel();
|
||||
if (!model) {
|
||||
return false;
|
||||
}
|
||||
const pos = editor.getPosition();
|
||||
const word = model.getWordAtPosition(pos);
|
||||
if (!word) {
|
||||
return false;
|
||||
}
|
||||
if (word.endColumn !== pos.column) {
|
||||
return false;
|
||||
}
|
||||
if (!isNaN(Number(word.word))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static isInEditableRange(editor: ICommonCodeEditor): boolean {
|
||||
const model = editor.getModel();
|
||||
const position = editor.getPosition();
|
||||
if (model.hasEditableRange()) {
|
||||
const editableRange = model.getEditableRange();
|
||||
if (!editableRange.containsPosition(position)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
readonly lineNumber: number;
|
||||
readonly column: number;
|
||||
readonly isInEditableRange: boolean;
|
||||
|
||||
readonly lineContentBefore: string;
|
||||
|
||||
readonly wordBefore: string;
|
||||
readonly wordAfter: string;
|
||||
|
||||
constructor(model: IModel, position: IPosition, private auto: boolean) {
|
||||
const lineContent = model.getLineContent(position.lineNumber);
|
||||
const wordUnderCursor = model.getWordAtPosition(position);
|
||||
|
||||
if (wordUnderCursor) {
|
||||
this.wordBefore = lineContent.substring(wordUnderCursor.startColumn - 1, position.column - 1);
|
||||
this.wordAfter = lineContent.substring(position.column - 1, wordUnderCursor.endColumn - 1);
|
||||
} else {
|
||||
this.wordBefore = '';
|
||||
this.wordAfter = '';
|
||||
}
|
||||
readonly leadingLineContent: string;
|
||||
readonly leadingWord: IWordAtPosition;
|
||||
readonly auto;
|
||||
|
||||
constructor(model: IModel, position: IPosition, auto: boolean) {
|
||||
this.leadingLineContent = model.getLineContent(position.lineNumber).substr(0, position.column - 1);
|
||||
this.leadingWord = model.getWordUntilPosition(position);
|
||||
this.lineNumber = position.lineNumber;
|
||||
this.column = position.column;
|
||||
this.lineContentBefore = lineContent.substr(0, position.column - 1);
|
||||
|
||||
this.isInEditableRange = true;
|
||||
if (model.hasEditableRange()) {
|
||||
const editableRange = model.getEditableRange();
|
||||
|
||||
if (!editableRange.containsPosition(position)) {
|
||||
this.isInEditableRange = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shouldAutoTrigger(): boolean {
|
||||
|
||||
if (this.wordBefore.length === 0) {
|
||||
// Word before position is empty
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isNaN(Number(this.wordBefore))) {
|
||||
// Word before is number only
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.wordAfter.length > 0) {
|
||||
// Word after position is non empty
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
isDifferentContext(context: Context): boolean {
|
||||
if (this.lineNumber !== context.lineNumber) {
|
||||
// Line number has changed
|
||||
return true;
|
||||
}
|
||||
|
||||
if (context.column < this.column - this.wordBefore.length) {
|
||||
// column went before word start
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!startsWith(context.lineContentBefore, this.lineContentBefore)) {
|
||||
// Line has changed before position
|
||||
return true;
|
||||
}
|
||||
|
||||
if (context.wordBefore === '' && context.lineContentBefore !== this.lineContentBefore) {
|
||||
// Most likely a space has been typed
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
shouldRetrigger(context: Context): boolean {
|
||||
if (!startsWith(this.lineContentBefore, context.lineContentBefore)) {
|
||||
// Doesn't look like the same line
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.lineContentBefore.length > context.lineContentBefore.length && this.wordBefore.length === 0) {
|
||||
// Text was deleted and previous current word was empty
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.auto && context.wordBefore.length === 0) {
|
||||
// Currently in auto mode and new current word is empty
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
this.auto = auto;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,7 +93,7 @@ export class SuggestModel implements IDisposable {
|
|||
private state: State;
|
||||
|
||||
private requestPromise: TPromise<void>;
|
||||
private context: Context;
|
||||
private context: LineContext;
|
||||
|
||||
private completionModel: CompletionModel;
|
||||
|
||||
|
@ -274,12 +220,11 @@ export class SuggestModel implements IDisposable {
|
|||
}
|
||||
|
||||
private onCursorChange(e: ICursorSelectionChangedEvent): void {
|
||||
if (!e.selection.isEmpty()) {
|
||||
this.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.source !== 'keyboard' || e.reason !== CursorChangeReason.NotSet) {
|
||||
if (!e.selection.isEmpty()
|
||||
|| e.source !== 'keyboard'
|
||||
|| e.reason !== CursorChangeReason.NotSet) {
|
||||
|
||||
this.cancel();
|
||||
return;
|
||||
}
|
||||
|
@ -288,32 +233,28 @@ export class SuggestModel implements IDisposable {
|
|||
return;
|
||||
}
|
||||
|
||||
const isInactive = this.state === State.Idle;
|
||||
|
||||
if (isInactive && !this.editor.getConfiguration().contribInfo.quickSuggestions) {
|
||||
return;
|
||||
}
|
||||
|
||||
const model = this.editor.getModel();
|
||||
|
||||
if (!model) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ctx = new Context(model, this.editor.getPosition(), false);
|
||||
if (this.state === State.Idle) {
|
||||
|
||||
if (isInactive) {
|
||||
// trigger was not called or it was canceled
|
||||
this.cancel();
|
||||
|
||||
if (ctx.shouldAutoTrigger()) {
|
||||
this.triggerAutoSuggestPromise = TPromise.timeout(this.quickSuggestDelay);
|
||||
this.triggerAutoSuggestPromise.then(() => {
|
||||
this.triggerAutoSuggestPromise = null;
|
||||
this.trigger(true);
|
||||
});
|
||||
if (this.editor.getConfiguration().contribInfo.quickSuggestions) {
|
||||
// trigger 24x7 IntelliSense when idle and enabled
|
||||
this.cancel();
|
||||
if (LineContext.shouldAutoTrigger(this.editor)) {
|
||||
this.triggerAutoSuggestPromise = TPromise.timeout(this.quickSuggestDelay);
|
||||
this.triggerAutoSuggestPromise.then(() => {
|
||||
this.triggerAutoSuggestPromise = null;
|
||||
this.trigger(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// refine active suggestion
|
||||
const ctx = new LineContext(model, this.editor.getPosition(), this.state === State.Auto);
|
||||
this.onNewContext(ctx);
|
||||
}
|
||||
}
|
||||
|
@ -326,9 +267,9 @@ export class SuggestModel implements IDisposable {
|
|||
return;
|
||||
}
|
||||
|
||||
const ctx = new Context(model, this.editor.getPosition(), auto);
|
||||
const ctx = new LineContext(model, this.editor.getPosition(), auto);
|
||||
|
||||
if (!ctx.isInEditableRange) {
|
||||
if (!LineContext.isInEditableRange(this.editor)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -359,9 +300,9 @@ export class SuggestModel implements IDisposable {
|
|||
items = items.concat(existingItems).sort(cmpFn);
|
||||
}
|
||||
|
||||
const ctx = new Context(model, this.editor.getPosition(), auto);
|
||||
const ctx = new LineContext(model, this.editor.getPosition(), auto);
|
||||
this.completionModel = new CompletionModel(items, this.context.column, {
|
||||
leadingLineContent: ctx.lineContentBefore,
|
||||
leadingLineContent: ctx.leadingLineContent,
|
||||
characterCountDelta: this.context ? ctx.column - this.context.column : 0
|
||||
});
|
||||
this.onNewContext(ctx);
|
||||
|
@ -369,42 +310,66 @@ export class SuggestModel implements IDisposable {
|
|||
}).then(null, onUnexpectedError);
|
||||
}
|
||||
|
||||
private onNewContext(ctx: Context): void {
|
||||
if (this.context && this.context.isDifferentContext(ctx)) {
|
||||
if (this.context.shouldRetrigger(ctx)) {
|
||||
this.trigger(this.state === State.Auto, true);
|
||||
} else {
|
||||
this.cancel();
|
||||
private onNewContext(ctx: LineContext): void {
|
||||
|
||||
if (!this.context) {
|
||||
// happens when 24x7 IntelliSense is enabled and still in its delay
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx.lineNumber !== this.context.lineNumber) {
|
||||
// e.g. happens when pressing Enter while IntelliSense is computed
|
||||
this.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx.column < this.context.column) {
|
||||
// typed -> moved cursor LEFT -> retrigger if still on a word
|
||||
if (ctx.leadingWord.word) {
|
||||
this.trigger(this.context.auto, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
} else if (this.completionModel) {
|
||||
if (!this.completionModel) {
|
||||
// happens when IntelliSense is not yet computed
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.completionModel.incomplete && ctx.column > this.context.column) {
|
||||
const {complete, incomplete} = this.completionModel.resolveIncompleteInfo();
|
||||
this.trigger(this.state === State.Auto, true, incomplete, complete);
|
||||
return;
|
||||
}
|
||||
if (ctx.column > this.context.column && this.completionModel.incomplete) {
|
||||
// typed -> moved cursor RIGHT & incomple model -> retrigger
|
||||
const {complete, incomplete} = this.completionModel.resolveIncompleteInfo();
|
||||
this.trigger(this.state === State.Auto, true, incomplete, complete);
|
||||
|
||||
const auto = this.state === State.Auto;
|
||||
const oldLineContext = this.completionModel.lineContext;
|
||||
} else {
|
||||
// typed -> moved cursor RIGHT -> update UI
|
||||
let oldLineContext = this.completionModel.lineContext;
|
||||
let isFrozen = false;
|
||||
|
||||
this.completionModel.lineContext = {
|
||||
leadingLineContent: ctx.lineContentBefore,
|
||||
characterCountDelta: this.context ? ctx.column - this.context.column : 0
|
||||
leadingLineContent: ctx.leadingLineContent,
|
||||
characterCountDelta: ctx.column - this.context.column
|
||||
};
|
||||
|
||||
// when explicitly request when the next context goes
|
||||
// from 'results' to 'no results' freeze
|
||||
if (!auto && this.completionModel.items.length === 0) {
|
||||
this.completionModel.lineContext = oldLineContext;
|
||||
isFrozen = this.completionModel.items.length > 0;
|
||||
if (this.completionModel.items.length === 0) {
|
||||
|
||||
if (LineContext.shouldAutoTrigger(this.editor) && this.context.leadingWord.endColumn < ctx.leadingWord.startColumn) {
|
||||
// retrigger when heading into a new word
|
||||
this.trigger(this.context.auto, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.context.auto) {
|
||||
// freeze when IntelliSense was manually requested
|
||||
this.completionModel.lineContext = oldLineContext;
|
||||
isFrozen = this.completionModel.items.length > 0;
|
||||
}
|
||||
}
|
||||
|
||||
this._onDidSuggest.fire({
|
||||
completionModel: this.completionModel,
|
||||
auto: this.context.auto,
|
||||
isFrozen,
|
||||
auto
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
|
|||
import { Model } from 'vs/editor/common/model/model';
|
||||
import { ICommonCodeEditor, Handler } from 'vs/editor/common/editorCommon';
|
||||
import { ISuggestSupport, ISuggestResult, SuggestRegistry } from 'vs/editor/common/modes';
|
||||
import { SuggestModel, Context } from 'vs/editor/contrib/suggest/common/suggestModel';
|
||||
import { SuggestModel, LineContext } from 'vs/editor/contrib/suggest/common/suggestModel';
|
||||
import { MockCodeEditor, MockScopeLocation } from 'vs/editor/test/common/mocks/mockCodeEditor';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
|
||||
|
@ -49,8 +49,10 @@ suite('SuggestModel - Context', function () {
|
|||
|
||||
function assertAutoTrigger(offset: number, expected: boolean): void {
|
||||
const pos = model.getPositionAt(offset);
|
||||
const ctx = new Context(model, pos, false);
|
||||
assert.equal(ctx.shouldAutoTrigger(), expected);
|
||||
const editor = createMockEditor(model);
|
||||
editor.setPosition(pos);
|
||||
assert.equal(LineContext.shouldAutoTrigger(editor), expected);
|
||||
editor.dispose();
|
||||
}
|
||||
|
||||
assertAutoTrigger(3, true); // end of word, Das|
|
||||
|
@ -59,28 +61,6 @@ suite('SuggestModel - Context', function () {
|
|||
assertAutoTrigger(55, false); // number, 1861|
|
||||
});
|
||||
|
||||
test('Context - isDifferentContext', function () {
|
||||
|
||||
// different line
|
||||
const ctx = new Context(model, { lineNumber: 1, column: 8 }, true); // Das Pfer|d
|
||||
assert.equal(ctx.isDifferentContext(new Context(model, { lineNumber: 2, column: 1 }, true)), true);
|
||||
|
||||
|
||||
function createEndContext(value: string) {
|
||||
const model = Model.createFromString(value);
|
||||
const ctx = new Context(model, model.getPositionAt(value.length), true); // Das Pfer|d
|
||||
return ctx;
|
||||
}
|
||||
|
||||
// got shorter -> redo
|
||||
assert.equal(createEndContext('One Two').isDifferentContext(createEndContext('One Tw')), true);
|
||||
|
||||
// got longer inside word -> keep
|
||||
assert.equal(createEndContext('One Tw').isDifferentContext(createEndContext('One Two')), false);
|
||||
|
||||
// got longer new word -> redo
|
||||
assert.equal(createEndContext('One Two').isDifferentContext(createEndContext('One Two ')), true);
|
||||
});
|
||||
});
|
||||
|
||||
suite('SuggestModel - TriggerAndCancelOracle', function () {
|
||||
|
@ -239,4 +219,49 @@ suite('SuggestModel - TriggerAndCancelOracle', function () {
|
|||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('#17400: Keep filtering suggestModel.ts after space', function () {
|
||||
|
||||
disposables.push(SuggestRegistry.register({ scheme: 'test' }, {
|
||||
triggerCharacters: [],
|
||||
provideCompletionItems(doc, pos) {
|
||||
return <ISuggestResult>{
|
||||
currentWord: '',
|
||||
incomplete: false,
|
||||
suggestions: [{
|
||||
label: 'My Table',
|
||||
type: 'property',
|
||||
insertText: 'My Table'
|
||||
}]
|
||||
};
|
||||
}
|
||||
}));
|
||||
|
||||
model.setValue('');
|
||||
|
||||
return withOracle((model, editor) => {
|
||||
|
||||
return assertEvent(model.onDidSuggest, () => {
|
||||
editor.setPosition({ lineNumber: 1, column: 1 });
|
||||
editor.trigger('keyboard', Handler.Type, { text: 'My' });
|
||||
|
||||
}, event => {
|
||||
assert.equal(event.auto, true);
|
||||
assert.equal(event.completionModel.items.length, 1);
|
||||
const [first] = event.completionModel.items;
|
||||
assert.equal(first.suggestion.label, 'My Table');
|
||||
|
||||
return assertEvent(model.onDidSuggest, () => {
|
||||
editor.setPosition({ lineNumber: 1, column: 3 });
|
||||
editor.trigger('keyboard', Handler.Type, { text: ' ' });
|
||||
|
||||
}, event => {
|
||||
assert.equal(event.auto, true);
|
||||
assert.equal(event.completionModel.items.length, 1);
|
||||
const [first] = event.completionModel.items;
|
||||
assert.equal(first.suggestion.label, 'My Table');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,7 +17,7 @@ import { domEvent } from 'vs/base/browser/event';
|
|||
import { Emitter } from 'vs/base/common/event';
|
||||
|
||||
|
||||
export function fillInActions(menu: IMenu, context: any, target: IAction[] | { primary: IAction[]; secondary: IAction[]; }, ignoreAltKey?: boolean): void {
|
||||
export function fillInActions(menu: IMenu, context: any, target: IAction[] | { primary: IAction[]; secondary: IAction[]; }): void {
|
||||
const groups = menu.getActions(context);
|
||||
if (groups.length === 0) {
|
||||
return;
|
||||
|
@ -25,11 +25,6 @@ export function fillInActions(menu: IMenu, context: any, target: IAction[] | { p
|
|||
|
||||
for (let tuple of groups) {
|
||||
let [group, actions] = tuple;
|
||||
|
||||
if (!ignoreAltKey && _altKey.value) {
|
||||
swapWithAltActionsIfPossible(actions);
|
||||
}
|
||||
|
||||
if (group === 'navigation') {
|
||||
|
||||
const head = Array.isArray<IAction>(target) ? target : target.primary;
|
||||
|
@ -67,13 +62,6 @@ export function fillInActions(menu: IMenu, context: any, target: IAction[] | { p
|
|||
}
|
||||
}
|
||||
|
||||
function swapWithAltActionsIfPossible(actions: MenuItemAction[]): void {
|
||||
for (let i = 0; i < actions.length; i++) {
|
||||
if (actions[i].alt) {
|
||||
actions[i] = actions[i].alt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function createActionItem(action: IAction, keybindingService: IKeybindingService, messageService: IMessageService): ActionItem {
|
||||
if (action instanceof MenuItemAction) {
|
||||
|
@ -86,8 +74,6 @@ const _altKey = new class extends Emitter<boolean> {
|
|||
|
||||
private _subscriptions: IDisposable[] = [];
|
||||
|
||||
private _value = false;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
|
@ -97,15 +83,6 @@ const _altKey = new class extends Emitter<boolean> {
|
|||
this._subscriptions.push(domEvent(document.body, 'blur')(e => this.fire(false)));
|
||||
}
|
||||
|
||||
fire(value: boolean) {
|
||||
super.fire(value);
|
||||
this._value = value;
|
||||
}
|
||||
|
||||
get value() {
|
||||
return this._value;
|
||||
}
|
||||
|
||||
dispose() {
|
||||
super.dispose();
|
||||
this._subscriptions = dispose(this._subscriptions);
|
||||
|
|
|
@ -50,7 +50,7 @@ class Menu implements IMenu {
|
|||
this._extensionService.onReady().then(_ => {
|
||||
|
||||
const menuItems = MenuRegistry.getMenuItems(id);
|
||||
const keysFilter: { [key: string]: boolean } = Object.create(null);
|
||||
const keysFilter = new Set<string>();
|
||||
|
||||
let group: MenuItemGroup;
|
||||
menuItems.sort(Menu._compareMenuItems);
|
||||
|
@ -71,7 +71,7 @@ class Menu implements IMenu {
|
|||
// subscribe to context changes
|
||||
this._disposables.push(this._contextKeyService.onDidChangeContext(keys => {
|
||||
for (let k of keys) {
|
||||
if (keysFilter[k]) {
|
||||
if (keysFilter.has(k)) {
|
||||
this._onDidChange.fire();
|
||||
return;
|
||||
}
|
||||
|
@ -110,10 +110,10 @@ class Menu implements IMenu {
|
|||
return result;
|
||||
}
|
||||
|
||||
private static _fillInKbExprKeys(exp: ContextKeyExpr, set: { [k: string]: boolean }): void {
|
||||
private static _fillInKbExprKeys(exp: ContextKeyExpr, set: Set<string>): void {
|
||||
if (exp) {
|
||||
for (let key of exp.keys()) {
|
||||
set[key] = true;
|
||||
set.add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ function isCommand(thing: any): thing is ICommand {
|
|||
|
||||
export const CommandsRegistry: ICommandRegistry = new class implements ICommandRegistry {
|
||||
|
||||
private _commands: { [id: string]: ICommand | ICommand[] } = Object.create(null);
|
||||
private _commands = new Map<string, ICommand | ICommand[]>();
|
||||
|
||||
registerCommand(id: string, commandOrDesc: ICommandHandler | ICommand): IDisposable {
|
||||
|
||||
|
@ -86,18 +86,18 @@ export const CommandsRegistry: ICommandRegistry = new class implements ICommandR
|
|||
}
|
||||
|
||||
// find a place to store the command
|
||||
const commandOrArray = this._commands[id];
|
||||
const commandOrArray = this._commands.get(id);
|
||||
if (commandOrArray === void 0) {
|
||||
this._commands[id] = command;
|
||||
this._commands.set(id, command);
|
||||
} else if (Array.isArray(commandOrArray)) {
|
||||
commandOrArray.unshift(command);
|
||||
} else {
|
||||
this._commands[id] = [command, commandOrArray];
|
||||
this._commands.set(id, [command, commandOrArray]);
|
||||
}
|
||||
|
||||
return {
|
||||
dispose: () => {
|
||||
const commandOrArray = this._commands[id];
|
||||
const commandOrArray = this._commands.get(id);
|
||||
if (Array.isArray(commandOrArray)) {
|
||||
// remove from array, remove array
|
||||
// if last element removed
|
||||
|
@ -105,19 +105,19 @@ export const CommandsRegistry: ICommandRegistry = new class implements ICommandR
|
|||
if (idx >= 0) {
|
||||
commandOrArray.splice(idx, 1);
|
||||
if (commandOrArray.length === 0) {
|
||||
delete this._commands[id];
|
||||
this._commands.delete(id);
|
||||
}
|
||||
}
|
||||
} else if (isCommand(commandOrArray)) {
|
||||
// remove from map
|
||||
delete this._commands[id];
|
||||
this._commands.delete(id);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
getCommand(id: string): ICommand {
|
||||
const commandOrArray = this._commands[id];
|
||||
const commandOrArray = this._commands.get(id);
|
||||
if (Array.isArray(commandOrArray)) {
|
||||
return commandOrArray[0];
|
||||
} else {
|
||||
|
@ -127,9 +127,9 @@ export const CommandsRegistry: ICommandRegistry = new class implements ICommandR
|
|||
|
||||
getCommands(): ICommandsMap {
|
||||
const result: ICommandsMap = Object.create(null);
|
||||
for (let id in this._commands) {
|
||||
result[id] = this.getCommand(id);
|
||||
}
|
||||
this._commands.forEach((value, key) => {
|
||||
result[key] = this.getCommand(key);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
@ -139,4 +139,4 @@ export const NullCommandService: ICommandService = {
|
|||
executeCommand() {
|
||||
return TPromise.as(undefined);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -82,7 +82,7 @@ export function getConfigurationValue<T>(config: any, settingPath: string, defau
|
|||
let current = config;
|
||||
for (let i = 0; i < path.length; i++) {
|
||||
current = current[path[i]];
|
||||
if (typeof current === 'undefined') {
|
||||
if (typeof current === 'undefined' || current === null) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,7 +148,7 @@ export function formatOptions(options: { [name: string]: string; }, columns: num
|
|||
}
|
||||
|
||||
function wrapText(text: string, columns: number): string[] {
|
||||
let lines = [];
|
||||
let lines: string[] = [];
|
||||
while (text.length) {
|
||||
let index = text.length < columns ? text.length : text.lastIndexOf(' ', columns);
|
||||
let line = text.slice(0, index).trim();
|
||||
|
|
|
@ -23,7 +23,7 @@ export interface ICommandAndKeybindingRule extends IKeybindingRule {
|
|||
}
|
||||
|
||||
export interface IKeybindingsRegistry {
|
||||
registerKeybindingRule(rule: IKeybindingRule);
|
||||
registerKeybindingRule(rule: IKeybindingRule): void;
|
||||
registerCommandAndKeybindingRule(desc: ICommandAndKeybindingRule): void;
|
||||
getDefaultKeybindings(): IKeybindingItem[];
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ export interface IWindowsService {
|
|||
openDevTools(windowId: number): TPromise<void>;
|
||||
toggleDevTools(windowId: number): TPromise<void>;
|
||||
// TODO@joao: rename, shouldn't this be closeWindow?
|
||||
// @ben: no, this actually leaves the window open but changes it to have no workspace opened
|
||||
closeFolder(windowId: number): TPromise<void>;
|
||||
toggleFullScreen(windowId: number): TPromise<void>;
|
||||
setRepresentedFilename(windowId: number, fileName: string): TPromise<void>;
|
||||
|
@ -40,8 +41,7 @@ export interface IWindowsService {
|
|||
quit(): TPromise<void>;
|
||||
|
||||
// Global methods
|
||||
// TODO@joao: rename, shouldn't this be openWindow?
|
||||
windowOpen(paths: string[], forceNewWindow?: boolean): TPromise<void>;
|
||||
openWindow(paths: string[], options?: { forceNewWindow?: boolean, forceReuseWindow?: boolean }): TPromise<void>;
|
||||
openNewWindow(): TPromise<void>;
|
||||
showWindow(windowId: number): TPromise<void>;
|
||||
getWindows(): TPromise<{ id: number; path: string; title: string; }[]>;
|
||||
|
@ -87,7 +87,8 @@ export interface IWindowService {
|
|||
}
|
||||
|
||||
export interface IWindowSettings {
|
||||
openFilesInNewWindow: boolean;
|
||||
openFilesInNewWindow: 'on' | 'off' | 'default';
|
||||
openFoldersInNewWindow: 'on' | 'off' | 'default';
|
||||
reopenFolders: 'all' | 'one' | 'none';
|
||||
restoreFullscreen: boolean;
|
||||
zoomLevel: number;
|
||||
|
|
|
@ -31,7 +31,7 @@ export interface IWindowsChannel extends IChannel {
|
|||
call(command: 'setDocumentEdited', arg: [number, boolean]): TPromise<void>;
|
||||
call(command: 'toggleMenuBar', arg: number): TPromise<void>;
|
||||
call(command: 'quit'): TPromise<void>;
|
||||
call(command: 'windowOpen', arg: [string[], boolean]): TPromise<void>;
|
||||
call(command: 'openWindow', arg: [string[], { forceNewWindow?: boolean, forceReuseWindow?: boolean }]): TPromise<void>;
|
||||
call(command: 'openNewWindow'): TPromise<void>;
|
||||
call(command: 'showWindow', arg: number): TPromise<void>;
|
||||
call(command: 'getWindows'): TPromise<{ id: number; path: string; title: string; }[]>;
|
||||
|
@ -76,7 +76,7 @@ export class WindowsChannel implements IWindowsChannel {
|
|||
case 'unmaximizeWindow': return this.service.unmaximizeWindow(arg);
|
||||
case 'setDocumentEdited': return this.service.setDocumentEdited(arg[0], arg[1]);
|
||||
case 'toggleMenuBar': return this.service.toggleMenuBar(arg);
|
||||
case 'windowOpen': return this.service.windowOpen(arg[0], arg[1]);
|
||||
case 'openWindow': return this.service.openWindow(arg[0], arg[1]);
|
||||
case 'openNewWindow': return this.service.openNewWindow();
|
||||
case 'showWindow': return this.service.showWindow(arg);
|
||||
case 'getWindows': return this.service.getWindows();
|
||||
|
@ -179,8 +179,8 @@ export class WindowsChannelClient implements IWindowsService {
|
|||
return this.channel.call('quit');
|
||||
}
|
||||
|
||||
windowOpen(paths: string[], forceNewWindow?: boolean): TPromise<void> {
|
||||
return this.channel.call('windowOpen', [paths, forceNewWindow]);
|
||||
openWindow(paths: string[], options?: { forceNewWindow?: boolean, forceReuseWindow?: boolean }): TPromise<void> {
|
||||
return this.channel.call('openWindow', [paths, options]);
|
||||
}
|
||||
|
||||
openNewWindow(): TPromise<void> {
|
||||
|
|
|
@ -16,7 +16,7 @@ import { fromEventEmitter } from 'vs/base/node/event';
|
|||
import { IURLService } from 'vs/platform/url/common/url';
|
||||
|
||||
// TODO@Joao: remove this dependency, move all implementation to this class
|
||||
import { IWindowsMainService } from 'vs/code/electron-main/windows';
|
||||
import { IWindowsMainService, OpenContext } from 'vs/code/electron-main/windows';
|
||||
|
||||
export class WindowsService implements IWindowsService, IDisposable {
|
||||
|
||||
|
@ -94,7 +94,7 @@ export class WindowsService implements IWindowsService, IDisposable {
|
|||
const vscodeWindow = this.windowsMainService.getWindowById(windowId);
|
||||
|
||||
if (vscodeWindow) {
|
||||
this.windowsMainService.open({ cli: this.environmentService.args, forceEmpty: true, windowToUse: vscodeWindow });
|
||||
this.windowsMainService.open({ context: OpenContext.OTHER, cli: this.environmentService.args, forceEmpty: true, windowToUse: vscodeWindow });
|
||||
}
|
||||
|
||||
return TPromise.as(null);
|
||||
|
@ -198,17 +198,17 @@ export class WindowsService implements IWindowsService, IDisposable {
|
|||
return TPromise.as(null);
|
||||
}
|
||||
|
||||
windowOpen(paths: string[], forceNewWindow?: boolean): TPromise<void> {
|
||||
openWindow(paths: string[], options?: { forceNewWindow?: boolean, forceReuseWindow?: boolean }): TPromise<void> {
|
||||
if (!paths || !paths.length) {
|
||||
return TPromise.as(null);
|
||||
}
|
||||
|
||||
this.windowsMainService.open({ cli: this.environmentService.args, pathsToOpen: paths, forceNewWindow: forceNewWindow });
|
||||
this.windowsMainService.open({ context: OpenContext.OTHER, cli: this.environmentService.args, pathsToOpen: paths, forceNewWindow: options && options.forceNewWindow, forceReuseWindow: options && options.forceReuseWindow });
|
||||
return TPromise.as(null);
|
||||
}
|
||||
|
||||
openNewWindow(): TPromise<void> {
|
||||
this.windowsMainService.openNewWindow();
|
||||
this.windowsMainService.openNewWindow(OpenContext.OTHER);
|
||||
return TPromise.as(null);
|
||||
}
|
||||
|
||||
|
@ -271,7 +271,7 @@ export class WindowsService implements IWindowsService, IDisposable {
|
|||
const cli = assign(Object.create(null), this.environmentService.args, { goto: true });
|
||||
const pathsToOpen = [filePath];
|
||||
|
||||
this.windowsMainService.open({ cli, pathsToOpen });
|
||||
this.windowsMainService.open({ context: OpenContext.OTHER, cli, pathsToOpen });
|
||||
return TPromise.as(null);
|
||||
}
|
||||
|
||||
|
|
|
@ -466,7 +466,7 @@ function createExtensionPathIndex(extensionService: ExtHostExtensionService): TP
|
|||
function defineAPI(factory: IExtensionApiFactory, extensionPaths: TrieMap<IExtensionDescription>): void {
|
||||
|
||||
// each extension is meant to get its own api implementation
|
||||
const extApiImpl: { [id: string]: typeof vscode } = Object.create(null);
|
||||
const extApiImpl = new Map<string, typeof vscode>();
|
||||
let defaultApiImpl: typeof vscode;
|
||||
|
||||
const node_module = <any>require.__$__nodeRequire('module');
|
||||
|
@ -479,9 +479,10 @@ function defineAPI(factory: IExtensionApiFactory, extensionPaths: TrieMap<IExten
|
|||
// get extension id from filename and api for extension
|
||||
const ext = extensionPaths.findSubstr(parent.filename);
|
||||
if (ext) {
|
||||
let apiImpl = extApiImpl[ext.id];
|
||||
let apiImpl = extApiImpl.get(ext.id);
|
||||
if (!apiImpl) {
|
||||
apiImpl = extApiImpl[ext.id] = factory(ext);
|
||||
apiImpl = factory(ext);
|
||||
extApiImpl.set(ext.id, apiImpl);
|
||||
}
|
||||
return apiImpl;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ interface CommandHandler {
|
|||
|
||||
export class ExtHostCommands extends ExtHostCommandsShape {
|
||||
|
||||
private _commands: { [n: string]: CommandHandler } = Object.create(null);
|
||||
private _commands = new Map<string, CommandHandler>();
|
||||
private _proxy: MainThreadCommandsShape;
|
||||
private _extHostEditors: ExtHostEditors;
|
||||
private _converter: CommandsConverter;
|
||||
|
@ -52,15 +52,15 @@ export class ExtHostCommands extends ExtHostCommandsShape {
|
|||
throw new Error('invalid id');
|
||||
}
|
||||
|
||||
if (this._commands[id]) {
|
||||
if (this._commands.has(id)) {
|
||||
throw new Error('command with id already exists');
|
||||
}
|
||||
|
||||
this._commands[id] = { callback, thisArg, description };
|
||||
this._commands.set(id, { callback, thisArg, description });
|
||||
this._proxy.$registerCommand(id);
|
||||
|
||||
return new extHostTypes.Disposable(() => {
|
||||
if (delete this._commands[id]) {
|
||||
if (this._commands.delete(id)) {
|
||||
this._proxy.$unregisterCommand(id);
|
||||
}
|
||||
});
|
||||
|
@ -68,7 +68,7 @@ export class ExtHostCommands extends ExtHostCommandsShape {
|
|||
|
||||
executeCommand<T>(id: string, ...args: any[]): Thenable<T> {
|
||||
|
||||
if (this._commands[id]) {
|
||||
if (this._commands.has(id)) {
|
||||
// we stay inside the extension host and support
|
||||
// to pass any kind of parameters around
|
||||
return this.$executeContributedCommand(id, ...args);
|
||||
|
@ -97,7 +97,7 @@ export class ExtHostCommands extends ExtHostCommandsShape {
|
|||
}
|
||||
|
||||
$executeContributedCommand<T>(id: string, ...args: any[]): Thenable<T> {
|
||||
let command = this._commands[id];
|
||||
let command = this._commands.get(id);
|
||||
if (!command) {
|
||||
return TPromise.wrapError<T>(`Contributed command '${id}' does not exist.`);
|
||||
}
|
||||
|
@ -139,12 +139,12 @@ export class ExtHostCommands extends ExtHostCommandsShape {
|
|||
|
||||
$getContributedCommandHandlerDescriptions(): TPromise<{ [id: string]: string | ICommandHandlerDescription }> {
|
||||
const result: { [id: string]: string | ICommandHandlerDescription } = Object.create(null);
|
||||
for (let id in this._commands) {
|
||||
let {description} = this._commands[id];
|
||||
this._commands.forEach((command, id) => {
|
||||
let {description} = command;
|
||||
if (description) {
|
||||
result[id] = description;
|
||||
}
|
||||
}
|
||||
});
|
||||
return TPromise.as(result);
|
||||
}
|
||||
}
|
||||
|
@ -212,4 +212,4 @@ export class CommandsConverter {
|
|||
return this._commands.executeCommand(actualCmd.command, ...actualCmd.arguments);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,13 +15,13 @@ import { DiagnosticSeverity } from './extHostTypes';
|
|||
|
||||
export class DiagnosticCollection implements vscode.DiagnosticCollection {
|
||||
|
||||
private static _maxDiagnosticsPerFile: number = 250;
|
||||
private static readonly _maxDiagnosticsPerFile: number = 250;
|
||||
|
||||
private readonly _name: string;
|
||||
|
||||
private _name: string;
|
||||
private _proxy: MainThreadDiagnosticsShape;
|
||||
|
||||
private _isDisposed = false;
|
||||
private _data: { [uri: string]: vscode.Diagnostic[] } = Object.create(null);
|
||||
private _data = new Map<string, vscode.Diagnostic[]>();
|
||||
|
||||
constructor(name: string, proxy: MainThreadDiagnosticsShape) {
|
||||
this._name = name;
|
||||
|
@ -66,7 +66,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
|
|||
}
|
||||
|
||||
// update single row
|
||||
this._data[first.toString()] = diagnostics;
|
||||
this._data.set(first.toString(), diagnostics);
|
||||
toSync = [first];
|
||||
|
||||
} else if (Array.isArray(first)) {
|
||||
|
@ -83,19 +83,19 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
|
|||
for (const {tuple} of sortedTuples) {
|
||||
const [uri, diagnostics] = tuple;
|
||||
if (!lastUri || uri.toString() !== lastUri.toString()) {
|
||||
if (lastUri && this._data[lastUri.toString()].length === 0) {
|
||||
delete this._data[lastUri.toString()];
|
||||
if (lastUri && this._data.get(lastUri.toString()).length === 0) {
|
||||
this._data.delete(lastUri.toString());
|
||||
}
|
||||
lastUri = uri;
|
||||
toSync.push(uri);
|
||||
this._data[uri.toString()] = [];
|
||||
this._data.set(uri.toString(), []);
|
||||
}
|
||||
|
||||
if (!diagnostics) {
|
||||
// [Uri, undefined] means clear this
|
||||
this._data[uri.toString()].length = 0;
|
||||
this._data.get(uri.toString()).length = 0;
|
||||
} else {
|
||||
this._data[uri.toString()].push(...diagnostics);
|
||||
this._data.get(uri.toString()).push(...diagnostics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
|
|||
const entries: [URI, IMarkerData[]][] = [];
|
||||
for (let uri of toSync) {
|
||||
let marker: IMarkerData[];
|
||||
let diagnostics = this._data[uri.toString()];
|
||||
let diagnostics = this._data.get(uri.toString());
|
||||
if (diagnostics) {
|
||||
|
||||
// no more than 250 diagnostics per file
|
||||
|
@ -144,27 +144,27 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
|
|||
|
||||
delete(uri: vscode.Uri): void {
|
||||
this._checkDisposed();
|
||||
delete this._data[uri.toString()];
|
||||
this._data.delete(uri.toString());
|
||||
this._proxy.$changeMany(this.name, [[<URI>uri, undefined]]);
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
this._checkDisposed();
|
||||
this._data = Object.create(null);
|
||||
this._data.clear();
|
||||
this._proxy.$clear(this.name);
|
||||
}
|
||||
|
||||
forEach(callback: (uri: URI, diagnostics: vscode.Diagnostic[], collection: DiagnosticCollection) => any, thisArg?: any): void {
|
||||
this._checkDisposed();
|
||||
for (let key in this._data) {
|
||||
this._data.forEach((value, key) => {
|
||||
let uri = URI.parse(key);
|
||||
callback.apply(thisArg, [uri, this.get(uri), this]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
get(uri: URI): vscode.Diagnostic[] {
|
||||
this._checkDisposed();
|
||||
let result = this._data[uri.toString()];
|
||||
let result = this._data.get(uri.toString());
|
||||
if (Array.isArray(result)) {
|
||||
return <vscode.Diagnostic[]>Object.freeze(result.slice(0));
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
|
|||
|
||||
has(uri: URI): boolean {
|
||||
this._checkDisposed();
|
||||
return Array.isArray(this._data[uri.toString()]);
|
||||
return Array.isArray(this._data.get(uri.toString()));
|
||||
}
|
||||
|
||||
private _checkDisposed() {
|
||||
|
|
|
@ -20,16 +20,14 @@ import { asWinJsPromise } from 'vs/base/common/async';
|
|||
import { getWordAtText, ensureValidWordDefinition } from 'vs/editor/common/model/wordHelper';
|
||||
import { MainContext, MainThreadDocumentsShape, ExtHostDocumentsShape, IModelAddedData } from './extHost.protocol';
|
||||
|
||||
const _modeId2WordDefinition: {
|
||||
[modeId: string]: RegExp;
|
||||
} = Object.create(null);
|
||||
const _modeId2WordDefinition = new Map<string, RegExp>();
|
||||
|
||||
function setWordDefinitionFor(modeId: string, wordDefinition: RegExp): void {
|
||||
_modeId2WordDefinition[modeId] = wordDefinition;
|
||||
_modeId2WordDefinition.set(modeId, wordDefinition);
|
||||
}
|
||||
|
||||
function getWordDefinitionFor(modeId: string): RegExp {
|
||||
return _modeId2WordDefinition[modeId];
|
||||
return _modeId2WordDefinition.get(modeId);
|
||||
}
|
||||
|
||||
export class ExtHostDocuments extends ExtHostDocumentsShape {
|
||||
|
@ -48,9 +46,9 @@ export class ExtHostDocuments extends ExtHostDocumentsShape {
|
|||
private _onDidSaveDocumentEventEmitter: Emitter<vscode.TextDocument>;
|
||||
public onDidSaveDocument: Event<vscode.TextDocument>;
|
||||
|
||||
private _documentData: { [modelUri: string]: ExtHostDocumentData; };
|
||||
private _documentLoader: { [modelUri: string]: TPromise<ExtHostDocumentData> };
|
||||
private _documentContentProviders: { [handle: number]: vscode.TextDocumentContentProvider; };
|
||||
private _documentData = new Map<string, ExtHostDocumentData>();
|
||||
private _documentLoader = new Map<string, TPromise<ExtHostDocumentData>>();
|
||||
private _documentContentProviders = new Map<number, vscode.TextDocumentContentProvider>();
|
||||
|
||||
private _proxy: MainThreadDocumentsShape;
|
||||
|
||||
|
@ -69,17 +67,11 @@ export class ExtHostDocuments extends ExtHostDocumentsShape {
|
|||
|
||||
this._onDidSaveDocumentEventEmitter = new Emitter<vscode.TextDocument>();
|
||||
this.onDidSaveDocument = this._onDidSaveDocumentEventEmitter.event;
|
||||
|
||||
this._documentData = Object.create(null);
|
||||
this._documentLoader = Object.create(null);
|
||||
this._documentContentProviders = Object.create(null);
|
||||
}
|
||||
|
||||
public getAllDocumentData(): ExtHostDocumentData[] {
|
||||
const result: ExtHostDocumentData[] = [];
|
||||
for (let key in this._documentData) {
|
||||
result.push(this._documentData[key]);
|
||||
}
|
||||
this._documentData.forEach(data => result.push(data));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -87,7 +79,7 @@ export class ExtHostDocuments extends ExtHostDocumentsShape {
|
|||
if (!resource) {
|
||||
return;
|
||||
}
|
||||
const data = this._documentData[resource.toString()];
|
||||
const data = this._documentData.get(resource.toString());
|
||||
if (data) {
|
||||
return data;
|
||||
}
|
||||
|
@ -95,21 +87,21 @@ export class ExtHostDocuments extends ExtHostDocumentsShape {
|
|||
|
||||
public ensureDocumentData(uri: URI): TPromise<ExtHostDocumentData> {
|
||||
|
||||
let cached = this._documentData[uri.toString()];
|
||||
let cached = this._documentData.get(uri.toString());
|
||||
if (cached) {
|
||||
return TPromise.as(cached);
|
||||
}
|
||||
|
||||
let promise = this._documentLoader[uri.toString()];
|
||||
let promise = this._documentLoader.get(uri.toString());
|
||||
if (!promise) {
|
||||
promise = this._proxy.$tryOpenDocument(uri).then(() => {
|
||||
delete this._documentLoader[uri.toString()];
|
||||
return this._documentData[uri.toString()];
|
||||
this._documentLoader.delete(uri.toString());
|
||||
return this._documentData.get(uri.toString());
|
||||
}, err => {
|
||||
delete this._documentLoader[uri.toString()];
|
||||
this._documentLoader.delete(uri.toString());
|
||||
return TPromise.wrapError(err);
|
||||
});
|
||||
this._documentLoader[uri.toString()] = promise;
|
||||
this._documentLoader.set(uri.toString(), promise);
|
||||
}
|
||||
|
||||
return promise;
|
||||
|
@ -122,13 +114,13 @@ export class ExtHostDocuments extends ExtHostDocumentsShape {
|
|||
|
||||
const handle = ExtHostDocuments._handlePool++;
|
||||
|
||||
this._documentContentProviders[handle] = provider;
|
||||
this._documentContentProviders.set(handle, provider);
|
||||
this._proxy.$registerTextContentProvider(handle, scheme);
|
||||
|
||||
let subscription: IDisposable;
|
||||
if (typeof provider.onDidChange === 'function') {
|
||||
subscription = provider.onDidChange(uri => {
|
||||
if (this._documentData[uri.toString()]) {
|
||||
if (this._documentData.has(uri.toString())) {
|
||||
this.$provideTextDocumentContent(handle, <URI>uri).then(value => {
|
||||
return this._proxy.$onVirtualDocumentChange(<URI>uri, value);
|
||||
}, onUnexpectedError);
|
||||
|
@ -136,7 +128,7 @@ export class ExtHostDocuments extends ExtHostDocumentsShape {
|
|||
});
|
||||
}
|
||||
return new Disposable(() => {
|
||||
if (delete this._documentContentProviders[handle]) {
|
||||
if (this._documentContentProviders.delete(handle)) {
|
||||
this._proxy.$unregisterTextContentProvider(handle);
|
||||
}
|
||||
if (subscription) {
|
||||
|
@ -147,7 +139,7 @@ export class ExtHostDocuments extends ExtHostDocumentsShape {
|
|||
}
|
||||
|
||||
$provideTextDocumentContent(handle: number, uri: URI): TPromise<string> {
|
||||
const provider = this._documentContentProviders[handle];
|
||||
const provider = this._documentContentProviders.get(handle);
|
||||
if (!provider) {
|
||||
return TPromise.wrapError<string>(`unsupported uri-scheme: ${uri.scheme}`);
|
||||
}
|
||||
|
@ -157,15 +149,15 @@ export class ExtHostDocuments extends ExtHostDocumentsShape {
|
|||
public $acceptModelAdd(initData: IModelAddedData): void {
|
||||
let data = new ExtHostDocumentData(this._proxy, initData.url, initData.value.lines, initData.value.EOL, initData.modeId, initData.versionId, initData.isDirty);
|
||||
let key = data.document.uri.toString();
|
||||
if (this._documentData[key]) {
|
||||
if (this._documentData.has(key)) {
|
||||
throw new Error('Document `' + key + '` already exists.');
|
||||
}
|
||||
this._documentData[key] = data;
|
||||
this._documentData.set(key, data);
|
||||
this._onDidAddDocumentEventEmitter.fire(data.document);
|
||||
}
|
||||
|
||||
public $acceptModelModeChanged(strURL: string, oldModeId: string, newModeId: string): void {
|
||||
let data = this._documentData[strURL];
|
||||
let data = this._documentData.get(strURL);
|
||||
|
||||
// Treat a mode change as a remove + add
|
||||
|
||||
|
@ -175,33 +167,33 @@ export class ExtHostDocuments extends ExtHostDocumentsShape {
|
|||
}
|
||||
|
||||
public $acceptModelSaved(strURL: string): void {
|
||||
let data = this._documentData[strURL];
|
||||
let data = this._documentData.get(strURL);
|
||||
data._acceptIsDirty(false);
|
||||
this._onDidSaveDocumentEventEmitter.fire(data.document);
|
||||
}
|
||||
|
||||
public $acceptModelDirty(strURL: string): void {
|
||||
let document = this._documentData[strURL];
|
||||
let document = this._documentData.get(strURL);
|
||||
document._acceptIsDirty(true);
|
||||
}
|
||||
|
||||
public $acceptModelReverted(strURL: string): void {
|
||||
let document = this._documentData[strURL];
|
||||
let document = this._documentData.get(strURL);
|
||||
document._acceptIsDirty(false);
|
||||
}
|
||||
|
||||
public $acceptModelRemoved(strURL: string): void {
|
||||
if (!this._documentData[strURL]) {
|
||||
if (!this._documentData.has(strURL)) {
|
||||
throw new Error('Document `' + strURL + '` does not exist.');
|
||||
}
|
||||
let data = this._documentData[strURL];
|
||||
delete this._documentData[strURL];
|
||||
let data = this._documentData.get(strURL);
|
||||
this._documentData.delete(strURL);
|
||||
this._onDidRemoveDocumentEventEmitter.fire(data.document);
|
||||
data.dispose();
|
||||
}
|
||||
|
||||
public $acceptModelChanged(strURL: string, events: editorCommon.IModelContentChangedEvent2[], isDirty: boolean): void {
|
||||
let data = this._documentData[strURL];
|
||||
let data = this._documentData.get(strURL);
|
||||
data._acceptIsDirty(isDirty);
|
||||
data.onEvents(events);
|
||||
this._onDidChangeDocumentEventEmitter.fire({
|
||||
|
|
|
@ -30,7 +30,7 @@ export class ExtHostEditors extends ExtHostEditorsShape {
|
|||
public onDidChangeTextEditorViewColumn: Event<vscode.TextEditorViewColumnChangeEvent>;
|
||||
private _onDidChangeTextEditorViewColumn: Emitter<vscode.TextEditorViewColumnChangeEvent>;
|
||||
|
||||
private _editors: { [id: string]: ExtHostTextEditor };
|
||||
private _editors: Map<string, ExtHostTextEditor>;
|
||||
private _proxy: MainThreadEditorsShape;
|
||||
private _onDidChangeActiveTextEditor: Emitter<vscode.TextEditor>;
|
||||
private _onDidChangeVisibleTextEditors: Emitter<vscode.TextEditor[]>;
|
||||
|
@ -56,17 +56,17 @@ export class ExtHostEditors extends ExtHostEditorsShape {
|
|||
this._proxy = threadService.get(MainContext.MainThreadEditors);
|
||||
this._onDidChangeActiveTextEditor = new Emitter<vscode.TextEditor>();
|
||||
this._onDidChangeVisibleTextEditors = new Emitter<vscode.TextEditor[]>();
|
||||
this._editors = Object.create(null);
|
||||
this._editors = new Map<string, ExtHostTextEditor>();
|
||||
|
||||
this._visibleEditorIds = [];
|
||||
}
|
||||
|
||||
getActiveTextEditor(): vscode.TextEditor {
|
||||
return this._editors[this._activeEditorId];
|
||||
return this._editors.get(this._activeEditorId);
|
||||
}
|
||||
|
||||
getVisibleTextEditors(): vscode.TextEditor[] {
|
||||
return this._visibleEditorIds.map(id => this._editors[id]);
|
||||
return this._visibleEditorIds.map(id => this._editors.get(id));
|
||||
}
|
||||
|
||||
get onDidChangeActiveTextEditor(): Event<vscode.TextEditor> {
|
||||
|
@ -79,7 +79,7 @@ export class ExtHostEditors extends ExtHostEditorsShape {
|
|||
|
||||
showTextDocument(document: vscode.TextDocument, column: vscode.ViewColumn, preserveFocus: boolean): TPromise<vscode.TextEditor> {
|
||||
return this._proxy.$tryShowTextDocument(<URI>document.uri, TypeConverters.fromViewColumn(column), preserveFocus).then(id => {
|
||||
let editor = this._editors[id];
|
||||
let editor = this._editors.get(id);
|
||||
if (editor) {
|
||||
return editor;
|
||||
} else {
|
||||
|
@ -97,11 +97,11 @@ export class ExtHostEditors extends ExtHostEditorsShape {
|
|||
$acceptTextEditorAdd(data: ITextEditorAddData): void {
|
||||
let document = this._extHostDocuments.getDocumentData(data.document);
|
||||
let newEditor = new ExtHostTextEditor(this._proxy, data.id, document, data.selections.map(TypeConverters.toSelection), data.options, TypeConverters.toViewColumn(data.editorPosition));
|
||||
this._editors[data.id] = newEditor;
|
||||
this._editors.set(data.id, newEditor);
|
||||
}
|
||||
|
||||
$acceptOptionsChanged(id: string, opts: IResolvedTextEditorConfiguration): void {
|
||||
let editor = this._editors[id];
|
||||
let editor = this._editors.get(id);
|
||||
editor._acceptOptions(opts);
|
||||
this._onDidChangeTextEditorOptions.fire({
|
||||
textEditor: editor,
|
||||
|
@ -112,7 +112,7 @@ export class ExtHostEditors extends ExtHostEditorsShape {
|
|||
$acceptSelectionsChanged(id: string, event: ISelectionChangeEvent): void {
|
||||
const kind = TextEditorSelectionChangeKind.fromValue(event.source);
|
||||
const selections = event.selections.map(TypeConverters.toSelection);
|
||||
const textEditor = this._editors[id];
|
||||
const textEditor = this._editors.get(id);
|
||||
textEditor._acceptSelections(selections);
|
||||
this._onDidChangeTextEditorSelection.fire({
|
||||
textEditor,
|
||||
|
@ -145,7 +145,7 @@ export class ExtHostEditors extends ExtHostEditorsShape {
|
|||
|
||||
$acceptEditorPositionData(data: ITextEditorPositionData): void {
|
||||
for (let id in data) {
|
||||
let textEditor = this._editors[id];
|
||||
let textEditor = this._editors.get(id);
|
||||
let viewColumn = TypeConverters.toViewColumn(data[id]);
|
||||
if (textEditor.viewColumn !== viewColumn) {
|
||||
textEditor._acceptViewColumn(viewColumn);
|
||||
|
@ -165,9 +165,9 @@ export class ExtHostEditors extends ExtHostEditorsShape {
|
|||
this.$acceptActiveEditorAndVisibleEditors(this._activeEditorId, newVisibleEditors);
|
||||
}
|
||||
|
||||
let editor = this._editors[id];
|
||||
let editor = this._editors.get(id);
|
||||
editor.dispose();
|
||||
delete this._editors[id];
|
||||
this._editors.delete(id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,20 +10,20 @@ export class ExtHostHeapService extends ExtHostHeapServiceShape {
|
|||
|
||||
private static _idPool = 0;
|
||||
|
||||
private _data: { [n: number]: any } = Object.create(null);
|
||||
private _data = new Map<number, any>();
|
||||
|
||||
keep(obj: any): number {
|
||||
const id = ExtHostHeapService._idPool++;
|
||||
this._data[id] = obj;
|
||||
this._data.set(id, obj);
|
||||
return id;
|
||||
}
|
||||
|
||||
delete(id: number): boolean {
|
||||
return this._data[id];
|
||||
return this._data.delete(id);
|
||||
}
|
||||
|
||||
get<T>(id: number): T {
|
||||
return this._data[id];
|
||||
return this._data.get(id);
|
||||
}
|
||||
|
||||
$onGarbageCollection(ids: number[]): void {
|
||||
|
@ -31,4 +31,4 @@ export class ExtHostHeapService extends ExtHostHeapServiceShape {
|
|||
this.delete(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -624,7 +624,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
|
|||
private _commands: ExtHostCommands;
|
||||
private _heapService: ExtHostHeapService;
|
||||
private _diagnostics: ExtHostDiagnostics;
|
||||
private _adapter: { [handle: number]: Adapter } = Object.create(null);
|
||||
private _adapter = new Map<number, Adapter>();
|
||||
|
||||
constructor(
|
||||
threadService: IThreadService,
|
||||
|
@ -643,7 +643,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
|
|||
|
||||
private _createDisposable(handle: number): Disposable {
|
||||
return new Disposable(() => {
|
||||
delete this._adapter[handle];
|
||||
this._adapter.delete(handle);
|
||||
this._proxy.$unregister(handle);
|
||||
});
|
||||
}
|
||||
|
@ -653,7 +653,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
|
|||
}
|
||||
|
||||
private _withAdapter<A, R>(handle: number, ctor: { new (...args: any[]): A }, callback: (adapter: A) => TPromise<R>): TPromise<R> {
|
||||
let adapter = this._adapter[handle];
|
||||
let adapter = this._adapter.get(handle);
|
||||
if (!(adapter instanceof ctor)) {
|
||||
return TPromise.wrapError(new Error('no adapter found'));
|
||||
}
|
||||
|
@ -664,7 +664,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
|
|||
|
||||
registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter[handle] = new OutlineAdapter(this._documents, provider);
|
||||
this._adapter.set(handle, new OutlineAdapter(this._documents, provider));
|
||||
this._proxy.$registerOutlineSupport(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
@ -679,7 +679,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
|
|||
const handle = this._nextHandle();
|
||||
const eventHandle = typeof provider.onDidChangeCodeLenses === 'function' ? this._nextHandle() : undefined;
|
||||
|
||||
this._adapter[handle] = new CodeLensAdapter(this._documents, this._commands.converter, this._heapService, provider);
|
||||
this._adapter.set(handle, new CodeLensAdapter(this._documents, this._commands.converter, this._heapService, provider));
|
||||
this._proxy.$registerCodeLensSupport(handle, selector, eventHandle);
|
||||
let result = this._createDisposable(handle);
|
||||
|
||||
|
@ -703,7 +703,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
|
|||
|
||||
registerDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter[handle] = new DefinitionAdapter(this._documents, provider);
|
||||
this._adapter.set(handle, new DefinitionAdapter(this._documents, provider));
|
||||
this._proxy.$registerDeclaractionSupport(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
@ -716,7 +716,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
|
|||
|
||||
registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter[handle] = new HoverAdapter(this._documents, provider);
|
||||
this._adapter.set(handle, new HoverAdapter(this._documents, provider));
|
||||
this._proxy.$registerHoverProvider(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
@ -729,7 +729,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
|
|||
|
||||
registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter[handle] = new DocumentHighlightAdapter(this._documents, provider);
|
||||
this._adapter.set(handle, new DocumentHighlightAdapter(this._documents, provider));
|
||||
this._proxy.$registerDocumentHighlightProvider(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
@ -742,7 +742,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
|
|||
|
||||
registerReferenceProvider(selector: vscode.DocumentSelector, provider: vscode.ReferenceProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter[handle] = new ReferenceAdapter(this._documents, provider);
|
||||
this._adapter.set(handle, new ReferenceAdapter(this._documents, provider));
|
||||
this._proxy.$registerReferenceSupport(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
@ -755,7 +755,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
|
|||
|
||||
registerCodeActionProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter[handle] = new QuickFixAdapter(this._documents, this._commands.converter, this._diagnostics, this._heapService, provider);
|
||||
this._adapter.set(handle, new QuickFixAdapter(this._documents, this._commands.converter, this._diagnostics, this._heapService, provider));
|
||||
this._proxy.$registerQuickFixSupport(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
@ -768,7 +768,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
|
|||
|
||||
registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter[handle] = new DocumentFormattingAdapter(this._documents, provider);
|
||||
this._adapter.set(handle, new DocumentFormattingAdapter(this._documents, provider));
|
||||
this._proxy.$registerDocumentFormattingSupport(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
@ -779,7 +779,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
|
|||
|
||||
registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter[handle] = new RangeFormattingAdapter(this._documents, provider);
|
||||
this._adapter.set(handle, new RangeFormattingAdapter(this._documents, provider));
|
||||
this._proxy.$registerRangeFormattingSupport(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
@ -790,7 +790,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
|
|||
|
||||
registerOnTypeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.OnTypeFormattingEditProvider, triggerCharacters: string[]): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter[handle] = new OnTypeFormattingAdapter(this._documents, provider);
|
||||
this._adapter.set(handle, new OnTypeFormattingAdapter(this._documents, provider));
|
||||
this._proxy.$registerOnTypeFormattingSupport(handle, selector, triggerCharacters);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
@ -803,7 +803,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
|
|||
|
||||
registerWorkspaceSymbolProvider(provider: vscode.WorkspaceSymbolProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter[handle] = new NavigateTypeAdapter(provider, this._heapService);
|
||||
this._adapter.set(handle, new NavigateTypeAdapter(provider, this._heapService));
|
||||
this._proxy.$registerNavigateTypeSupport(handle);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
@ -820,7 +820,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
|
|||
|
||||
registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter[handle] = new RenameAdapter(this._documents, provider);
|
||||
this._adapter.set(handle, new RenameAdapter(this._documents, provider));
|
||||
this._proxy.$registerRenameSupport(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
@ -833,7 +833,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
|
|||
|
||||
registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, triggerCharacters: string[]): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter[handle] = new SuggestAdapter(this._documents, this._commands.converter, this._heapService, provider);
|
||||
this._adapter.set(handle, new SuggestAdapter(this._documents, this._commands.converter, this._heapService, provider));
|
||||
this._proxy.$registerSuggestSupport(handle, selector, triggerCharacters);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
@ -850,7 +850,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
|
|||
|
||||
registerSignatureHelpProvider(selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, triggerCharacters: string[]): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter[handle] = new SignatureHelpAdapter(this._documents, provider);
|
||||
this._adapter.set(handle, new SignatureHelpAdapter(this._documents, provider));
|
||||
this._proxy.$registerSignatureHelpProvider(handle, selector, triggerCharacters);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
@ -863,7 +863,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
|
|||
|
||||
registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter[handle] = new LinkProviderAdapter(this._documents, provider);
|
||||
this._adapter.set(handle, new LinkProviderAdapter(this._documents, provider));
|
||||
this._proxy.$registerDocumentLinkProvider(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
|
|
@ -465,7 +465,7 @@ export class Uri extends URI { }
|
|||
export class WorkspaceEdit {
|
||||
|
||||
private _values: [Uri, TextEdit[]][] = [];
|
||||
private _index: { [uri: string]: number } = Object.create(null);
|
||||
private _index = new Map<string, number>();
|
||||
|
||||
replace(uri: Uri, range: Range, newText: string): void {
|
||||
let edit = new TextEdit(range, newText);
|
||||
|
@ -486,21 +486,21 @@ export class WorkspaceEdit {
|
|||
}
|
||||
|
||||
has(uri: Uri): boolean {
|
||||
return typeof this._index[uri.toString()] !== 'undefined';
|
||||
return this._index.has(uri.toString());
|
||||
}
|
||||
|
||||
set(uri: Uri, edits: TextEdit[]): void {
|
||||
let idx = this._index[uri.toString()];
|
||||
const idx = this._index.get(uri.toString());
|
||||
if (typeof idx === 'undefined') {
|
||||
let newLen = this._values.push([uri, edits]);
|
||||
this._index[uri.toString()] = newLen - 1;
|
||||
this._index.set(uri.toString(), newLen - 1);
|
||||
} else {
|
||||
this._values[idx][1] = edits;
|
||||
}
|
||||
}
|
||||
|
||||
get(uri: Uri): TextEdit[] {
|
||||
let idx = this._index[uri.toString()];
|
||||
let idx = this._index.get(uri.toString());
|
||||
return typeof idx !== 'undefined' && this._values[idx][1];
|
||||
}
|
||||
|
||||
|
|
|
@ -579,7 +579,7 @@ export class MainThreadEditorsTracker {
|
|||
}
|
||||
|
||||
private _findVisibleTextEditorIds(): string[] {
|
||||
let result = [];
|
||||
let result: string[] = [];
|
||||
let modelUris = Object.keys(this._model2TextEditors);
|
||||
for (let i = 0, len = modelUris.length; i < len; i++) {
|
||||
let editors = this._model2TextEditors[modelUris[i]];
|
||||
|
|
|
@ -16,7 +16,7 @@ export class MainThreadTreeExplorers extends MainThreadTreeExplorersShape {
|
|||
private _proxy: ExtHostTreeExplorersShape;
|
||||
|
||||
constructor(
|
||||
@IThreadService private threadService: IThreadService,
|
||||
@IThreadService threadService: IThreadService,
|
||||
@ITreeExplorerService private treeExplorerService: ITreeExplorerService,
|
||||
@IMessageService private messageService: IMessageService,
|
||||
@ICommandService private commandService: ICommandService
|
||||
|
|
|
@ -30,9 +30,9 @@ export class MainThreadWorkspace extends MainThreadWorkspaceShape {
|
|||
constructor(
|
||||
@ISearchService searchService: ISearchService,
|
||||
@IWorkspaceContextService contextService: IWorkspaceContextService,
|
||||
@ITextFileService textFileService,
|
||||
@IWorkbenchEditorService editorService,
|
||||
@ITextModelResolverService textModelResolverService,
|
||||
@ITextFileService textFileService: ITextFileService,
|
||||
@IWorkbenchEditorService editorService: IWorkbenchEditorService,
|
||||
@ITextModelResolverService textModelResolverService: ITextModelResolverService,
|
||||
@IFileService fileService: IFileService
|
||||
) {
|
||||
super();
|
||||
|
@ -99,7 +99,7 @@ export class MainThreadWorkspace extends MainThreadWorkspaceShape {
|
|||
}
|
||||
}
|
||||
|
||||
return bulkEdit(this._fileService, this._textModelResolverService, codeEditor, edits)
|
||||
return bulkEdit(this._textModelResolverService, codeEditor, edits, this._fileService)
|
||||
.then(() => true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ export class ContributableActionProvider implements IActionProvider {
|
|||
private registry: IActionBarRegistry;
|
||||
|
||||
constructor() {
|
||||
this.registry = (<IActionBarRegistry>Registry.as(Extensions.Actionbar));
|
||||
this.registry = Registry.as<IActionBarRegistry>(Extensions.Actionbar);
|
||||
}
|
||||
|
||||
private toContext(tree: ITree, element: any): any {
|
||||
|
|
|
@ -89,5 +89,5 @@ const schema: IJSONSchema =
|
|||
}
|
||||
};
|
||||
|
||||
const jsonRegistry = <IJSONContributionRegistry>Registry.as(JSONExtensions.JSONContribution);
|
||||
const jsonRegistry = Registry.as<IJSONContributionRegistry>(JSONExtensions.JSONContribution);
|
||||
jsonRegistry.registerSchema(schemaId, schema);
|
|
@ -10,7 +10,7 @@ import { KeyCode, KeyMod, KeyChord } from 'vs/base/common/keyCodes';
|
|||
import { Registry } from 'vs/platform/platform';
|
||||
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
|
||||
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actionRegistry';
|
||||
import { IPartService, IZenModeOptions } from 'vs/workbench/services/part/common/partService';
|
||||
import { IPartService } from 'vs/workbench/services/part/common/partService';
|
||||
|
||||
class ToggleZenMode extends Action {
|
||||
|
||||
|
@ -26,8 +26,8 @@ class ToggleZenMode extends Action {
|
|||
this.enabled = !!this.partService;
|
||||
}
|
||||
|
||||
public run(options: IZenModeOptions): TPromise<any> {
|
||||
this.partService.toggleZenMode(options);
|
||||
public run(): TPromise<any> {
|
||||
this.partService.toggleZenMode();
|
||||
return TPromise.as(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,14 +46,10 @@ export abstract class Composite extends WorkbenchComponent implements IComposite
|
|||
return null;
|
||||
}
|
||||
|
||||
public get telemetryService(): ITelemetryService {
|
||||
protected get telemetryService(): ITelemetryService {
|
||||
return this._telemetryService;
|
||||
}
|
||||
|
||||
public get telemetryData(): any {
|
||||
return this._telemetryData;
|
||||
}
|
||||
|
||||
public get onTitleAreaUpdate(): Event<void> {
|
||||
return this._onTitleAreaUpdate.event;
|
||||
}
|
||||
|
@ -102,7 +98,7 @@ export abstract class Composite extends WorkbenchComponent implements IComposite
|
|||
|
||||
// Only submit telemetry data when not running from an integration test
|
||||
if (this._telemetryService && this._telemetryService.publicLog) {
|
||||
let eventName: string = 'compositeOpen';
|
||||
const eventName: string = 'compositeOpen';
|
||||
this._telemetryService.publicLog(eventName, { composite: this.getId() });
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +110,7 @@ export abstract class Composite extends WorkbenchComponent implements IComposite
|
|||
|
||||
// Only submit telemetry data when not running from an integration test
|
||||
if (this._telemetryService && this._telemetryService.publicLog) {
|
||||
let eventName: string = 'compositeShown';
|
||||
const eventName: string = 'compositeShown';
|
||||
this._telemetryData.composite = this.getId();
|
||||
this._telemetryService.publicLog(eventName, this._telemetryData);
|
||||
}
|
||||
|
@ -223,10 +219,10 @@ export abstract class CompositeDescriptor<T extends Composite> extends AsyncDesc
|
|||
}
|
||||
|
||||
export abstract class CompositeRegistry<T extends Composite> {
|
||||
private composits: CompositeDescriptor<T>[];
|
||||
private composites: CompositeDescriptor<T>[];
|
||||
|
||||
constructor() {
|
||||
this.composits = [];
|
||||
this.composites = [];
|
||||
}
|
||||
|
||||
protected registerComposite(descriptor: CompositeDescriptor<T>): void {
|
||||
|
@ -234,25 +230,25 @@ export abstract class CompositeRegistry<T extends Composite> {
|
|||
return;
|
||||
}
|
||||
|
||||
this.composits.push(descriptor);
|
||||
this.composites.push(descriptor);
|
||||
}
|
||||
|
||||
public getComposite(id: string): CompositeDescriptor<T> {
|
||||
return this.compositeById(id);
|
||||
}
|
||||
|
||||
protected getComposits(): CompositeDescriptor<T>[] {
|
||||
return this.composits.slice(0);
|
||||
protected getComposites(): CompositeDescriptor<T>[] {
|
||||
return this.composites.slice(0);
|
||||
}
|
||||
|
||||
protected setComposits(compositsToSet: CompositeDescriptor<T>[]): void {
|
||||
this.composits = compositsToSet;
|
||||
protected setComposites(compositesToSet: CompositeDescriptor<T>[]): void {
|
||||
this.composites = compositesToSet;
|
||||
}
|
||||
|
||||
private compositeById(id: string): CompositeDescriptor<T> {
|
||||
for (let i = 0; i < this.composits.length; i++) {
|
||||
if (this.composits[i].id === id) {
|
||||
return this.composits[i];
|
||||
for (let i = 0; i < this.composites.length; i++) {
|
||||
if (this.composites[i].id === id) {
|
||||
return this.composites[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -180,31 +180,23 @@ export function getIconClasses(modelService: IModelService, modeService: IModeSe
|
|||
}
|
||||
|
||||
if (path) {
|
||||
const basename = paths.basename(path);
|
||||
const dotSegments = basename.split('.');
|
||||
const basename = cssEscape(paths.basename(path).toLowerCase());
|
||||
|
||||
// Folders
|
||||
if (isFolder) {
|
||||
if (basename) {
|
||||
classes.push(`${basename.toLowerCase()}-name-folder-icon`);
|
||||
}
|
||||
classes.push(`${basename}-name-folder-icon`);
|
||||
}
|
||||
|
||||
// Files
|
||||
else {
|
||||
|
||||
// Name
|
||||
const name = dotSegments[0]; // file.txt => "file", .dockerfile => "", file.some.txt => "file"
|
||||
if (name) {
|
||||
classes.push(`${cssEscape(name.toLowerCase())}-name-file-icon`);
|
||||
}
|
||||
classes.push(`${basename}-name-file-icon`);
|
||||
|
||||
// Extension(s)
|
||||
const extensions = dotSegments.splice(1);
|
||||
if (extensions.length > 0) {
|
||||
for (let i = 0; i < extensions.length; i++) {
|
||||
classes.push(`${cssEscape(extensions.slice(i).join('.').toLowerCase())}-ext-file-icon`); // add each combination of all found extensions if more than one
|
||||
}
|
||||
const dotSegments = basename.split('.');
|
||||
for (let i = 1; i < dotSegments.length; i++) {
|
||||
classes.push(`${dotSegments.slice(i).join('.')}-ext-file-icon`); // add each combination of all found extensions if more than one
|
||||
}
|
||||
|
||||
// Configured Language
|
||||
|
@ -215,7 +207,6 @@ export function getIconClasses(modelService: IModelService, modeService: IModeSe
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ export class PanelRegistry extends CompositeRegistry<Panel> {
|
|||
* Returns an array of registered panels known to the platform.
|
||||
*/
|
||||
public getPanels(): PanelDescriptor[] {
|
||||
return this.getComposits();
|
||||
return this.getComposites();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -92,13 +92,14 @@ export abstract class TogglePanelAction extends Action {
|
|||
}
|
||||
|
||||
private isPanelShowing(): boolean {
|
||||
let panel = this.panelService.getActivePanel();
|
||||
const panel = this.panelService.getActivePanel();
|
||||
|
||||
return panel && panel.getId() === this.panelId;
|
||||
}
|
||||
|
||||
protected isPanelFocussed(): boolean {
|
||||
let activePanel = this.panelService.getActivePanel();
|
||||
let activeElement = document.activeElement;
|
||||
const activePanel = this.panelService.getActivePanel();
|
||||
const activeElement = document.activeElement;
|
||||
|
||||
return activePanel && activeElement && DOM.isAncestor(activeElement, (<Panel>activePanel).getContainer().getHTMLElement());
|
||||
}
|
||||
|
|
|
@ -49,45 +49,31 @@ export abstract class Part extends WorkbenchComponent {
|
|||
/**
|
||||
* Subclasses override to provide a title area implementation.
|
||||
*/
|
||||
public createTitleArea(parent: Builder): Builder {
|
||||
protected createTitleArea(parent: Builder): Builder {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the title area container.
|
||||
*/
|
||||
public getTitleArea(): Builder {
|
||||
return this.titleArea;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses override to provide a content area implementation.
|
||||
*/
|
||||
public createContentArea(parent: Builder): Builder {
|
||||
protected createContentArea(parent: Builder): Builder {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the content area container.
|
||||
*/
|
||||
public getContentArea(): Builder {
|
||||
protected getContentArea(): Builder {
|
||||
return this.contentArea;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses override to provide a status area implementation.
|
||||
*/
|
||||
public createStatusArea(parent: Builder): Builder {
|
||||
protected createStatusArea(parent: Builder): Builder {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the status area container.
|
||||
*/
|
||||
public getStatusArea(): Builder {
|
||||
return this.statusArea;
|
||||
}
|
||||
|
||||
/**
|
||||
* Layout title, content and status area in the given dimension.
|
||||
*/
|
||||
|
@ -138,7 +124,7 @@ export class PartLayout {
|
|||
}
|
||||
|
||||
public computeStyle(): void {
|
||||
let containerStyle = this.container.getComputedStyle();
|
||||
const containerStyle = this.container.getComputedStyle();
|
||||
this.containerStyle = {
|
||||
borderLeftWidth: parseInt(containerStyle.getPropertyValue('border-left-width'), 10),
|
||||
borderRightWidth: parseInt(containerStyle.getPropertyValue('border-right-width'), 10),
|
||||
|
@ -147,7 +133,7 @@ export class PartLayout {
|
|||
};
|
||||
|
||||
if (this.titleArea) {
|
||||
let titleStyle = this.titleArea.getComputedStyle();
|
||||
const titleStyle = this.titleArea.getComputedStyle();
|
||||
this.titleStyle = {
|
||||
display: titleStyle.getPropertyValue('display'),
|
||||
height: this.titleArea.getTotalSize().height
|
||||
|
@ -155,7 +141,7 @@ export class PartLayout {
|
|||
}
|
||||
|
||||
if (this.statusArea) {
|
||||
let statusStyle = this.statusArea.getComputedStyle();
|
||||
const statusStyle = this.statusArea.getComputedStyle();
|
||||
this.statusStyle = {
|
||||
display: statusStyle.getPropertyValue('display'),
|
||||
height: this.statusArea.getTotalSize().height
|
||||
|
@ -168,11 +154,11 @@ export class PartLayout {
|
|||
this.computeStyle();
|
||||
}
|
||||
|
||||
let width = dimension.width - (this.containerStyle.borderLeftWidth + this.containerStyle.borderRightWidth);
|
||||
let height = dimension.height - (this.containerStyle.borderTopWidth + this.containerStyle.borderBottomWidth);
|
||||
const width = dimension.width - (this.containerStyle.borderLeftWidth + this.containerStyle.borderRightWidth);
|
||||
const height = dimension.height - (this.containerStyle.borderTopWidth + this.containerStyle.borderBottomWidth);
|
||||
|
||||
// Return the applied sizes to title, content and status
|
||||
let sizes: Dimension[] = [];
|
||||
const sizes: Dimension[] = [];
|
||||
|
||||
// Title Size: Width (Fill), Height (Variable)
|
||||
let titleSize: Dimension;
|
||||
|
@ -192,7 +178,7 @@ export class PartLayout {
|
|||
}
|
||||
|
||||
// Content Size: Width (Fill), Height (Variable)
|
||||
let contentSize = new Dimension(width, height - titleSize.height - statusSize.height);
|
||||
const contentSize = new Dimension(width, height - titleSize.height - statusSize.height);
|
||||
|
||||
sizes.push(titleSize);
|
||||
sizes.push(contentSize);
|
||||
|
|
|
@ -41,7 +41,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
|||
private mapProgressServiceToComposite: { [compositeId: string]: IProgressService; };
|
||||
private activeComposite: Composite;
|
||||
private lastActiveCompositeId: string;
|
||||
private instantiatedComposits: Composite[];
|
||||
private instantiatedComposites: Composite[];
|
||||
private titleLabel: Builder;
|
||||
private toolBar: ToolBar;
|
||||
private compositeLoaderPromises: { [compositeId: string]: TPromise<Composite>; };
|
||||
|
@ -74,7 +74,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
|||
this.mapActionsBindingToComposite = {};
|
||||
this.mapProgressServiceToComposite = {};
|
||||
this.activeComposite = null;
|
||||
this.instantiatedComposits = [];
|
||||
this.instantiatedComposites = [];
|
||||
this.compositeLoaderPromises = {};
|
||||
}
|
||||
|
||||
|
@ -152,9 +152,9 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
|||
protected createComposite(id: string, isActive?: boolean): TPromise<Composite> {
|
||||
|
||||
// Check if composite is already created
|
||||
for (let i = 0; i < this.instantiatedComposits.length; i++) {
|
||||
if (this.instantiatedComposits[i].getId() === id) {
|
||||
return TPromise.as(this.instantiatedComposits[i]);
|
||||
for (let i = 0; i < this.instantiatedComposites.length; i++) {
|
||||
if (this.instantiatedComposites[i].getId() === id) {
|
||||
return TPromise.as(this.instantiatedComposites[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,7 +170,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
|||
this.mapProgressServiceToComposite[composite.getId()] = progressService;
|
||||
|
||||
// Remember as Instantiated
|
||||
this.instantiatedComposits.push(composite);
|
||||
this.instantiatedComposites.push(composite);
|
||||
|
||||
// Register to title area update events from the composite
|
||||
this.instantiatedCompositeListeners.push(composite.onTitleAreaUpdate(() => this.onTitleAreaUpdate(composite.getId())));
|
||||
|
@ -181,7 +181,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
|||
return composite;
|
||||
});
|
||||
|
||||
// Report progress for slow loading composits
|
||||
// Report progress for slow loading composites
|
||||
progressService.showWhile(loaderPromise, this.partService.isCreated() ? 800 : 3200 /* less ugly initial startup */);
|
||||
|
||||
// Add to Promise Cache until Loaded
|
||||
|
@ -207,7 +207,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
|||
|
||||
let createCompositePromise: TPromise<void>;
|
||||
|
||||
// Composits created for the first time
|
||||
// Composites created for the first time
|
||||
let compositeContainer = this.mapCompositeToCompositeContainer[composite.getId()];
|
||||
if (!compositeContainer) {
|
||||
|
||||
|
@ -228,7 +228,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
|||
createCompositePromise = TPromise.as(null);
|
||||
}
|
||||
|
||||
// Report progress for slow loading composits (but only if we did not create the composits before already)
|
||||
// Report progress for slow loading composites (but only if we did not create the composites before already)
|
||||
let progressService = this.mapProgressServiceToComposite[composite.getId()];
|
||||
if (progressService && !compositeContainer) {
|
||||
this.mapProgressServiceToComposite[composite.getId()].showWhile(createCompositePromise, this.partService.isCreated() ? 800 : 3200 /* less ugly initial startup */);
|
||||
|
@ -351,7 +351,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
|||
secondaryActions.push(...this.getSecondaryActions());
|
||||
|
||||
// From Contributions
|
||||
let actionBarRegistry = <IActionBarRegistry>Registry.as(Extensions.Actionbar);
|
||||
let actionBarRegistry = Registry.as<IActionBarRegistry>(Extensions.Actionbar);
|
||||
primaryActions.push(...actionBarRegistry.getActionBarActionsForContext(this.actionContributionScope, composite));
|
||||
secondaryActions.push(...actionBarRegistry.getSecondaryActionBarActionsForContext(this.actionContributionScope, composite));
|
||||
|
||||
|
@ -443,7 +443,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
|||
|
||||
// Check Registry
|
||||
if (!actionItem) {
|
||||
let actionBarRegistry = <IActionBarRegistry>Registry.as(Extensions.Actionbar);
|
||||
let actionBarRegistry = Registry.as<IActionBarRegistry>(Extensions.Actionbar);
|
||||
actionItem = actionBarRegistry.getActionItemForContext(this.actionContributionScope, ToolBarContext, action);
|
||||
}
|
||||
|
||||
|
@ -486,7 +486,7 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
|||
}
|
||||
|
||||
public shutdown(): void {
|
||||
this.instantiatedComposits.forEach(i => i.shutdown());
|
||||
this.instantiatedComposites.forEach(i => i.shutdown());
|
||||
|
||||
super.shutdown();
|
||||
}
|
||||
|
@ -496,11 +496,11 @@ export abstract class CompositePart<T extends Composite> extends Part {
|
|||
this.mapProgressServiceToComposite = null;
|
||||
this.mapActionsBindingToComposite = null;
|
||||
|
||||
for (let i = 0; i < this.instantiatedComposits.length; i++) {
|
||||
this.instantiatedComposits[i].dispose();
|
||||
for (let i = 0; i < this.instantiatedComposites.length; i++) {
|
||||
this.instantiatedComposites[i].dispose();
|
||||
}
|
||||
|
||||
this.instantiatedComposits = [];
|
||||
this.instantiatedComposites = [];
|
||||
|
||||
this.instantiatedCompositeListeners = dispose(this.instantiatedCompositeListeners);
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
|||
* This class is only intended to be subclassed and not instantiated.
|
||||
*/
|
||||
export abstract class BaseEditor extends Panel implements IEditor {
|
||||
private _input: EditorInput;
|
||||
protected _input: EditorInput;
|
||||
private _options: EditorOptions;
|
||||
private _position: Position;
|
||||
|
||||
|
@ -42,24 +42,10 @@ export abstract class BaseEditor extends Panel implements IEditor {
|
|||
return this._input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current input of this editor or null if none.
|
||||
*/
|
||||
public getInput(): EditorInput {
|
||||
return this._input || null;
|
||||
}
|
||||
|
||||
public get options(): EditorOptions {
|
||||
return this._options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current options of this editor or null if none.
|
||||
*/
|
||||
public getOptions(): EditorOptions {
|
||||
return this._options || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: Clients should not call this method, the workbench calls this
|
||||
* method. Calling it otherwise may result in unexpected behavior.
|
||||
|
|
|
@ -56,7 +56,7 @@ export class BinaryResourceDiffEditor extends BaseEditor implements IVerticalSas
|
|||
}
|
||||
|
||||
public getTitle(): string {
|
||||
return this.getInput() ? this.getInput().getName() : nls.localize('binaryDiffEditor', "Binary Diff Viewer");
|
||||
return this.input ? this.input.getName() : nls.localize('binaryDiffEditor', "Binary Diff Viewer");
|
||||
}
|
||||
|
||||
public createEditor(parent: Builder): void {
|
||||
|
@ -92,7 +92,7 @@ export class BinaryResourceDiffEditor extends BaseEditor implements IVerticalSas
|
|||
}
|
||||
|
||||
public setInput(input: EditorInput, options?: EditorOptions): TPromise<void> {
|
||||
const oldInput = this.getInput();
|
||||
const oldInput = this.input;
|
||||
super.setInput(input, options);
|
||||
|
||||
// Detect options
|
||||
|
@ -112,7 +112,7 @@ export class BinaryResourceDiffEditor extends BaseEditor implements IVerticalSas
|
|||
}
|
||||
|
||||
// Assert that the current input is still the one we expect. This prevents a race condition when loading a diff takes long and another input was set meanwhile
|
||||
if (!this.getInput() || this.getInput() !== input) {
|
||||
if (!this.input || this.input !== input) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor {
|
|||
}
|
||||
|
||||
public getTitle(): string {
|
||||
return this.getInput() ? this.getInput().getName() : nls.localize('binaryEditor', "Binary Viewer");
|
||||
return this.input ? this.input.getName() : nls.localize('binaryEditor', "Binary Viewer");
|
||||
}
|
||||
|
||||
public createEditor(parent: Builder): void {
|
||||
|
@ -58,7 +58,7 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor {
|
|||
}
|
||||
|
||||
public setInput(input: EditorInput, options?: EditorOptions): TPromise<void> {
|
||||
const oldInput = this.getInput();
|
||||
const oldInput = this.input;
|
||||
super.setInput(input, options);
|
||||
|
||||
// Detect options
|
||||
|
@ -78,7 +78,7 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor {
|
|||
}
|
||||
|
||||
// Assert that the current input is still the one we expect. This prevents a race condition when loading takes long and another input was set meanwhile
|
||||
if (!this.getInput() || this.getInput() !== input) {
|
||||
if (!this.input || this.input !== input) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ import { StatusbarItemDescriptor, StatusbarAlignment, IStatusbarRegistry, Extens
|
|||
import { EditorDescriptor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
import { EditorInput, IEditorRegistry, Extensions as EditorExtensions, IEditorInputFactory, SideBySideEditorInput } from 'vs/workbench/common/editor';
|
||||
import { StringEditorInput } from 'vs/workbench/common/editor/stringEditorInput';
|
||||
import { StringEditor } from 'vs/workbench/browser/parts/editor/stringEditor';
|
||||
import { TextResourceEditor } from 'vs/workbench/browser/parts/editor/textResourceEditor';
|
||||
import { SideBySideEditor } from 'vs/workbench/browser/parts/editor/sideBySideEditor';
|
||||
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
|
||||
import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput';
|
||||
|
@ -44,10 +44,10 @@ import * as editorCommands from 'vs/workbench/browser/parts/editor/editorCommand
|
|||
// Register String Editor
|
||||
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
|
||||
new EditorDescriptor(
|
||||
StringEditor.ID,
|
||||
TextResourceEditor.ID,
|
||||
nls.localize('textEditor', "Text Editor"),
|
||||
'vs/workbench/browser/parts/editor/stringEditor',
|
||||
'StringEditor'
|
||||
'vs/workbench/browser/parts/editor/textResourceEditor',
|
||||
'TextResourceEditor'
|
||||
),
|
||||
[
|
||||
new SyncDescriptor(StringEditorInput),
|
||||
|
|
|
@ -8,11 +8,11 @@ import * as types from 'vs/base/common/types';
|
|||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService';
|
||||
import { ActiveEditorMoveArguments, ActiveEditorMovePositioning, ActiveEditorMovePositioningBy, EditorCommands } from 'vs/workbench/common/editor';
|
||||
import { ActiveEditorMoveArguments, ActiveEditorMovePositioning, ActiveEditorMovePositioningBy, EditorCommands, TextCompareEditorVisible } from 'vs/workbench/common/editor';
|
||||
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IEditor, Position, POSITIONS } from 'vs/platform/editor/common/editor';
|
||||
import { EditorContextKeys } from 'vs/editor/common/editorCommon';
|
||||
import { TextCompareEditorVisible, TextDiffEditor } from 'vs/workbench/browser/parts/editor/textDiffEditor';
|
||||
import { TextDiffEditor } from 'vs/workbench/browser/parts/editor/textDiffEditor';
|
||||
import { EditorStacksModel } from 'vs/workbench/common/editor/editorStacksModel';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IMessageService, Severity, CloseAction } from 'vs/platform/message/common/message';
|
||||
|
@ -210,7 +210,6 @@ function handleCommandDeprecations(): void {
|
|||
'workbench.files.action.reopenClosedFile': 'workbench.action.reopenClosedEditor',
|
||||
'workbench.files.action.workingFilesPicker': 'workbench.action.showAllEditors',
|
||||
'workbench.action.cycleEditor': 'workbench.action.navigateEditorGroups',
|
||||
'workbench.action.terminal.focus': 'workbench.action.focusPanel',
|
||||
'workbench.action.showEditorsInLeftGroup': 'workbench.action.showEditorsInFirstGroup',
|
||||
'workbench.action.showEditorsInCenterGroup': 'workbench.action.showEditorsInSecondGroup',
|
||||
'workbench.action.showEditorsInRightGroup': 'workbench.action.showEditorsInThirdGroup',
|
||||
|
|
|
@ -22,7 +22,6 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi
|
|||
import { Position, POSITIONS } from 'vs/platform/editor/common/editor';
|
||||
import { IEditorGroupService, ITabOptions, GroupArrangement, GroupOrientation } from 'vs/workbench/services/group/common/groupService';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
|
@ -139,7 +138,6 @@ export class EditorGroupsControl implements IEditorGroupsControl, IVerticalSashL
|
|||
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
|
||||
@IEditorGroupService private editorGroupService: IEditorGroupService,
|
||||
@ITelemetryService private telemetryService: ITelemetryService,
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@IContextKeyService private contextKeyService: IContextKeyService,
|
||||
@IExtensionService private extensionService: IExtensionService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue