Merge branch 'master' into joh/ftp

This commit is contained in:
Johannes Rieken
2017-09-19 15:40:08 +02:00
196 changed files with 3960 additions and 2036 deletions
+35 -35
View File
@@ -6,12 +6,12 @@
"type": "node",
"request": "launch",
"name": "Gulp Build",
"program": "${workspaceRoot}/node_modules/gulp/bin/gulp.js",
"program": "${workspaceFolder}/node_modules/gulp/bin/gulp.js",
"stopOnEntry": true,
"args": [
"watch-extension:json-client"
],
"cwd": "${workspaceRoot}"
"cwd": "${workspaceFolder}"
},
{
"type": "node",
@@ -21,7 +21,7 @@
"port": 5870,
"restart": true,
"outFiles": [
"${workspaceRoot}/out/**/*.js"
"${workspaceFolder}/out/**/*.js"
]
},
{
@@ -31,7 +31,7 @@
"protocol": "inspector",
"port": 5871,
"outFiles": [
"${workspaceRoot}/out/**/*.js"
"${workspaceFolder}/out/**/*.js"
]
},
{
@@ -41,7 +41,7 @@
"name": "Attach to Search Process",
"port": 5876,
"outFiles": [
"${workspaceRoot}/out/**/*.js"
"${workspaceFolder}/out/**/*.js"
]
},
{
@@ -51,7 +51,7 @@
"protocol": "inspector",
"port": 5874,
"outFiles": [
"${workspaceRoot}/out/**/*.js"
"${workspaceFolder}/out/**/*.js"
]
},
{
@@ -61,7 +61,7 @@
"protocol": "inspector",
"port": 5875,
"outFiles": [
"${workspaceRoot}/out/**/*.js"
"${workspaceFolder}/out/**/*.js"
]
},
{
@@ -70,12 +70,12 @@
"name": "VS Code Emmet Tests",
"runtimeExecutable": "${execPath}",
"args": [
"${workspaceRoot}/extensions/emmet/test-fixtures",
"--extensionDevelopmentPath=${workspaceRoot}/extensions/emmet",
"--extensionTestsPath=${workspaceRoot}/extensions/emmet/out/test"
"${workspaceFolder}/extensions/emmet/test-fixtures",
"--extensionDevelopmentPath=${workspaceFolder}/extensions/emmet",
"--extensionTestsPath=${workspaceFolder}/extensions/emmet/out/test"
],
"outFiles": [
"${workspaceRoot}/out/**/*.js"
"${workspaceFolder}/out/**/*.js"
]
},
{
@@ -84,12 +84,12 @@
"name": "VS Code API Tests",
"runtimeExecutable": "${execPath}",
"args": [
"${workspaceRoot}/extensions/vscode-api-tests/testWorkspace",
"--extensionDevelopmentPath=${workspaceRoot}/extensions/vscode-api-tests",
"--extensionTestsPath=${workspaceRoot}/extensions/vscode-api-tests/out"
"${workspaceFolder}/extensions/vscode-api-tests/testWorkspace",
"--extensionDevelopmentPath=${workspaceFolder}/extensions/vscode-api-tests",
"--extensionTestsPath=${workspaceFolder}/extensions/vscode-api-tests/out"
],
"outFiles": [
"${workspaceRoot}/out/**/*.js"
"${workspaceFolder}/out/**/*.js"
]
},
{
@@ -98,12 +98,12 @@
"name": "VS Code Tokenizer Tests",
"runtimeExecutable": "${execPath}",
"args": [
"${workspaceRoot}/extensions/vscode-colorize-tests/test",
"--extensionDevelopmentPath=${workspaceRoot}/extensions/vscode-colorize-tests",
"--extensionTestsPath=${workspaceRoot}/extensions/vscode-colorize-tests/out"
"${workspaceFolder}/extensions/vscode-colorize-tests/test",
"--extensionDevelopmentPath=${workspaceFolder}/extensions/vscode-colorize-tests",
"--extensionTestsPath=${workspaceFolder}/extensions/vscode-colorize-tests/out"
],
"outFiles": [
"${workspaceRoot}/out/**/*.js"
"${workspaceFolder}/out/**/*.js"
]
},
{
@@ -117,30 +117,30 @@
"request": "launch",
"name": "Launch VS Code",
"windows": {
"runtimeExecutable": "${workspaceRoot}/scripts/code.bat"
"runtimeExecutable": "${workspaceFolder}/scripts/code.bat"
},
"osx": {
"runtimeExecutable": "${workspaceRoot}/scripts/code.sh"
"runtimeExecutable": "${workspaceFolder}/scripts/code.sh"
},
"linux": {
"runtimeExecutable": "${workspaceRoot}/scripts/code.sh"
"runtimeExecutable": "${workspaceFolder}/scripts/code.sh"
},
"urlFilter": "*index.html*",
"runtimeArgs": [
"--inspect=5875"
],
"webRoot": "${workspaceRoot}"
"webRoot": "${workspaceFolder}"
},
{
"type": "node",
"request": "launch",
"name": "Git Unit Tests",
"protocol": "inspector",
"program": "${workspaceRoot}/extensions/git/node_modules/mocha/bin/_mocha",
"program": "${workspaceFolder}/extensions/git/node_modules/mocha/bin/_mocha",
"stopOnEntry": false,
"cwd": "${workspaceRoot}/extensions/git",
"cwd": "${workspaceFolder}/extensions/git",
"outFiles": [
"${workspaceRoot}/extensions/git/out/**/*.js"
"${workspaceFolder}/extensions/git/out/**/*.js"
]
},
{
@@ -148,38 +148,38 @@
"request": "launch",
"name": "Unit Tests",
"protocol": "inspector",
"program": "${workspaceRoot}/node_modules/mocha/bin/_mocha",
"runtimeExecutable": "${workspaceRoot}/.build/electron/Code - OSS.app/Contents/MacOS/Electron",
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
"runtimeExecutable": "${workspaceFolder}/.build/electron/Code - OSS.app/Contents/MacOS/Electron",
"windows": {
"runtimeExecutable": "${workspaceRoot}/.build/electron/Code - OSS.exe"
"runtimeExecutable": "${workspaceFolder}/.build/electron/Code - OSS.exe"
},
"linux": {
"runtimeExecutable": "${workspaceRoot}/.build/electron/code-oss"
"runtimeExecutable": "${workspaceFolder}/.build/electron/code-oss"
},
"stopOnEntry": false,
"args": [
"--timeout",
"2000"
],
"cwd": "${workspaceRoot}",
"cwd": "${workspaceFolder}",
"env": {
"ELECTRON_RUN_AS_NODE": "true"
},
"outFiles": [
"${workspaceRoot}/out/**/*.js"
"${workspaceFolder}/out/**/*.js"
]
},
{
"type": "node",
"request": "launch",
"name": "Launch Smoke Test",
"program": "${workspaceRoot}/test/smoke/out/main.js",
"cwd": "${workspaceRoot}/test/smoke",
"program": "${workspaceFolder}/test/smoke/out/main.js",
"cwd": "${workspaceFolder}/test/smoke",
"timeout": 240000,
"port": 9999,
"args": [
"-l",
"${workspaceRoot}/.build/electron/Code - OSS.app/Contents/MacOS/Electron"
"${workspaceFolder}/.build/electron/Code - OSS.app/Contents/MacOS/Electron"
],
"outFiles": [
"${cwd}/out/**/*.js"
+2 -2
View File
@@ -27,9 +27,9 @@
"lcov.watch": [
{
"pattern": "**/*.test.js",
"command": "${workspaceRoot}/scripts/test.sh --coverage --run ${file}",
"command": "${workspaceFolder}/scripts/test.sh --coverage --run ${file}",
"windows": {
"command": "${workspaceRoot}\\scripts\\test.bat --coverage --run ${file}"
"command": "${workspaceFolder}\\scripts\\test.bat --coverage --run ${file}"
}
}
]
+62 -1
View File
@@ -7,6 +7,8 @@
const gulp = require('gulp');
const fs = require('fs');
const os = require('os');
const cp = require('child_process');
const path = require('path');
const es = require('event-stream');
const azure = require('gulp-azure-storage');
@@ -43,7 +45,7 @@ const nodeModules = ['electron', 'original-fs']
// Build
const builtInExtensions = [
{ name: 'ms-vscode.node-debug', version: '1.17.6' },
{ name: 'ms-vscode.node-debug', version: '1.17.8' },
{ name: 'ms-vscode.node-debug2', version: '1.17.1' }
];
@@ -443,3 +445,62 @@ gulp.task('upload-vscode-sourcemaps', ['minify-vscode'], () => {
prefix: commit + '/'
}));
});
const allConfigDetailsPath = path.join(os.tmpdir(), 'configuration.json');
gulp.task('upload-vscode-configuration', ['generate-vscode-configuration'], () => {
if (!fs.existsSync(allConfigDetailsPath)) {
console.error(`configuration file at ${allConfigDetailsPath} does not exist`);
return;
}
return gulp.src(allConfigDetailsPath)
.pipe(azure.upload({
account: process.env.AZURE_STORAGE_ACCOUNT,
key: process.env.AZURE_STORAGE_ACCESS_KEY,
container: 'configuration',
prefix: `${versionStringToNumber(packageJson.version)}/${commit}/`
}));
});
function versionStringToNumber(versionStr) {
const semverRegex = /(\d+)\.(\d+)\.(\d+)/;
const match = versionStr.match(semverRegex);
if (!match) {
return 0;
}
return parseInt(match[1], 10) * 10000 + parseInt(match[2], 10) * 100 + parseInt(match[3], 10);
}
gulp.task('generate-vscode-configuration', () => {
return new Promise((resolve, reject) => {
const buildDir = process.env['AGENT_BUILDDIRECTORY'];
if (!buildDir) {
return reject(new Error('$AGENT_BUILDDIRECTORY not set'));
}
const appPath = path.join(buildDir, 'VSCode-darwin/Visual\\ Studio\\ Code\\ -\\ Insiders.app/Contents/Resources/app/bin/code');
const codeProc = cp.exec(`${appPath} --export-default-configuration='${allConfigDetailsPath}' --wait`);
const timer = setTimeout(() => {
codeProc.kill();
reject(new Error('export-default-configuration process timed out'));
}, 10 * 1000);
codeProc.stdout.on('data', d => console.log(d.toString()));
codeProc.stderr.on('data', d => console.log(d.toString()));
codeProc.on('exit', () => {
clearTimeout(timer);
resolve();
});
codeProc.on('error', err => {
clearTimeout(timer);
reject(err);
});
}).catch(e => {
// Don't fail the build
console.error(e.toString());
});
});
+5 -3
View File
@@ -22,7 +22,7 @@ function getOptions(urlString) {
headers: {
'User-Agent': 'NodeJS'
}
}
};
}
function download(url, redirectCount) {
@@ -100,7 +100,9 @@ exports.update = function (repoId, repoPath, dest, modifyGrammar) {
result.version = 'https://github.com/' + repoId + '/commit/' + info.commitSha;
}
for (let key in grammar) {
result[key] = grammar[key];
if (!result.hasOwnProperty(key)) {
result[key] = grammar[key];
}
}
try {
@@ -116,7 +118,7 @@ exports.update = function (repoId, repoPath, dest, modifyGrammar) {
});
}, console.error);
}
};
if (path.basename(process.argv[1]) === 'update-grammar.js') {
for (var i = 3; i < process.argv.length; i += 2) {
+3
View File
@@ -39,3 +39,6 @@ step "Run integration tests" \
step "Publish release" \
./build/tfs/darwin/release.sh
step "Generate and upload configuration.json" \
npm run gulp -- upload-vscode-configuration
@@ -27,8 +27,8 @@ export function activate(context): void {
//settings.json suggestions
context.subscriptions.push(registerSettingsCompletions());
//extensions.json suggestions
context.subscriptions.push(registerExtensionsCompletions());
//extensions suggestions
context.subscriptions.push(...registerExtensionsCompletions());
// launch.json decorations
context.subscriptions.push(vscode.window.onDidChangeActiveTextEditor(editor => updateLaunchJsonDecorations(editor), null, context.subscriptions));
@@ -67,43 +67,69 @@ function registerSettingsCompletions(): vscode.Disposable {
});
}
function registerExtensionsCompletions(): vscode.Disposable {
interface IExtensionsContent {
recommendations: string[];
}
function registerExtensionsCompletions(): vscode.Disposable[] {
return [registerExtensionsCompletionsInExtensionsDocument(), registerExtensionsCompletionsInWorkspaceConfigurationDocument()];
}
function registerExtensionsCompletionsInExtensionsDocument(): vscode.Disposable {
return vscode.languages.registerCompletionItemProvider({ pattern: '**/extensions.json' }, {
provideCompletionItems(document, position, token) {
const location = getLocation(document.getText(), document.offsetAt(position));
const range = document.getWordRangeAtPosition(position) || new vscode.Range(position, position);
if (location.path[0] === 'recommendations') {
const config = parse(document.getText());
const alreadyEnteredExtensions = config && config.recommendations || [];
if (Array.isArray(alreadyEnteredExtensions)) {
const knownExtensionProposals = vscode.extensions.all.filter(e =>
!(e.id.startsWith('vscode.')
|| e.id === 'Microsoft.vscode-markdown'
|| alreadyEnteredExtensions.indexOf(e.id) > -1));
if (knownExtensionProposals.length) {
return knownExtensionProposals.map(e => {
const item = new vscode.CompletionItem(e.id);
const insertText = `"${e.id}"`;
item.kind = vscode.CompletionItemKind.Value;
item.insertText = insertText;
item.range = range;
item.filterText = insertText;
return item;
});
} else {
const example = new vscode.CompletionItem(localize('exampleExtension', "Example"));
example.insertText = '"vscode.csharp"';
example.kind = vscode.CompletionItemKind.Value;
example.range = range;
return [example];
}
}
const extensionsContent = <IExtensionsContent>parse(document.getText());
return provideInstalledExtensionProposals(extensionsContent, range);
}
return [];
}
});
}
function registerExtensionsCompletionsInWorkspaceConfigurationDocument(): vscode.Disposable {
return vscode.languages.registerCompletionItemProvider({ pattern: '**/*.code-workspace' }, {
provideCompletionItems(document, position, token) {
const location = getLocation(document.getText(), document.offsetAt(position));
const range = document.getWordRangeAtPosition(position) || new vscode.Range(position, position);
if (location.path[0] === 'extensions' && location.path[1] === 'recommendations') {
const extensionsContent = <IExtensionsContent>parse(document.getText())['extensions'];
return provideInstalledExtensionProposals(extensionsContent, range);
}
return [];
}
});
}
function provideInstalledExtensionProposals(extensionsContent: IExtensionsContent, range: vscode.Range): vscode.ProviderResult<vscode.CompletionItem[] | vscode.CompletionList> {
const alreadyEnteredExtensions = extensionsContent && extensionsContent.recommendations || [];
if (Array.isArray(alreadyEnteredExtensions)) {
const knownExtensionProposals = vscode.extensions.all.filter(e =>
!(e.id.startsWith('vscode.')
|| e.id === 'Microsoft.vscode-markdown'
|| alreadyEnteredExtensions.indexOf(e.id) > -1));
if (knownExtensionProposals.length) {
return knownExtensionProposals.map(e => {
const item = new vscode.CompletionItem(e.id);
const insertText = `"${e.id}"`;
item.kind = vscode.CompletionItemKind.Value;
item.insertText = insertText;
item.range = range;
item.filterText = insertText;
return item;
});
} else {
const example = new vscode.CompletionItem(localize('exampleExtension', "Example"));
example.insertText = '"vscode.csharp"';
example.kind = vscode.CompletionItemKind.Value;
example.range = range;
return [example];
}
}
}
function newSimpleCompletionItem(label: string, range: vscode.Range, description?: string, insertText?: string): vscode.CompletionItem {
const item = new vscode.CompletionItem(label);
item.kind = vscode.CompletionItemKind.Value;
+5 -5
View File
@@ -7,11 +7,11 @@
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceRoot}"
"--extensionDevelopmentPath=${workspaceFolder}"
],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": ["${workspaceRoot}/client/out/**/*.js"],
"outFiles": ["${workspaceFolder}/client/out/**/*.js"],
"preLaunchTask": "npm"
},
{
@@ -19,10 +19,10 @@
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/client/out/test" ],
"args": ["--extensionDevelopmentPath=${workspaceFolder}", "--extensionTestsPath=${workspaceFolder}/client/out/test" ],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": ["${workspaceRoot}/client/out/test/**/*.js"],
"outFiles": ["${workspaceFolder}/client/out/test/**/*.js"],
"preLaunchTask": "npm"
},
{
@@ -32,7 +32,7 @@
"protocol": "legacy",
"port": 6004,
"sourceMaps": true,
"outFiles": ["${workspaceRoot}/server/out/**/*.js"]
"outFiles": ["${workspaceFolder}/server/out/**/*.js"]
}
]
}
+1 -1
View File
@@ -1,5 +1,5 @@
// Available variables which can be used inside of strings.
// ${workspaceRoot}: the root folder of the team
// ${workspaceFolder}: the root folder of the team
// ${file}: the current opened file
// ${fileBasename}: the current opened file's basename
// ${fileDirname}: the current opened file's dirname
+31 -24
View File
@@ -6,7 +6,7 @@
import * as path from 'path';
import { languages, window, commands, ExtensionContext, TextDocument, ColorRange, ColorFormat, Color } from 'vscode';
import { languages, window, commands, ExtensionContext, TextDocument, ColorInformation, ColorPresentation, Color, TextEdit as CodeTextEdit } from 'vscode';
import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind, TextEdit } from 'vscode-languageclient';
import { ConfigurationFeature } from 'vscode-languageclient/lib/proposed';
@@ -60,38 +60,45 @@ export function activate(context: ExtensionContext) {
client.onReady().then(_ => {
// register color provider
context.subscriptions.push(languages.registerColorProvider(documentSelector, {
provideDocumentColors(document: TextDocument): Thenable<ColorRange[]> {
provideDocumentColors(document: TextDocument): Thenable<ColorInformation[]> {
let params = client.code2ProtocolConverter.asDocumentSymbolParams(document);
return client.sendRequest(DocumentColorRequest.type, params).then(symbols => {
return symbols.map(symbol => {
let range = client.protocol2CodeConverter.asRange(symbol.range);
let color = new Color(symbol.color.red * 255, symbol.color.green * 255, symbol.color.blue * 255, symbol.color.alpha);
return new ColorRange(range, color);
return new ColorInformation(range, color);
});
});
},
resolveDocumentColor(color: Color, colorFormat: ColorFormat): Thenable<string> | string {
switch (colorFormat) {
case ColorFormat.RGB:
if (color.alpha === 1) {
return `rgb(${Math.round(color.red * 255)}, ${Math.round(color.green * 255)}, ${Math.round(color.blue * 255)})`;
} else {
return `rgba(${Math.round(color.red * 255)}, ${Math.round(color.green * 255)}, ${Math.round(color.blue * 255)}, ${color.alpha})`;
}
case ColorFormat.HEX:
if (color.alpha === 1) {
return `#${_toTwoDigitHex(Math.round(color.red * 255))}${_toTwoDigitHex(Math.round(color.green * 255))}${_toTwoDigitHex(Math.round(color.blue * 255))}`;
} else {
return `#${_toTwoDigitHex(Math.round(color.red * 255))}${_toTwoDigitHex(Math.round(color.green * 255))}${_toTwoDigitHex(Math.round(color.blue * 255))}${_toTwoDigitHex(Math.round(color.alpha * 255))}`;
}
case ColorFormat.HSL:
const hsl = convert.rgb.hsl(Math.round(color.red * 255), Math.round(color.green * 255), Math.round(color.blue * 255));
if (color.alpha === 1) {
return `hsl(${hsl[0]}, ${hsl[1]}%, ${hsl[2]}%)`;
} else {
return `hsla(${hsl[0]}, ${hsl[1]}%, ${hsl[2]}%, ${color.alpha})`;
}
provideColorPresentations(colorInfo: ColorInformation): ColorPresentation[] | Thenable<ColorPresentation[]> {
let result: ColorPresentation[] = [];
let color = colorInfo.color;
let label;
if (color.alpha === 1) {
label = `rgb(${Math.round(color.red * 255)}, ${Math.round(color.green * 255)}, ${Math.round(color.blue * 255)})`;
} else {
label = `rgba(${Math.round(color.red * 255)}, ${Math.round(color.green * 255)}, ${Math.round(color.blue * 255)}, ${color.alpha})`;
}
result.push({ label: label, textEdit: new CodeTextEdit(colorInfo.range, label) });
if (color.alpha === 1) {
label = `#${_toTwoDigitHex(Math.round(color.red * 255))}${_toTwoDigitHex(Math.round(color.green * 255))}${_toTwoDigitHex(Math.round(color.blue * 255))}`;
} else {
label = `#${_toTwoDigitHex(Math.round(color.red * 255))}${_toTwoDigitHex(Math.round(color.green * 255))}${_toTwoDigitHex(Math.round(color.blue * 255))}${_toTwoDigitHex(Math.round(color.alpha * 255))}`;
}
result.push({ label: label, textEdit: new CodeTextEdit(colorInfo.range, label) });
const hsl = convert.rgb.hsl(Math.round(color.red * 255), Math.round(color.green * 255), Math.round(color.blue * 255));
if (color.alpha === 1) {
label = `hsl(${hsl[0]}, ${hsl[1]}%, ${hsl[2]}%)`;
} else {
label = `hsla(${hsl[0]}, ${hsl[1]}%, ${hsl[2]}%, ${color.alpha})`;
}
result.push({ label: label, textEdit: new CodeTextEdit(colorInfo.range, label) });
return result;
}
}));
});
+4 -4
View File
@@ -8,25 +8,25 @@
"request": "attach",
"port": 6004,
"sourceMaps": true,
"outDir": "${workspaceRoot}/out"
"outDir": "${workspaceFolder}/out"
},
{
"name": "Unit Tests",
"type": "node",
"request": "launch",
"program": "${workspaceRoot}/../../../node_modules/mocha/bin/_mocha",
"program": "${workspaceFolder}/../../../node_modules/mocha/bin/_mocha",
"stopOnEntry": false,
"args": [
"--timeout",
"999999",
"--colors"
],
"cwd": "${workspaceRoot}",
"cwd": "${workspaceFolder}",
"runtimeExecutable": null,
"runtimeArgs": [],
"env": {},
"sourceMaps": true,
"outDir": "${workspaceRoot}/out"
"outDir": "${workspaceFolder}/out"
}
]
}
+2 -2
View File
@@ -10,11 +10,11 @@
"name": "Launch Extension",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceRoot}"
"--extensionDevelopmentPath=${workspaceFolder}"
],
"sourceMaps": true,
"outFiles": [
"${workspaceRoot}/out/**/*.js"
"${workspaceFolder}/out/**/*.js"
]
}
]
+12 -4
View File
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { Node, HtmlNode, Rule } from 'EmmetNode';
import { Node, HtmlNode, Rule, Property } from 'EmmetNode';
import { getNode, getInnerRange, getMappingForIncludedLanguages, parseDocument, validate, getEmmetConfiguration } from './util';
import { getExpandOptions, extractAbbreviation, extractAbbreviationFromText, isStyleSheet, isAbbreviationValid, getEmmetMode, expandAbbreviation } from 'vscode-emmet-helper';
@@ -149,8 +149,8 @@ export function expandEmmetAbbreviation(args): Thenable<boolean> {
return;
}
let currentNode = getNode(rootNode, position);
if (!isValidLocationForEmmetAbbreviation(currentNode, syntax, position)) {
let currentNode = getNode(rootNode, position, true);
if (!isValidLocationForEmmetAbbreviation(currentNode, syntax, position, abbreviation)) {
return;
}
@@ -182,7 +182,7 @@ function fallbackTab(): Thenable<boolean> {
* @param syntax syntax of the abbreviation
* @param position position to validate
*/
export function isValidLocationForEmmetAbbreviation(currentNode: Node, syntax: string, position: vscode.Position): boolean {
export function isValidLocationForEmmetAbbreviation(currentNode: Node, syntax: string, position: vscode.Position, abbreviation: string): boolean {
// Continue validation only if the file was parse-able and the currentNode has been found
if (!currentNode) {
return true;
@@ -190,6 +190,14 @@ export function isValidLocationForEmmetAbbreviation(currentNode: Node, syntax: s
if (isStyleSheet(syntax)) {
// CSS Emmet snippets are for property-value or in case of colors, just value
if (currentNode.type === 'property' && (<Property>currentNode).value) {
if (position.isBefore((<Property>currentNode).valueToken.start)) {
return false;
}
return /^#\d+$/.test(abbreviation);
}
// If current node is a rule or at-rule, then perform additional checks to ensure
// emmet suggestions are not provided in the rule selector
if (currentNode.type !== 'rule' && currentNode.type !== 'at-rule') {
@@ -95,7 +95,7 @@ export class DefaultCompletionItemProvider implements vscode.CompletionItemProvi
return;
}
let currentNode = getNode(rootNode, position);
let currentNode = getNode(rootNode, position, true);
if (!isStyleSheet(syntax)) {
const currentHtmlNode = <HtmlNode>currentNode;
@@ -111,7 +111,7 @@ export class DefaultCompletionItemProvider implements vscode.CompletionItemProvi
}
}
if (!isValidLocationForEmmetAbbreviation(currentNode, syntax, position)) {
if (!isValidLocationForEmmetAbbreviation(currentNode, syntax, position, document.getText(document.getWordRangeAtPosition(position)))) {
return;
}
return syntax;
@@ -211,6 +211,29 @@ suite('Tests for Expand Abbreviations (CSS)', () => {
});
});
});
test('Invalid locations for abbreviations in css', () => {
const scssContentsNoExpand = `
m10
.boo {
margin: 10px;
.hoo {
background:
}
}
`
return withRandomFileEditor(scssContentsNoExpand, 'scss', (editor, doc) => {
editor.selections = [
new Selection(1, 3, 1, 3), // outside rule
new Selection(5, 15, 5, 15) // in the value part of property value
];
return expandEmmetAbbreviation(null).then(() => {
assert.equal(editor.document.getText(), scssContentsNoExpand);
return Promise.resolve();
});
});
});
});
suite('Tests for Wrap with Abbreviations', () => {
+5 -5
View File
@@ -7,11 +7,11 @@
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceRoot}"
"--extensionDevelopmentPath=${workspaceFolder}"
],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": ["${workspaceRoot}/client/out/**/*.js"],
"outFiles": ["${workspaceFolder}/client/out/**/*.js"],
"preLaunchTask": "npm"
},
{
@@ -19,10 +19,10 @@
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/client/out/test" ],
"args": ["--extensionDevelopmentPath=${workspaceFolder}", "--extensionTestsPath=${workspaceFolder}/client/out/test" ],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": ["${workspaceRoot}/client/out/test/**/*.js"],
"outFiles": ["${workspaceFolder}/client/out/test/**/*.js"],
"preLaunchTask": "npm"
},
{
@@ -32,7 +32,7 @@
"port": 6004,
"protocol": "legacy",
"sourceMaps": true,
"outFiles": ["${workspaceRoot}/server/out/**/*.js"]
"outFiles": ["${workspaceFolder}/server/out/**/*.js"]
}
]
}
+1 -1
View File
@@ -1,5 +1,5 @@
// Available variables which can be used inside of strings.
// ${workspaceRoot}: the root folder of the team
// ${workspaceFolder}: the root folder of the team
// ${file}: the current opened file
// ${fileBasename}: the current opened file's basename
// ${fileDirname}: the current opened file's dirname
+31 -24
View File
@@ -6,7 +6,7 @@
import * as path from 'path';
import { languages, ExtensionContext, IndentAction, Position, TextDocument, Color, ColorRange, ColorFormat } from 'vscode';
import { languages, ExtensionContext, IndentAction, Position, TextDocument, Color, ColorInformation, ColorPresentation, TextEdit } from 'vscode';
import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind, RequestType, TextDocumentPositionParams } from 'vscode-languageclient';
import { EMPTY_ELEMENTS } from './htmlEmptyTagsShared';
import { activateTagClosing } from './tagClosing';
@@ -77,38 +77,45 @@ export function activate(context: ExtensionContext) {
toDispose.push(disposable);
client.onReady().then(() => {
disposable = languages.registerColorProvider(documentSelector, {
provideDocumentColors(document: TextDocument): Thenable<ColorRange[]> {
provideDocumentColors(document: TextDocument): Thenable<ColorInformation[]> {
let params = client.code2ProtocolConverter.asDocumentSymbolParams(document);
return client.sendRequest(DocumentColorRequest.type, params).then(symbols => {
return symbols.map(symbol => {
let range = client.protocol2CodeConverter.asRange(symbol.range);
let color = new Color(symbol.color.red * 255, symbol.color.green * 255, symbol.color.blue * 255, symbol.color.alpha);
return new ColorRange(range, color);
return new ColorInformation(range, color);
});
});
},
resolveDocumentColor(color: Color, colorFormat: ColorFormat): Thenable<string> | string {
switch (colorFormat) {
case ColorFormat.RGB:
if (color.alpha === 1) {
return `rgb(${Math.round(color.red * 255)}, ${Math.round(color.green * 255)}, ${Math.round(color.blue * 255)})`;
} else {
return `rgba(${Math.round(color.red * 255)}, ${Math.round(color.green * 255)}, ${Math.round(color.blue * 255)}, ${color.alpha})`;
}
case ColorFormat.HEX:
if (color.alpha === 1) {
return `#${_toTwoDigitHex(Math.round(color.red * 255))}${_toTwoDigitHex(Math.round(color.green * 255))}${_toTwoDigitHex(Math.round(color.blue * 255))}`;
} else {
return `#${_toTwoDigitHex(Math.round(color.red * 255))}${_toTwoDigitHex(Math.round(color.green * 255))}${_toTwoDigitHex(Math.round(color.blue * 255))}${_toTwoDigitHex(Math.round(color.alpha * 255))}`;
}
case ColorFormat.HSL:
const hsl = convert.rgb.hsl(Math.round(color.red * 255), Math.round(color.green * 255), Math.round(color.blue * 255));
if (color.alpha === 1) {
return `hsl(${hsl[0]}, ${hsl[1]}%, ${hsl[2]}%)`;
} else {
return `hsla(${hsl[0]}, ${hsl[1]}%, ${hsl[2]}%, ${color.alpha})`;
}
provideColorPresentations(colorInfo: ColorInformation): ColorPresentation[] | Thenable<ColorPresentation[]> {
let result: ColorPresentation[] = [];
let color = colorInfo.color;
let label;
if (color.alpha === 1) {
label = `rgb(${Math.round(color.red * 255)}, ${Math.round(color.green * 255)}, ${Math.round(color.blue * 255)})`;
} else {
label = `rgba(${Math.round(color.red * 255)}, ${Math.round(color.green * 255)}, ${Math.round(color.blue * 255)}, ${color.alpha})`;
}
result.push({ label: label, textEdit: new TextEdit(colorInfo.range, label) });
if (color.alpha === 1) {
label = `#${_toTwoDigitHex(Math.round(color.red * 255))}${_toTwoDigitHex(Math.round(color.green * 255))}${_toTwoDigitHex(Math.round(color.blue * 255))}`;
} else {
label = `#${_toTwoDigitHex(Math.round(color.red * 255))}${_toTwoDigitHex(Math.round(color.green * 255))}${_toTwoDigitHex(Math.round(color.blue * 255))}${_toTwoDigitHex(Math.round(color.alpha * 255))}`;
}
result.push({ label: label, textEdit: new TextEdit(colorInfo.range, label) });
const hsl = convert.rgb.hsl(Math.round(color.red * 255), Math.round(color.green * 255), Math.round(color.blue * 255));
if (color.alpha === 1) {
label = `hsl(${hsl[0]}, ${hsl[1]}%, ${hsl[2]}%)`;
} else {
label = `hsla(${hsl[0]}, ${hsl[1]}%, ${hsl[2]}%, ${color.alpha})`;
}
result.push({ label: label, textEdit: new TextEdit(colorInfo.range, label) });
return result;
}
});
toDispose.push(disposable);
+4 -4
View File
@@ -8,25 +8,25 @@
"request": "attach",
"port": 6004,
"sourceMaps": true,
"outDir": "${workspaceRoot}/out"
"outDir": "${workspaceFolder}/out"
},
{
"name": "Unit Tests",
"type": "node",
"request": "launch",
"program": "${workspaceRoot}/../../../node_modules/mocha/bin/_mocha",
"program": "${workspaceFolder}/../../../node_modules/mocha/bin/_mocha",
"stopOnEntry": false,
"args": [
"--timeout",
"999999",
"--colors"
],
"cwd": "${workspaceRoot}",
"cwd": "${workspaceFolder}",
"runtimeExecutable": null,
"runtimeArgs": [],
"env": {},
"sourceMaps": true,
"outDir": "${workspaceRoot}/out"
"outDir": "${workspaceFolder}/out"
}
]
}
@@ -58,7 +58,7 @@ export function getDocumentRegions(languageService: LanguageService, document: T
}
importedScripts.push(value);
} else if (lastAttributeName === 'type' && lastTagName.toLowerCase() === 'script') {
if (/["'](text|application)\/(java|ecma)script["']/.test(scanner.getTokenText())) {
if (/["'](module|(text|application)\/(java|ecma)script)["']/.test(scanner.getTokenText())) {
languageIdFromType = 'javascript';
} else {
languageIdFromType = void 0;
+11 -5
View File
@@ -5,7 +5,7 @@
'use strict';
import { getLanguageModelCache } from '../languageModelCache';
import { LanguageService as HTMLLanguageService, HTMLDocument, DocumentContext, FormattingOptions } from 'vscode-html-languageservice';
import { LanguageService as HTMLLanguageService, HTMLDocument, DocumentContext, FormattingOptions, HTMLFormatConfiguration } from 'vscode-html-languageservice';
import { TextDocument, Position, Range } from 'vscode-languageserver-types';
import { LanguageMode, Settings } from './languageModes';
@@ -40,12 +40,18 @@ export function getHTMLMode(htmlLanguageService: HTMLLanguageService): LanguageM
return htmlLanguageService.findDocumentSymbols(document, htmlDocuments.get(document));
},
format(document: TextDocument, range: Range, formatParams: FormattingOptions, settings: Settings = globalSettings) {
let formatSettings = settings && settings.html && settings.html.format;
if (!formatSettings) {
formatSettings = formatParams;
let formatSettings: HTMLFormatConfiguration = settings && settings.html && settings.html.format;
if (formatSettings) {
formatSettings = merge(formatSettings, {});
} else {
formatSettings = merge(formatParams, merge(formatSettings, {}));
formatSettings = {};
}
if (formatSettings.contentUnformatted) {
formatSettings.contentUnformatted = formatSettings.contentUnformatted + ',script';
} else {
formatSettings.contentUnformatted = 'script';
}
formatSettings = merge(formatParams, formatSettings);
return htmlLanguageService.format(document, range, formatSettings);
},
doAutoClose(document: TextDocument, position: Position) {
@@ -13,7 +13,6 @@
}
},
});
</script>
</head>
@@ -13,7 +13,6 @@
}
},
});
</script>
</head>
@@ -13,7 +13,6 @@
}
},
});
</script>
</head>
@@ -3,5 +3,4 @@
<script>
Polymer({
});
</script>
@@ -58,12 +58,11 @@ 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>\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\n </script></head></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>\n |<script>\nvar x=5;\n</script>|</head></html>', '<html><head>\n <script>\n var x = 5;\n </script></head></html>');
});
test('HTLM & Scripts - Fixtures', function () {
@@ -74,11 +73,11 @@ suite('HTML Embedded Formatting', () => {
});
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\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 </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\n </script>\n <script>\n function(x) {}\n\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 </script>\n <script>\n function(x) {}\n </script>\n</head>\n\n</html>');
});
test('HTML & Styles', function (): any {
@@ -95,7 +94,7 @@ suite('HTML Embedded Formatting', () => {
};
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\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 </script>\n</head>\n\n</html>\n', options);
});
test('Inside script', function (): any {
@@ -104,7 +103,7 @@ suite('HTML Embedded Formatting', () => {
});
test('Range after new line', function (): any {
assertFormat('<html><head>\n |<script>\nvar x=6;\n</script>\n|</head></html>', '<html><head>\n <script>\n var x = 6;\n\n </script>\n</head></html>');
assertFormat('<html><head>\n |<script>\nvar x=6;\n</script>\n|</head></html>', '<html><head>\n <script>\n var x = 6;\n </script>\n</head></html>');
});
});
+4 -4
View File
@@ -7,11 +7,11 @@
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceRoot}"
"--extensionDevelopmentPath=${workspaceFolder}"
],
"stopOnEntry": false,
"sourceMaps": true,
"outDir": "${workspaceRoot}/out",
"outDir": "${workspaceFolder}/out",
"preLaunchTask": "npm"
},
{
@@ -19,10 +19,10 @@
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test" ],
"args": ["--extensionDevelopmentPath=${workspaceFolder}", "--extensionTestsPath=${workspaceFolder}/out/test" ],
"stopOnEntry": false,
"sourceMaps": true,
"outDir": "${workspaceRoot}/out/test",
"outDir": "${workspaceFolder}/out/test",
"preLaunchTask": "npm"
}
]
+1 -1
View File
@@ -1,5 +1,5 @@
// Available variables which can be used inside of strings.
// ${workspaceRoot}: the root folder of the team
// ${workspaceFolder}: the root folder of the team
// ${file}: the current opened file
// ${fileBasename}: the current opened file's basename
// ${fileDirname}: the current opened file's dirname
+5 -3
View File
@@ -67,7 +67,8 @@
"path": "./syntaxes/JavaScript.tmLanguage.json",
"embeddedLanguages": {
"meta.tag.js": "jsx-tags",
"meta.tag.without-attributes.js": "jsx-tags"
"meta.tag.without-attributes.js": "jsx-tags",
"meta.embedded.expression.js": "javascriptreact"
}
},
{
@@ -76,7 +77,8 @@
"path": "./syntaxes/JavaScript.tmLanguage.json",
"embeddedLanguages": {
"meta.tag.js": "jsx-tags",
"meta.tag.without-attributes.js": "jsx-tags"
"meta.tag.without-attributes.js": "jsx-tags",
"meta.embedded.expression.js": "javascript"
}
},
{
@@ -132,4 +134,4 @@
"devDependencies": {
"@types/node": "^7.0.4"
}
}
}
+5 -5
View File
@@ -7,11 +7,11 @@
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceRoot}"
"--extensionDevelopmentPath=${workspaceFolder}"
],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": ["${workspaceRoot}/client/out"],
"outFiles": ["${workspaceFolder}/client/out"],
"preLaunchTask": "npm"
},
{
@@ -19,10 +19,10 @@
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/client/out/test" ],
"args": ["--extensionDevelopmentPath=${workspaceFolder}", "--extensionTestsPath=${workspaceFolder}/client/out/test" ],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": ["${workspaceRoot}/client/out/test"],
"outFiles": ["${workspaceFolder}/client/out/test"],
"preLaunchTask": "npm"
},
{
@@ -31,7 +31,7 @@
"request": "attach",
"port": 6004,
"sourceMaps": true,
"outFiles": ["${workspaceRoot}/server/out"]
"outFiles": ["${workspaceFolder}/server/out"]
}
]
+1 -1
View File
@@ -1,5 +1,5 @@
// Available variables which can be used inside of strings.
// ${workspaceRoot}: the root folder of the team
// ${workspaceFolder}: the root folder of the team
// ${file}: the current opened file
// ${fileBasename}: the current opened file's basename
// ${fileDirname}: the current opened file's dirname
+13 -6
View File
@@ -6,7 +6,7 @@
import * as path from 'path';
import { workspace, languages, ExtensionContext, extensions, Uri, TextDocument, ColorRange, Color, ColorFormat } from 'vscode';
import { workspace, languages, ExtensionContext, extensions, Uri, TextDocument, ColorInformation, Color, ColorPresentation, TextEdit } from 'vscode';
import { LanguageClient, LanguageClientOptions, RequestType, ServerOptions, TransportKind, NotificationType, DidChangeConfigurationNotification } from 'vscode-languageclient';
import TelemetryReporter from 'vscode-extension-telemetry';
import { ConfigurationFeature } from 'vscode-languageclient/lib/proposed';
@@ -122,22 +122,29 @@ export function activate(context: ExtensionContext) {
};
// register color provider
context.subscriptions.push(languages.registerColorProvider(documentSelector, {
provideDocumentColors(document: TextDocument): Thenable<ColorRange[]> {
provideDocumentColors(document: TextDocument): Thenable<ColorInformation[]> {
let params = client.code2ProtocolConverter.asDocumentSymbolParams(document);
return client.sendRequest(DocumentColorRequest.type, params).then(symbols => {
return symbols.map(symbol => {
let range = client.protocol2CodeConverter.asRange(symbol.range);
let color = new Color(symbol.color.red * 255, symbol.color.green * 255, symbol.color.blue * 255, symbol.color.alpha);
return new ColorRange(range, color);
return new ColorInformation(range, color);
});
});
},
resolveDocumentColor(color: Color, colorFormat: ColorFormat): Thenable<string> | string {
provideColorPresentations(colorInfo: ColorInformation): ColorPresentation[] | Thenable<ColorPresentation[]> {
let result: ColorPresentation[] = [];
let color = colorInfo.color;
let label;
if (color.alpha === 1) {
return `#${_toTwoDigitHex(Math.round(color.red * 255))}${_toTwoDigitHex(Math.round(color.green * 255))}${_toTwoDigitHex(Math.round(color.blue * 255))}`;
label = `#${_toTwoDigitHex(Math.round(color.red * 255))}${_toTwoDigitHex(Math.round(color.green * 255))}${_toTwoDigitHex(Math.round(color.blue * 255))}`;
} else {
return `#${_toTwoDigitHex(Math.round(color.red * 255))}${_toTwoDigitHex(Math.round(color.green * 255))}${_toTwoDigitHex(Math.round(color.blue * 255))}${_toTwoDigitHex(Math.round(color.alpha * 255))}`;
label = `#${_toTwoDigitHex(Math.round(color.red * 255))}${_toTwoDigitHex(Math.round(color.green * 255))}${_toTwoDigitHex(Math.round(color.blue * 255))}${_toTwoDigitHex(Math.round(color.alpha * 255))}`;
}
result.push({ label: label, textEdit: new TextEdit(colorInfo.range, label) });
return result;
}
}));
});
+4 -4
View File
@@ -8,25 +8,25 @@
"request": "attach",
"port": 6004,
"sourceMaps": true,
"outDir": "${workspaceRoot}/out"
"outDir": "${workspaceFolder}/out"
},
{
"name": "Unit Tests",
"type": "node",
"request": "launch",
"program": "${workspaceRoot}/../../../node_modules/mocha/bin/_mocha",
"program": "${workspaceFolder}/../../../node_modules/mocha/bin/_mocha",
"stopOnEntry": false,
"args": [
"--timeout",
"999999",
"--colors"
],
"cwd": "${workspaceRoot}",
"cwd": "${workspaceFolder}",
"runtimeExecutable": null,
"runtimeArgs": [],
"env": {},
"sourceMaps": true,
"outDir": "${workspaceRoot}/out"
"outDir": "${workspaceFolder}/out"
}
]
}
+54 -3
View File
@@ -41,7 +41,52 @@
{
"language": "markdown",
"scopeName": "text.html.markdown",
"path": "./syntaxes/markdown.tmLanguage"
"path": "./syntaxes/markdown.tmLanguage",
"embeddedLanguages": {
"meta.embedded.block.html": "html",
"source.js": "javascript",
"source.css": "css",
"meta.embedded.block.css": "css",
"meta.embedded.block.ini": "ini",
"meta.embedded.block.java": "java",
"meta.embedded.block.lua": "lua",
"meta.embedded.block.makefile": "makefile",
"meta.embedded.block.perl": "perl",
"meta.embedded.block.r": "r",
"meta.embedded.block.ruby": "ruby",
"meta.embedded.block.php": "php",
"meta.embedded.block.sql": "sql",
"meta.embedded.block.vs_net": "vs_net",
"meta.embedded.block.xml": "xml",
"meta.embedded.block.xsl": "xsl",
"meta.embedded.block.yaml": "yaml",
"meta.embedded.block.dosbatch": "dosbatch",
"meta.embedded.block.clojure": "clojure",
"meta.embedded.block.coffee": "coffee",
"meta.embedded.block.c": "c",
"meta.embedded.block.cpp": "cpp",
"meta.embedded.block.diff": "diff",
"meta.embedded.block.dockerfile": "dockerfile",
"meta.embedded.block.go": "go",
"meta.embedded.block.groovy": "groovy",
"meta.embedded.block.jade": "jade",
"meta.embedded.block.javascript": "javascript",
"meta.embedded.block.json": "json",
"meta.embedded.block.less": "less",
"meta.embedded.block.objc": "objc",
"meta.embedded.block.scss": "scss",
"meta.embedded.block.perl6": "perl6",
"meta.embedded.block.powershell": "powershell",
"meta.embedded.block.python": "python",
"meta.embedded.block.rust": "rust",
"meta.embedded.block.scala": "scala",
"meta.embedded.block.shellscript": "shellscript",
"meta.embedded.block.typescript": "typescript",
"meta.embedded.block.typescriptreact": "typescriptreact",
"meta.embedded.block.csharp": "csharp",
"meta.embedded.block.fsharp": "fsharp"
}
}
],
"commands": [
@@ -234,7 +279,13 @@
"editor.wordWrap": "on",
"editor.quickSuggestions": false
}
}
},
"jsonValidation": [
{
"fileMatch": "package.json",
"url": "./schemas/package.schema.json"
}
]
},
"scripts": {
"vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:markdown ./tsconfig.json",
@@ -254,4 +305,4 @@
"gulp-rename": "^1.2.2",
"gulp-replace": "^0.5.4"
}
}
}
@@ -0,0 +1,32 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Markdown contributions to package.json",
"type": "object",
"properties": {
"contributes": {
"type": "object",
"properties": {
"markdown.previewStyles": {
"type": "array",
"description": "Contributed CSS files that change the look or layout of the Markdown preview",
"items": {
"type": "string",
"description": "Extension relative path to a css file"
}
},
"markdown.previewScripts": {
"type": "array",
"description": "Contributed scripts that are executed in the Markdown preview",
"items": {
"type": "string",
"description": "Extension relative path to a JavaScript file"
}
},
"markdown.markdownItPlugins": {
"type": "boolean",
"description": "Does this extension contributes a markdown-it plugin?"
}
}
}
}
}
+57 -42
View File
@@ -1,64 +1,69 @@
// @ts-check
var gulp = require('gulp');
var util = require("gulp-util");
var replace = require('gulp-replace');
var rename = require('gulp-rename');
const languages = [
{ name: 'css', identifiers: ['css', 'css.erb'], source: 'source.css' },
{ name: 'basic', identifiers: ['html', 'htm', 'shtml', 'xhtml', 'inc', 'tmpl', 'tpl'], source: 'text.html.basic' },
{ name: 'ini', identifiers: ['ini', 'conf'], source: 'source.ini' },
{ name: 'java', identifiers: ['java', 'bsh'], source: 'source.java' },
{ name: 'lua', identifiers: ['lua'], source: 'source.lua' },
{ name: 'makefile', identifiers: ['Makefile', 'makefile', 'GNUmakefile', 'OCamlMakefile'], source: 'source.makefile' },
{ name: 'perl', identifiers: ['perl', 'pl', 'pm', 'pod', 't', 'PL', 'psgi', 'vcl'], source: 'source.perl' },
{ name: 'r', identifiers: ['R', 'r', 's', 'S', 'Rprofile'], source: 'source.r' },
{ name: 'ruby', identifiers: ['ruby', 'rb', 'rbx', 'rjs', 'Rakefile', 'rake', 'cgi', 'fcgi', 'gemspec', 'irbrc', 'Capfile', 'ru', 'prawn', 'Cheffile', 'Gemfile', 'Guardfile', 'Hobofile', 'Vagrantfile', 'Appraisals', 'Rantfile', 'Berksfile', 'Berksfile.lock', 'Thorfile', 'Puppetfile'], source: 'source.ruby' },
{ name: 'css', language: 'css', identifiers: ['css', 'css.erb'], source: 'source.css' },
{ name: 'basic', language: 'html', identifiers: ['html', 'htm', 'shtml', 'xhtml', 'inc', 'tmpl', 'tpl'], source: 'text.html.basic' },
{ name: 'ini', language: 'ini', identifiers: ['ini', 'conf'], source: 'source.ini' },
{ name: 'java', language: 'java', identifiers: ['java', 'bsh'], source: 'source.java' },
{ name: 'lua', language: 'lua', identifiers: ['lua'], source: 'source.lua' },
{ name: 'makefile', language: 'makefile', identifiers: ['Makefile', 'makefile', 'GNUmakefile', 'OCamlMakefile'], source: 'source.makefile' },
{ name: 'perl', language: 'perl', identifiers: ['perl', 'pl', 'pm', 'pod', 't', 'PL', 'psgi', 'vcl'], source: 'source.perl' },
{ name: 'r', language: 'r', identifiers: ['R', 'r', 's', 'S', 'Rprofile'], source: 'source.r' },
{ name: 'ruby', language: 'ruby', identifiers: ['ruby', 'rb', 'rbx', 'rjs', 'Rakefile', 'rake', 'cgi', 'fcgi', 'gemspec', 'irbrc', 'Capfile', 'ru', 'prawn', 'Cheffile', 'Gemfile', 'Guardfile', 'Hobofile', 'Vagrantfile', 'Appraisals', 'Rantfile', 'Berksfile', 'Berksfile.lock', 'Thorfile', 'Puppetfile'], source: 'source.ruby' },
// Left to its own devices, the PHP grammar will match HTML as a combination of operators
// and constants. Therefore, HTML must take precedence over PHP in order to get proper
// syntax highlighting.
{ name: 'php', identifiers: ['php', 'php3', 'php4', 'php5', 'phpt', 'phtml', 'aw', 'ctp'], source: ['text.html.basic', 'text.html.php#language'] },
{ name: 'sql', identifiers: ['sql', 'ddl', 'dml'], source: 'source.sql' },
{ name: 'vs_net', identifiers: ['vb'], source: 'source.asp.vb.net' },
{ name: 'xml', identifiers: ['xml', 'xsd', 'tld', 'jsp', 'pt', 'cpt', 'dtml', 'rss', 'opml'], source: 'text.xml' },
{ name: 'xsl', identifiers: ['xsl', 'xslt'], source: 'text.xml.xsl' },
{ name: 'yaml', identifiers: ['yaml', 'yml'], source: 'source.yaml' },
{ name: 'dosbatch', identifiers: ['bat', 'batch'], source: 'source.dosbatch' },
{ name: 'clojure', identifiers: ['clj', 'cljs', 'clojure'], source: 'source.clojure' },
{ name: 'coffee', identifiers: ['coffee', 'Cakefile', 'coffee.erb'], source: 'source.coffee' },
{ name: 'c', identifiers: ['c', 'h'], source: 'source.c' },
{ name: 'cpp', identifiers: ['cpp', 'c\\+\\+', 'cxx'], source: 'source.cpp' },
{ name: 'diff', identifiers: ['patch', 'diff', 'rej'], source: 'source.diff' },
{ name: 'dockerfile', identifiers: ['dockerfile', 'Dockerfile'], source: 'source.dockerfile' },
{ name: 'php', language: 'php', identifiers: ['php', 'php3', 'php4', 'php5', 'phpt', 'phtml', 'aw', 'ctp'], source: ['text.html.basic', 'text.html.php#language'] },
{ name: 'sql', language: 'sql', identifiers: ['sql', 'ddl', 'dml'], source: 'source.sql' },
{ name: 'vs_net', language: 'vs_net', identifiers: ['vb'], source: 'source.asp.vb.net' },
{ name: 'xml', language: 'xml', identifiers: ['xml', 'xsd', 'tld', 'jsp', 'pt', 'cpt', 'dtml', 'rss', 'opml'], source: 'text.xml' },
{ name: 'xsl', language: 'xsl', identifiers: ['xsl', 'xslt'], source: 'text.xml.xsl' },
{ name: 'yaml', language: 'yaml', identifiers: ['yaml', 'yml'], source: 'source.yaml' },
{ name: 'dosbatch', language: 'dosbatch', identifiers: ['bat', 'batch'], source: 'source.dosbatch' },
{ name: 'clojure', language: 'clojure', identifiers: ['clj', 'cljs', 'clojure'], source: 'source.clojure' },
{ name: 'coffee', language: 'coffee', identifiers: ['coffee', 'Cakefile', 'coffee.erb'], source: 'source.coffee' },
{ name: 'c', language: 'c', identifiers: ['c', 'h'], source: 'source.c' },
{ name: 'cpp', language: 'cpp', identifiers: ['cpp', 'c\\+\\+', 'cxx'], source: 'source.cpp' },
{ name: 'diff', language: 'diff', identifiers: ['patch', 'diff', 'rej'], source: 'source.diff' },
{ name: 'dockerfile', language: 'dockerfile', identifiers: ['dockerfile', 'Dockerfile'], source: 'source.dockerfile' },
{ name: 'git_commit', identifiers: ['COMMIT_EDITMSG', 'MERGE_MSG'], source: 'text.git-commit' },
{ name: 'git_rebase', identifiers: ['git-rebase-todo'], source: 'text.git-rebase' },
{ name: 'go', identifiers: ['go', 'golang'], source: 'source.go' },
{ name: 'groovy', identifiers: ['groovy', 'gvy'], source: 'source.groovy' },
{ name: 'jade', identifiers: ['jade', 'pug'], source: 'text.jade' },
{ name: 'go', language: 'go', identifiers: ['go', 'golang'], source: 'source.go' },
{ name: 'groovy', language: 'groovy', identifiers: ['groovy', 'gvy'], source: 'source.groovy' },
{ name: 'jade', language: 'jade', identifiers: ['jade', 'pug'], source: 'text.jade' },
{ name: 'js', identifiers: ['js', 'jsx', 'javascript', 'es6', 'mjs'], source: 'source.js' },
{ name: 'js', language: 'javascript', identifiers: ['js', 'jsx', 'javascript', 'es6', 'mjs'], source: 'source.js' },
{ name: 'js_regexp', identifiers: ['regexp'], source: 'source.js.regexp' },
{ name: 'json', identifiers: ['json', 'sublime-settings', 'sublime-menu', 'sublime-keymap', 'sublime-mousemap', 'sublime-theme', 'sublime-build', 'sublime-project', 'sublime-completions'], source: 'source.json' },
{ name: 'less', identifiers: ['less'], source: 'source.css.less' },
{ name: 'objc', identifiers: ['objectivec', 'objective-c', 'mm', 'objc', 'obj-c', 'm', 'h'], source: 'source.objc' },
{ name: 'scss', identifiers: ['scss'], source: 'source.css.scss' },
{ name: 'json', language: 'json', identifiers: ['json', 'sublime-settings', 'sublime-menu', 'sublime-keymap', 'sublime-mousemap', 'sublime-theme', 'sublime-build', 'sublime-project', 'sublime-completions'], source: 'source.json' },
{ name: 'less', language: 'less', identifiers: ['less'], source: 'source.css.less' },
{ name: 'objc', language: 'objc', identifiers: ['objectivec', 'objective-c', 'mm', 'objc', 'obj-c', 'm', 'h'], source: 'source.objc' },
{ name: 'scss', language: 'scss', identifiers: ['scss'], source: 'source.css.scss' },
{ name: 'perl6', identifiers: ['perl6', 'p6', 'pl6', 'pm6', 'nqp'], source: 'source.perl.6' },
{ name: 'powershell', identifiers: ['powershell', 'ps1', 'psm1', 'psd1'], source: 'source.powershell' },
{ name: 'python', identifiers: ['python', 'py', 'py3', 'rpy', 'pyw', 'cpy', 'SConstruct', 'Sconstruct', 'sconstruct', 'SConscript', 'gyp', 'gypi'], source: 'source.python' },
{ name: 'perl6', language: 'perl6', identifiers: ['perl6', 'p6', 'pl6', 'pm6', 'nqp'], source: 'source.perl.6' },
{ name: 'powershell', language: 'powershell', identifiers: ['powershell', 'ps1', 'psm1', 'psd1'], source: 'source.powershell' },
{ name: 'python', language: 'python', identifiers: ['python', 'py', 'py3', 'rpy', 'pyw', 'cpy', 'SConstruct', 'Sconstruct', 'sconstruct', 'SConscript', 'gyp', 'gypi'], source: 'source.python' },
{ name: 'regexp_python', identifiers: ['re'], source: 'source.regexp.python' },
{ name: 'rust', identifiers: ['rust', 'rs'], source: 'source.rust' },
{ name: 'scala', identifiers: ['scala', 'sbt'], source: 'source.scala' },
{ name: 'shell', identifiers: ['shell', 'sh', 'bash', 'zsh', 'bashrc', 'bash_profile', 'bash_login', 'profile', 'bash_logout', '.textmate_init'], source: 'source.shell' },
{ name: 'ts', identifiers: ['typescript', 'ts'], source: 'source.ts' },
{ name: 'tsx', identifiers: ['tsx'], source: 'source.tsx' },
{ name: 'csharp', identifiers: ['cs', 'csharp', 'c#'], source: 'source.cs' },
{ name: 'fsharp', identifiers: ['fs', 'fsharp', 'f#'], source: 'source.fsharp' },
{ name: 'rust', language: 'rust', identifiers: ['rust', 'rs'], source: 'source.rust' },
{ name: 'scala', language: 'scala', identifiers: ['scala', 'sbt'], source: 'source.scala' },
{ name: 'shell', language: 'shellscript', identifiers: ['shell', 'sh', 'bash', 'zsh', 'bashrc', 'bash_profile', 'bash_login', 'profile', 'bash_logout', '.textmate_init'], source: 'source.shell' },
{ name: 'ts', language: 'typescript', identifiers: ['typescript', 'ts'], source: 'source.ts' },
{ name: 'tsx', language: 'typescriptreact', identifiers: ['tsx'], source: 'source.tsx' },
{ name: 'csharp', language: 'csharp', identifiers: ['cs', 'csharp', 'c#'], source: 'source.cs' },
{ name: 'fsharp', language: 'fsharp', identifiers: ['fs', 'fsharp', 'f#'], source: 'source.fsharp' },
];
const fencedCodeBlockDefinition = (name, identifiers, sourceScope) => {
const fencedCodeBlockDefinition = (name, identifiers, sourceScope, language) => {
if (!Array.isArray(sourceScope)) {
sourceScope = [sourceScope];
}
language = language || name
const scopes = sourceScope.map(scope =>
`<dict>
<key>include</key>
@@ -106,6 +111,8 @@ const fencedCodeBlockDefinition = (name, identifiers, sourceScope) => {
<string>(^|\\G)(\\s*)(.*)</string>
<key>while</key>
<string>(^|\\G)(?!\\s*([\`~]{3,})\\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.${language}</string>
<key>patterns</key>
<array>
${indent(4, scopes)}
@@ -129,7 +136,7 @@ const fencedCodeBlockInclude = (name) =>
const fencedCodeBlockDefinitions = () =>
languages
.map(language => fencedCodeBlockDefinition(language.name, language.identifiers, language.source))
.map(language => fencedCodeBlockDefinition(language.name, language.identifiers, language.source, language.language))
.join('\n');
@@ -147,3 +154,11 @@ gulp.task('default', function () {
.pipe(rename('markdown.tmLanguage'))
.pipe(gulp.dest('.'));
});
gulp.task('embedded', function () {
const out = {}
for (const lang of languages.filter(x => x.language)) {
out['meta.embedded.block.' +lang.language] = lang.language;
}
util.log(JSON.stringify(out, undefined, 4));
});
@@ -626,6 +626,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.css</string>
<key>patterns</key>
<array>
<dict>
@@ -677,6 +679,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.html</string>
<key>patterns</key>
<array>
<dict>
@@ -728,6 +732,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.ini</string>
<key>patterns</key>
<array>
<dict>
@@ -779,6 +785,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.java</string>
<key>patterns</key>
<array>
<dict>
@@ -830,6 +838,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.lua</string>
<key>patterns</key>
<array>
<dict>
@@ -881,6 +891,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.makefile</string>
<key>patterns</key>
<array>
<dict>
@@ -932,6 +944,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.perl</string>
<key>patterns</key>
<array>
<dict>
@@ -983,6 +997,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.r</string>
<key>patterns</key>
<array>
<dict>
@@ -1034,6 +1050,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.ruby</string>
<key>patterns</key>
<array>
<dict>
@@ -1085,6 +1103,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.php</string>
<key>patterns</key>
<array>
<dict>
@@ -1140,6 +1160,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.sql</string>
<key>patterns</key>
<array>
<dict>
@@ -1191,6 +1213,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.vs_net</string>
<key>patterns</key>
<array>
<dict>
@@ -1242,6 +1266,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.xml</string>
<key>patterns</key>
<array>
<dict>
@@ -1293,6 +1319,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.xsl</string>
<key>patterns</key>
<array>
<dict>
@@ -1344,6 +1372,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.yaml</string>
<key>patterns</key>
<array>
<dict>
@@ -1395,6 +1425,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.dosbatch</string>
<key>patterns</key>
<array>
<dict>
@@ -1446,6 +1478,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.clojure</string>
<key>patterns</key>
<array>
<dict>
@@ -1497,6 +1531,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.coffee</string>
<key>patterns</key>
<array>
<dict>
@@ -1548,6 +1584,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.c</string>
<key>patterns</key>
<array>
<dict>
@@ -1599,6 +1637,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.cpp</string>
<key>patterns</key>
<array>
<dict>
@@ -1650,6 +1690,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.diff</string>
<key>patterns</key>
<array>
<dict>
@@ -1701,6 +1743,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.dockerfile</string>
<key>patterns</key>
<array>
<dict>
@@ -1752,6 +1796,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.git_commit</string>
<key>patterns</key>
<array>
<dict>
@@ -1803,6 +1849,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.git_rebase</string>
<key>patterns</key>
<array>
<dict>
@@ -1854,6 +1902,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.go</string>
<key>patterns</key>
<array>
<dict>
@@ -1905,6 +1955,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.groovy</string>
<key>patterns</key>
<array>
<dict>
@@ -1956,6 +2008,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.jade</string>
<key>patterns</key>
<array>
<dict>
@@ -2007,6 +2061,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.javascript</string>
<key>patterns</key>
<array>
<dict>
@@ -2058,6 +2114,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.js_regexp</string>
<key>patterns</key>
<array>
<dict>
@@ -2109,6 +2167,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.json</string>
<key>patterns</key>
<array>
<dict>
@@ -2160,6 +2220,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.less</string>
<key>patterns</key>
<array>
<dict>
@@ -2211,6 +2273,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.objc</string>
<key>patterns</key>
<array>
<dict>
@@ -2262,6 +2326,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.scss</string>
<key>patterns</key>
<array>
<dict>
@@ -2313,6 +2379,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.perl6</string>
<key>patterns</key>
<array>
<dict>
@@ -2364,6 +2432,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.powershell</string>
<key>patterns</key>
<array>
<dict>
@@ -2415,6 +2485,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.python</string>
<key>patterns</key>
<array>
<dict>
@@ -2466,6 +2538,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.regexp_python</string>
<key>patterns</key>
<array>
<dict>
@@ -2517,6 +2591,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.rust</string>
<key>patterns</key>
<array>
<dict>
@@ -2568,6 +2644,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.scala</string>
<key>patterns</key>
<array>
<dict>
@@ -2619,6 +2697,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.shellscript</string>
<key>patterns</key>
<array>
<dict>
@@ -2670,6 +2750,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.typescript</string>
<key>patterns</key>
<array>
<dict>
@@ -2721,6 +2803,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.typescriptreact</string>
<key>patterns</key>
<array>
<dict>
@@ -2772,6 +2856,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.csharp</string>
<key>patterns</key>
<array>
<dict>
@@ -2823,6 +2909,8 @@
<string>(^|\G)(\s*)(.*)</string>
<key>while</key>
<string>(^|\G)(?!\s*([`~]{3,})\s*$)</string>
<key>contentName</key>
<string>meta.embedded.block.fsharp</string>
<key>patterns</key>
<array>
<dict>
+2 -2
View File
@@ -7,11 +7,11 @@
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceRoot}"
"--extensionDevelopmentPath=${workspaceFolder}"
],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": ["${workspaceRoot}/client/out/**/*.js"],
"outFiles": ["${workspaceFolder}/client/out/**/*.js"],
"preLaunchTask": "npm"
}
]
+3 -3
View File
@@ -7,12 +7,12 @@
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceRoot}"
"--extensionDevelopmentPath=${workspaceFolder}"
],
"stopOnEntry": false,
"sourceMaps": true,
"outDir": "${workspaceRoot}/out",
"outDir": "${workspaceFolder}/out",
"preLaunchTask": "npm"
}
}
]
}
+1 -1
View File
@@ -1,5 +1,5 @@
// Available variables which can be used inside of strings.
// ${workspaceRoot}: the root folder of the team
// ${workspaceFolder}: the root folder of the team
// ${file}: the current opened file
// ${fileBasename}: the current opened file's basename
// ${fileDirname}: the current opened file's dirname
+3 -3
View File
@@ -7,12 +7,12 @@
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceRoot}"
"--extensionDevelopmentPath=${workspaceFolder}"
],
"stopOnEntry": false,
"sourceMaps": true,
"outDir": "${workspaceRoot}/out",
"outDir": "${workspaceFolder}/out",
"preLaunchTask": "npm"
}
}
]
}
+1 -1
View File
@@ -1,5 +1,5 @@
// Available variables which can be used inside of strings.
// ${workspaceRoot}: the root folder of the team
// ${workspaceFolder}: the root folder of the team
// ${file}: the current opened file
// ${fileBasename}: the current opened file's basename
// ${fileDirname}: the current opened file's dirname
+3 -13
View File
@@ -1,17 +1,7 @@
// ATTENTION - THIS DIRECTORY CONTAINS THIRD PARTY OPEN SOURCE MATERIALS:
[{
"name": "textmate/r.tmbundle",
"name": "Ikuyadeu/vscode-R",
"version": "0.0.0",
"license": "TextMate Bundle License",
"repositoryURL": "https://github.com/textmate/r.tmbundle",
"licenseDetail": [
"Copyright (c) textmate-r.tmbundle project authors",
"",
"If not otherwise specified (see below), files in this folder fall under the following license: ",
"",
"Permission to copy, use, modify, sell and distribute this",
"software is granted. This software is provided \"as is\" without",
"express or implied warranty, and with no claim as to its",
"suitability for any purpose."
]
"license": "MIT",
"repositoryURL": "https://github.com/Ikuyadeu/vscode-R"
}]
+1 -1
View File
@@ -4,7 +4,7 @@
"publisher": "vscode",
"engines": { "vscode": "*" },
"scripts": {
"update-grammar": "node ../../build/npm/update-grammar.js textmate/r.tmbundle Syntaxes/R.plist ./syntaxes/r.tmLanguage.json"
"update-grammar": "node ../../build/npm/update-grammar.js Ikuyadeu/vscode-R syntax/r.json ./syntaxes/r.tmLanguage.json"
},
"contributes": {
"languages": [{
File diff suppressed because one or more lines are too long
+355 -135
View File
@@ -22,8 +22,8 @@
}
},
{
"c": "#",
"t": "source.r comment.line.number-sign.r punctuation.definition.comment.r",
"c": "#'",
"t": "source.r comment.line.roxygen.r punctuation.definition.comment.r",
"r": {
"dark_plus": "comment: #608B4E",
"light_plus": "comment: #008000",
@@ -33,8 +33,8 @@
}
},
{
"c": "' Add together two numbers.",
"t": "source.r comment.line.number-sign.r",
"c": " Add together two numbers.",
"t": "source.r comment.line.roxygen.r",
"r": {
"dark_plus": "comment: #608B4E",
"light_plus": "comment: #008000",
@@ -44,8 +44,8 @@
}
},
{
"c": "#",
"t": "source.r comment.line.number-sign.r punctuation.definition.comment.r",
"c": "#'",
"t": "source.r comment.line.roxygen.r punctuation.definition.comment.r",
"r": {
"dark_plus": "comment: #608B4E",
"light_plus": "comment: #008000",
@@ -55,8 +55,8 @@
}
},
{
"c": "'",
"t": "source.r comment.line.number-sign.r",
"c": "#'",
"t": "source.r comment.line.roxygen.r punctuation.definition.comment.r",
"r": {
"dark_plus": "comment: #608B4E",
"light_plus": "comment: #008000",
@@ -66,8 +66,8 @@
}
},
{
"c": "#",
"t": "source.r comment.line.number-sign.r punctuation.definition.comment.r",
"c": " ",
"t": "source.r comment.line.roxygen.r",
"r": {
"dark_plus": "comment: #608B4E",
"light_plus": "comment: #008000",
@@ -77,8 +77,19 @@
}
},
{
"c": "' @param x A number.",
"t": "source.r comment.line.number-sign.r",
"c": "@param",
"t": "source.r comment.line.roxygen.r keyword.other.r",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
}
},
{
"c": " ",
"t": "source.r comment.line.roxygen.r",
"r": {
"dark_plus": "comment: #608B4E",
"light_plus": "comment: #008000",
@@ -88,8 +99,19 @@
}
},
{
"c": "#",
"t": "source.r comment.line.number-sign.r punctuation.definition.comment.r",
"c": "x",
"t": "source.r comment.line.roxygen.r variable.parameter.r",
"r": {
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "comment: #608B4E",
"light_vs": "comment: #008000",
"hc_black": "variable: #9CDCFE"
}
},
{
"c": " A number.",
"t": "source.r comment.line.roxygen.r",
"r": {
"dark_plus": "comment: #608B4E",
"light_plus": "comment: #008000",
@@ -99,8 +121,8 @@
}
},
{
"c": "' @param y A number.",
"t": "source.r comment.line.number-sign.r",
"c": "#'",
"t": "source.r comment.line.roxygen.r punctuation.definition.comment.r",
"r": {
"dark_plus": "comment: #608B4E",
"light_plus": "comment: #008000",
@@ -110,8 +132,8 @@
}
},
{
"c": "#",
"t": "source.r comment.line.number-sign.r punctuation.definition.comment.r",
"c": " ",
"t": "source.r comment.line.roxygen.r",
"r": {
"dark_plus": "comment: #608B4E",
"light_plus": "comment: #008000",
@@ -121,8 +143,19 @@
}
},
{
"c": "' @return The sum of \\code{x} and \\code{y}.",
"t": "source.r comment.line.number-sign.r",
"c": "@param",
"t": "source.r comment.line.roxygen.r keyword.other.r",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
}
},
{
"c": " ",
"t": "source.r comment.line.roxygen.r",
"r": {
"dark_plus": "comment: #608B4E",
"light_plus": "comment: #008000",
@@ -132,8 +165,19 @@
}
},
{
"c": "#",
"t": "source.r comment.line.number-sign.r punctuation.definition.comment.r",
"c": "y",
"t": "source.r comment.line.roxygen.r variable.parameter.r",
"r": {
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "comment: #608B4E",
"light_vs": "comment: #008000",
"hc_black": "variable: #9CDCFE"
}
},
{
"c": " A number.",
"t": "source.r comment.line.roxygen.r",
"r": {
"dark_plus": "comment: #608B4E",
"light_plus": "comment: #008000",
@@ -143,8 +187,8 @@
}
},
{
"c": "' @examples",
"t": "source.r comment.line.number-sign.r",
"c": "#'",
"t": "source.r comment.line.roxygen.r punctuation.definition.comment.r",
"r": {
"dark_plus": "comment: #608B4E",
"light_plus": "comment: #008000",
@@ -154,8 +198,8 @@
}
},
{
"c": "#",
"t": "source.r comment.line.number-sign.r punctuation.definition.comment.r",
"c": " ",
"t": "source.r comment.line.roxygen.r",
"r": {
"dark_plus": "comment: #608B4E",
"light_plus": "comment: #008000",
@@ -165,8 +209,19 @@
}
},
{
"c": "' add(1, 1)",
"t": "source.r comment.line.number-sign.r",
"c": "@return",
"t": "source.r comment.line.roxygen.r keyword.other.r",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
}
},
{
"c": " The sum of \\code{x} and \\code{y}.",
"t": "source.r comment.line.roxygen.r",
"r": {
"dark_plus": "comment: #608B4E",
"light_plus": "comment: #008000",
@@ -176,8 +231,8 @@
}
},
{
"c": "#",
"t": "source.r comment.line.number-sign.r punctuation.definition.comment.r",
"c": "#'",
"t": "source.r comment.line.roxygen.r punctuation.definition.comment.r",
"r": {
"dark_plus": "comment: #608B4E",
"light_plus": "comment: #008000",
@@ -187,8 +242,63 @@
}
},
{
"c": "' add(10, 1)",
"t": "source.r comment.line.number-sign.r",
"c": " ",
"t": "source.r comment.line.roxygen.r",
"r": {
"dark_plus": "comment: #608B4E",
"light_plus": "comment: #008000",
"dark_vs": "comment: #608B4E",
"light_vs": "comment: #008000",
"hc_black": "comment: #7CA668"
}
},
{
"c": "@examples",
"t": "source.r comment.line.roxygen.r keyword.other.r",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
}
},
{
"c": "#'",
"t": "source.r comment.line.roxygen.r punctuation.definition.comment.r",
"r": {
"dark_plus": "comment: #608B4E",
"light_plus": "comment: #008000",
"dark_vs": "comment: #608B4E",
"light_vs": "comment: #008000",
"hc_black": "comment: #7CA668"
}
},
{
"c": " add(1, 1)",
"t": "source.r comment.line.roxygen.r",
"r": {
"dark_plus": "comment: #608B4E",
"light_plus": "comment: #008000",
"dark_vs": "comment: #608B4E",
"light_vs": "comment: #008000",
"hc_black": "comment: #7CA668"
}
},
{
"c": "#'",
"t": "source.r comment.line.roxygen.r punctuation.definition.comment.r",
"r": {
"dark_plus": "comment: #608B4E",
"light_plus": "comment: #008000",
"dark_vs": "comment: #608B4E",
"light_vs": "comment: #008000",
"hc_black": "comment: #7CA668"
}
},
{
"c": " add(10, 1)",
"t": "source.r comment.line.roxygen.r",
"r": {
"dark_plus": "comment: #608B4E",
"light_plus": "comment: #008000",
@@ -254,7 +364,7 @@
},
{
"c": "(",
"t": "source.r",
"t": "source.r meta.function.r punctuation.section.parens.begin.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -265,7 +375,7 @@
},
{
"c": "x",
"t": "source.r variable.other.r",
"t": "source.r meta.function.r meta.function.parameters.r variable.parameter.r",
"r": {
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
@@ -275,8 +385,19 @@
}
},
{
"c": ", ",
"t": "source.r",
"c": ",",
"t": "source.r meta.function.r meta.function.parameters.r punctuation.separator.parameters.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": " ",
"t": "source.r meta.function.r meta.function.parameters.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -287,7 +408,7 @@
},
{
"c": "y",
"t": "source.r variable.other.r",
"t": "source.r meta.function.r meta.function.parameters.r variable.parameter.r",
"r": {
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
@@ -297,7 +418,18 @@
}
},
{
"c": ") ",
"c": ")",
"t": "source.r meta.function.r punctuation.section.parens.end.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": " ",
"t": "source.r",
"r": {
"dark_plus": "default: #D4D4D4",
@@ -309,7 +441,7 @@
},
{
"c": "{",
"t": "source.r meta.block.r punctuation.section.block.begin.r",
"t": "source.r punctuation.section.braces.begin.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -320,7 +452,7 @@
},
{
"c": " ",
"t": "source.r meta.block.r",
"t": "source.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -331,7 +463,7 @@
},
{
"c": "x",
"t": "source.r meta.block.r variable.other.r",
"t": "source.r variable.other.r",
"r": {
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
@@ -342,7 +474,7 @@
},
{
"c": " ",
"t": "source.r meta.block.r",
"t": "source.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -353,83 +485,6 @@
},
{
"c": "+",
"t": "source.r meta.block.r keyword.operator.arithmetic.r",
"r": {
"dark_plus": "keyword.operator: #D4D4D4",
"light_plus": "keyword.operator: #000000",
"dark_vs": "keyword.operator: #D4D4D4",
"light_vs": "keyword.operator: #000000",
"hc_black": "keyword.operator: #D4D4D4"
}
},
{
"c": " ",
"t": "source.r meta.block.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "y",
"t": "source.r meta.block.r variable.other.r",
"r": {
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE"
}
},
{
"c": "}",
"t": "source.r meta.block.r punctuation.section.block.end.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "add(",
"t": "source.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "1",
"t": "source.r constant.numeric.r",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"hc_black": "constant.numeric: #B5CEA8"
}
},
{
"c": ", ",
"t": "source.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "-",
"t": "source.r keyword.operator.arithmetic.r",
"r": {
"dark_plus": "keyword.operator: #D4D4D4",
@@ -440,8 +495,63 @@
}
},
{
"c": "2",
"t": "source.r constant.numeric.r",
"c": " ",
"t": "source.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "y",
"t": "source.r variable.other.r",
"r": {
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE"
}
},
{
"c": "}",
"t": "source.r punctuation.section.braces.end.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "add",
"t": "source.r meta.function-call.r variable.function.r",
"r": {
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE"
}
},
{
"c": "(",
"t": "source.r meta.function-call.r punctuation.section.parens.begin.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "1",
"t": "source.r meta.function-call.r meta.function-call.arguments.r constant.numeric.float.decimal.r",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
@@ -451,8 +561,63 @@
}
},
{
"c": ", ",
"t": "source.r",
"c": ",",
"t": "source.r meta.function-call.r meta.function-call.arguments.r punctuation.separator.parameters.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": " ",
"t": "source.r meta.function-call.r meta.function-call.arguments.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "-",
"t": "source.r meta.function-call.r meta.function-call.arguments.r keyword.operator.arithmetic.r",
"r": {
"dark_plus": "keyword.operator: #D4D4D4",
"light_plus": "keyword.operator: #000000",
"dark_vs": "keyword.operator: #D4D4D4",
"light_vs": "keyword.operator: #000000",
"hc_black": "keyword.operator: #D4D4D4"
}
},
{
"c": "2",
"t": "source.r meta.function-call.r meta.function-call.arguments.r constant.numeric.float.decimal.r",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"hc_black": "constant.numeric: #B5CEA8"
}
},
{
"c": ",",
"t": "source.r meta.function-call.r meta.function-call.arguments.r punctuation.separator.parameters.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": " ",
"t": "source.r meta.function-call.r meta.function-call.arguments.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -463,7 +628,7 @@
},
{
"c": "2.0",
"t": "source.r constant.numeric.r",
"t": "source.r meta.function-call.r meta.function-call.arguments.r constant.numeric.float.decimal.r",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
@@ -474,7 +639,7 @@
},
{
"c": ")",
"t": "source.r",
"t": "source.r meta.function-call.r punctuation.definition.parameters.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -484,8 +649,19 @@
}
},
{
"c": "add(",
"t": "source.r",
"c": "add",
"t": "source.r meta.function-call.r variable.function.r",
"r": {
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE"
}
},
{
"c": "(",
"t": "source.r meta.function-call.r punctuation.section.parens.begin.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -496,7 +672,7 @@
},
{
"c": "1.0e10",
"t": "source.r constant.numeric.r",
"t": "source.r meta.function-call.r meta.function-call.arguments.r constant.numeric.float.decimal.r",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
@@ -506,8 +682,19 @@
}
},
{
"c": ", ",
"t": "source.r",
"c": ",",
"t": "source.r meta.function-call.r meta.function-call.arguments.r punctuation.separator.parameters.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": " ",
"t": "source.r meta.function-call.r meta.function-call.arguments.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -518,7 +705,7 @@
},
{
"c": "2.0e10",
"t": "source.r constant.numeric.r",
"t": "source.r meta.function-call.r meta.function-call.arguments.r constant.numeric.float.decimal.r",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
@@ -529,7 +716,7 @@
},
{
"c": ")",
"t": "source.r",
"t": "source.r meta.function-call.r punctuation.definition.parameters.r",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
@@ -539,7 +726,18 @@
}
},
{
"c": "paste(",
"c": "paste",
"t": "source.r support.function.r",
"r": {
"dark_plus": "support.function: #DCDCAA",
"light_plus": "support.function: #795E26",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "support.function: #DCDCAA"
}
},
{
"c": "(",
"t": "source.r",
"r": {
"dark_plus": "default: #D4D4D4",
@@ -616,7 +814,18 @@
}
},
{
"c": "paste(",
"c": "paste",
"t": "source.r support.function.r",
"r": {
"dark_plus": "support.function: #DCDCAA",
"light_plus": "support.function: #795E26",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "support.function: #DCDCAA"
}
},
{
"c": "(",
"t": "source.r",
"r": {
"dark_plus": "default: #D4D4D4",
@@ -693,7 +902,18 @@
}
},
{
"c": "paste(",
"c": "paste",
"t": "source.r support.function.r",
"r": {
"dark_plus": "support.function: #DCDCAA",
"light_plus": "support.function: #795E26",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "support.function: #DCDCAA"
}
},
{
"c": "(",
"t": "source.r",
"r": {
"dark_plus": "default: #D4D4D4",
+3 -2
View File
@@ -77,7 +77,8 @@
"path": "./syntaxes/TypeScriptReact.tmLanguage.json",
"embeddedLanguages": {
"meta.tag.tsx": "jsx-tags",
"meta.tag.without-attributes.tsx": "jsx-tags"
"meta.tag.without-attributes.tsx": "jsx-tags",
"meta.embedded.expression.tsx": "typescriptreact"
}
}
],
@@ -564,4 +565,4 @@
}
]
}
}
}
+1 -1
View File
@@ -7,7 +7,7 @@
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": ["${workspaceRoot}/../../", "${workspaceRoot}/testWorkspace", "--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out" ],
"args": ["${workspaceFolder}/../../", "${workspaceFolder}/testWorkspace", "--extensionDevelopmentPath=${workspaceFolder}", "--extensionTestsPath=${workspaceFolder}/out" ],
"stopOnEntry": false,
"sourceMaps": true,
"outDir": "out",
+1 -1
View File
@@ -1,5 +1,5 @@
// Available variables which can be used inside of strings.
// ${workspaceRoot}: the root folder of the team
// ${workspaceFolder}: the root folder of the team
// ${file}: the current opened file
// ${fileBasename}: the current opened file's basename
// ${fileDirname}: the current opened file's dirname
+2 -2
View File
@@ -7,10 +7,10 @@
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": ["${workspaceRoot}/../../", "${workspaceRoot}/test", "--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out" ],
"args": ["${workspaceFolder}/../../", "${workspaceFolder}/test", "--extensionDevelopmentPath=${workspaceFolder}", "--extensionTestsPath=${workspaceFolder}/out" ],
"stopOnEntry": false,
"sourceMaps": true,
"outDir": "${workspaceRoot}/out",
"outDir": "${workspaceFolder}/out",
"preLaunchTask": "npm"
}
]
+1 -1
View File
@@ -1,5 +1,5 @@
// Available variables which can be used inside of strings.
// ${workspaceRoot}: the root folder of the team
// ${workspaceFolder}: the root folder of the team
// ${file}: the current opened file
// ${relativeFile}: the current opened file relative to cwd
// ${fileBasename}: the current opened file's basename
+1 -1
View File
@@ -574,7 +574,7 @@
"xterm": {
"version": "3.0.0",
"from": "Tyriar/xterm.js#vscode-release/1.17",
"resolved": "git+https://github.com/Tyriar/xterm.js.git#f9b919c84d9d7b8cea1d8efb5294bb75ff5f4531"
"resolved": "git+https://github.com/Tyriar/xterm.js.git#35088059e61ba654ac78df453633c7a9272ed8bd"
},
"yauzl": {
"version": "2.8.0",
+1 -1
View File
@@ -7617,7 +7617,7 @@ declare namespace Electron {
}
interface TouchBarConstructorOptions {
items: TouchBarButton | TouchBarColorPicker | TouchBarGroup | TouchBarLabel | TouchBarPopover | TouchBarScrubber | TouchBarSegmentedControl | TouchBarSlider | TouchBarSpacer;
items: (TouchBarButton | TouchBarColorPicker | TouchBarGroup | TouchBarLabel | TouchBarPopover | TouchBarScrubber | TouchBarSegmentedControl | TouchBarSlider | TouchBarSpacer)[];
escapeItem?: TouchBarButton | TouchBarColorPicker | TouchBarGroup | TouchBarLabel | TouchBarPopover | TouchBarScrubber | TouchBarSegmentedControl | TouchBarSlider | TouchBarSpacer;
}
+1 -1
View File
@@ -22,7 +22,7 @@ export interface IJSONSchema {
minItems?: number;
maxItems?: number;
uniqueItems?: boolean;
additionalItems?: boolean;
additionalItems?: boolean | IJSONSchema;
pattern?: string;
minLength?: number;
maxLength?: number;
+4 -1
View File
@@ -39,6 +39,9 @@ export function score(target: string, query: string, cache?: { [id: string]: num
if (!target || !query) {
return 0; // return early if target or query are undefined
}
if (target.length < query.length) {
return 0; // impossible for query to be contained in target
}
const hash = target + query;
const cached = cache && cache[hash];
@@ -69,7 +72,7 @@ export function score(target: string, query: string, cache?: { [id: string]: num
}
// Same case bonus
if (target[indexOf] === query[indexOf]) {
if (target[indexOf] === query[index]) {
score += 1;
}
+4 -4
View File
@@ -11,25 +11,25 @@ import scorer = require('vs/base/common/scorer');
suite('Scorer', () => {
test('score', function () {
const target = 'HelLo-World';
const target = 'HeLlo-World';
const scores = [];
scores.push(scorer.score(target, 'HelLo-World')); // direct case match
scores.push(scorer.score(target, 'hello-world')); // direct mix-case match
scores.push(scorer.score(target, 'HW')); // direct case prefix (multiple)
scores.push(scorer.score(target, 'H')); // direct case prefix
scores.push(scorer.score(target, 'hw')); // direct mix-case prefix (multiple)
scores.push(scorer.score(target, 'H')); // direct case prefix
scores.push(scorer.score(target, 'h')); // direct mix-case prefix
scores.push(scorer.score(target, 'W')); // direct case word prefix
scores.push(scorer.score(target, 'w')); // direct mix-case word prefix
scores.push(scorer.score(target, 'Ld')); // in-string case match (multiple)
scores.push(scorer.score(target, 'L')); // in-string case match
scores.push(scorer.score(target, 'ld')); // in-string mix-case match
scores.push(scorer.score(target, 'L')); // in-string case match
scores.push(scorer.score(target, 'l')); // in-string mix-case match
scores.push(scorer.score(target, '4')); // no match
// Assert scoring order
let sortedScores = scores.sort((a, b) => b - a);
let sortedScores = scores.concat().sort((a, b) => b - a);
assert.deepEqual(scores, sortedScores);
});
+47 -1
View File
@@ -11,7 +11,7 @@ import { stopProfiling } from 'vs/base/node/profiler';
import nls = require('vs/nls');
import URI from 'vs/base/common/uri';
import { IStorageService } from 'vs/platform/storage/node/storage';
import { shell, screen, BrowserWindow, systemPreferences, app } from 'electron';
import { shell, screen, BrowserWindow, systemPreferences, app, TouchBar, nativeImage } from 'electron';
import { TPromise, TValueCallback } from 'vs/base/common/winjs.base';
import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment';
import { ILogService } from 'vs/platform/log/common/log';
@@ -26,6 +26,7 @@ import { isLinux, isMacintosh, isWindows } from 'vs/base/common/platform';
import { ICodeWindow } from 'vs/platform/windows/electron-main/windows';
import { IWorkspaceIdentifier, IWorkspacesMainService } from 'vs/platform/workspaces/common/workspaces';
import { IBackupMainService } from 'vs/platform/backup/common/backup';
import { ICommandAction } from 'vs/platform/actions/common/actions';
export interface IWindowState {
width?: number;
@@ -857,6 +858,51 @@ export class CodeWindow implements ICodeWindow {
this._win.webContents.send(channel, ...args);
}
public updateTouchBar(items: ICommandAction[][]): void {
if (!isMacintosh) {
return; // only supported on macOS
}
const groups: (Electron.TouchBarGroup | Electron.TouchBarSpacer)[] = [];
items.forEach(itemGroup => {
if (itemGroup.length) {
// Group Segments
const groupSegments = itemGroup.map(item => {
let icon: Electron.NativeImage;
if (item.iconPath) {
icon = nativeImage.createFromPath(item.iconPath);
if (icon.isEmpty()) {
icon = void 0;
}
}
return {
label: !icon ? item.title as string : void 0,
icon
};
});
// Group Touch Bar
const groupTouchBar = new TouchBar.TouchBarSegmentedControl({
segments: groupSegments,
mode: 'buttons',
segmentStyle: 'automatic',
change: (selectedIndex) => {
this.sendWhenReady('vscode:runAction', itemGroup[selectedIndex].id);
}
});
// Push and add small space between groups
groups.push(groupTouchBar);
groups.push(new TouchBar.TouchBarSpacer({ size: 'small' }));
}
});
this._win.setTouchBar(new TouchBar({ items: groups }));
}
public dispose(): void {
if (this.showTimeoutHandle) {
clearTimeout(this.showTimeoutHandle);
+29 -28
View File
@@ -19,7 +19,7 @@ import { IPathWithLineAndColumn, parseLineAndColumnAware } from 'vs/code/node/pa
import { ILifecycleService, UnloadReason, IWindowUnloadEvent } from 'vs/platform/lifecycle/electron-main/lifecycleMain';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ILogService } from 'vs/platform/log/common/log';
import { IWindowSettings, OpenContext, IPath, IWindowConfiguration, INativeOpenDialogOptions, ReadyState, IPathsToWaitFor } from 'vs/platform/windows/common/windows';
import { IWindowSettings, OpenContext, IPath, IWindowConfiguration, INativeOpenDialogOptions, ReadyState, IPathsToWaitFor, IEnterWorkspaceResult } from 'vs/platform/windows/common/windows';
import { getLastActiveWindow, findBestWindowOrFolderForFile, findWindowOnWorkspace, findWindowOnExtensionDevelopmentPath, findWindowOnWorkspaceOrFolderPath } from 'vs/code/node/windowsFinder';
import CommonEvent, { Emitter } from 'vs/base/common/event';
import product from 'vs/platform/node/product';
@@ -1294,20 +1294,29 @@ export class WindowsManager implements IWindowsMainService {
});
}
public saveAndOpenWorkspace(win: CodeWindow, path: string): TPromise<void> {
return this.workspacesManager.saveAndOpenWorkspace(win, path);
public saveAndEnterWorkspace(win: CodeWindow, path: string): TPromise<IEnterWorkspaceResult> {
return this.workspacesManager.saveAndEnterWorkspace(win, path).then(result => this.doEnterWorkspace(win, result));
}
public createAndOpenWorkspace(win: CodeWindow, folders?: string[], path?: string): TPromise<void> {
return this.workspacesManager.createAndOpenWorkspace(win, folders, path);
public createAndEnterWorkspace(win: CodeWindow, folders?: string[], path?: string): TPromise<IEnterWorkspaceResult> {
return this.workspacesManager.createAndEnterWorkspace(win, folders, path).then(result => this.doEnterWorkspace(win, result));
}
private doEnterWorkspace(win: CodeWindow, result: IEnterWorkspaceResult): IEnterWorkspaceResult {
// Mark as recently opened
this.historyService.addRecentlyOpened([result.workspace], []);
// Trigger Eevent to indicate load of workspace into window
this._onWindowReady.fire(win);
return result;
}
public openWorkspace(win?: CodeWindow): void {
this.workspacesManager.openWorkspace(win);
}
private onBeforeWindowUnload(e: IWindowUnloadEvent): void {
const windowClosing = (e.reason === UnloadReason.CLOSE);
const windowLoading = (e.reason === UnloadReason.LOAD);
@@ -1639,7 +1648,7 @@ class WorkspacesManager {
) {
}
public saveAndOpenWorkspace(window: CodeWindow, path: string): TPromise<void> {
public saveAndEnterWorkspace(window: CodeWindow, path: string): TPromise<IEnterWorkspaceResult> {
if (!window || !window.win || window.readyState !== ReadyState.READY || !window.openedWorkspace || !path || !this.isValidTargetWorkspacePath(window, path)) {
return TPromise.as(null); // return early if the window is not ready or disposed or does not have a workspace
}
@@ -1647,7 +1656,7 @@ class WorkspacesManager {
return this.doSaveAndOpenWorkspace(window, window.openedWorkspace, path);
}
public createAndOpenWorkspace(window: CodeWindow, folders?: string[], path?: string): TPromise<void> {
public createAndEnterWorkspace(window: CodeWindow, folders?: string[], path?: string): TPromise<IEnterWorkspaceResult> {
if (!window || !window.win || window.readyState !== ReadyState.READY || !this.isValidTargetWorkspacePath(window, path)) {
return TPromise.as(null); // return early if the window is not ready or disposed
}
@@ -1690,7 +1699,7 @@ class WorkspacesManager {
return true; // OK
}
private doSaveAndOpenWorkspace(window: CodeWindow, workspace: IWorkspaceIdentifier, path?: string): TPromise<void> {
private doSaveAndOpenWorkspace(window: CodeWindow, workspace: IWorkspaceIdentifier, path?: string): TPromise<IEnterWorkspaceResult> {
let savePromise: TPromise<IWorkspaceIdentifier>;
if (path) {
savePromise = this.workspacesService.saveWorkspace(workspace, path);
@@ -1701,26 +1710,18 @@ class WorkspacesManager {
return savePromise.then(workspace => {
window.focus();
// Only open workspace when the window has not vetoed this
return this.lifecycleService.unload(window, UnloadReason.RELOAD, workspace).done(veto => {
if (!veto) {
// Register window for backups and migrate current backups over
let backupPath: string;
if (!window.config.extensionDevelopmentPath) {
backupPath = this.backupService.registerWorkspaceBackupSync(workspace, window.config.backupPath);
}
// Register window for backups and migrate current backups over
let backupPath: string;
if (window.config && !window.config.extensionDevelopmentPath) {
backupPath = this.backupService.registerWorkspaceBackupSync(workspace, window.config.backupPath);
}
// Update window configuration properly based on transition to workspace
window.config.folderPath = void 0;
window.config.workspace = workspace;
window.config.backupPath = backupPath;
// Craft a new window configuration to use for the transition
const configuration: IWindowConfiguration = mixin({}, window.config);
configuration.folderPath = void 0;
configuration.workspace = workspace;
configuration.backupPath = backupPath;
// Reload
window.reload(configuration);
}
});
return { workspace, backupPath };
});
}
+1 -1
View File
@@ -122,7 +122,7 @@ class Main {
console.log(localize('foundExtension', "Found '{0}' in the marketplace.", id));
console.log(localize('installing', "Installing..."));
return this.extensionManagementService.installFromGallery(extension, false)
return this.extensionManagementService.installFromGallery(extension)
.then(() => console.log(localize('successInstall', "Extension '{0}' v{1} was successfully installed!", id, extension.version)));
});
});
+22 -19
View File
@@ -680,28 +680,31 @@ export interface IColor {
}
/**
* Represents a color format
* String representations for a color
*/
export enum ColorFormat {
RGB = 0,
HEX = 1,
HSL = 2
}
/**
* A color formatter.
* @internal
*/
export interface IColorFormatter {
readonly supportsTransparency: boolean;
readonly colorFormat: ColorFormat;
format(color: Color): string;
export interface IColorPresentation {
/**
* The label of this color presentation. It will be shown on the color
* picker header. By default this is also the text that is inserted when selecting
* this color presentation.
*/
label: string;
/**
* An [edit](#TextEdit) which is applied to a document when selecting
* this presentation for the color.
*/
textEdit?: TextEdit;
/**
* An optional array of additional [text edits](#TextEdit) that are applied when
* selecting this color presentation.
*/
additionalTextEdits?: TextEdit[];
}
/**
* A color range is a range in a text model which represents a color.
*/
export interface IColorRange {
export interface IColorInformation {
/**
* The range within the model.
@@ -721,11 +724,11 @@ export interface DocumentColorProvider {
/**
* Provides the color ranges for a specific model.
*/
provideColorRanges(model: editorCommon.IReadOnlyModel, token: CancellationToken): IColorRange[] | Thenable<IColorRange[]>;
provideDocumentColors(model: editorCommon.IReadOnlyModel, token: CancellationToken): IColorInformation[] | Thenable<IColorInformation[]>;
/**
* Provide the string representation for a color.
* Provide the string representations for a color.
*/
resolveColor(color: IColor, colorFormat: ColorFormat, token: CancellationToken): string | Thenable<string>;
provideColorPresentations(colorInfo: IColorInformation, token: CancellationToken): IColorPresentation[] | Thenable<IColorPresentation[]>;
}
export interface IResourceEdit {
@@ -149,10 +149,10 @@ export class ColorDetector implements IEditorContribution {
private updateDecorations(colorDatas: IColorData[]): void {
const decorations = colorDatas.map(c => ({
range: {
startLineNumber: c.colorRange.range.startLineNumber,
startColumn: c.colorRange.range.startColumn,
endLineNumber: c.colorRange.range.endLineNumber,
endColumn: c.colorRange.range.endColumn
startLineNumber: c.colorInfo.range.startLineNumber,
startColumn: c.colorInfo.range.startColumn,
endLineNumber: c.colorInfo.range.endLineNumber,
endColumn: c.colorInfo.range.endColumn
},
options: {}
}));
@@ -163,12 +163,12 @@ export class ColorDetector implements IEditorContribution {
this._decorationsIds.forEach((id, i) => this._colorDatas.set(id, colorDatas[i]));
}
private updateColorDecorators(colorInfos: IColorData[]): void {
private updateColorDecorators(colorData: IColorData[]): void {
let decorations = [];
let newDecorationsTypes: { [key: string]: boolean } = {};
for (let i = 0; i < colorInfos.length && decorations.length < MAX_DECORATORS; i++) {
const { red, green, blue, alpha } = colorInfos[i].colorRange.color;
for (let i = 0; i < colorData.length && decorations.length < MAX_DECORATORS; i++) {
const { red, green, blue, alpha } = colorData[i].colorInfo.color;
const rgba = new RGBA(Math.round(red * 255), Math.round(green * 255), Math.round(blue * 255), alpha);
let subKey = hash(rgba).toString(16);
let color = `rgba(${rgba.r}, ${rgba.g}, ${rgba.b}, ${rgba.a})`;
@@ -195,10 +195,10 @@ export class ColorDetector implements IEditorContribution {
newDecorationsTypes[key] = true;
decorations.push({
range: {
startLineNumber: colorInfos[i].colorRange.range.startLineNumber,
startColumn: colorInfos[i].colorRange.range.startColumn,
endLineNumber: colorInfos[i].colorRange.range.endLineNumber,
endColumn: colorInfos[i].colorRange.range.endColumn
startLineNumber: colorData[i].colorInfo.range.startLineNumber,
startColumn: colorData[i].colorInfo.range.startColumn,
endLineNumber: colorData[i].colorInfo.range.endLineNumber,
endColumn: colorData[i].colorInfo.range.endColumn
},
options: this._codeEditorService.resolveDecorationOptions(key, true)
});
@@ -5,8 +5,7 @@
import Event, { Emitter } from 'vs/base/common/event';
import { Color } from 'vs/base/common/color';
import { IColorFormatter } from 'vs/editor/common/modes';
import { HexFormatter, HSLFormatter, RGBFormatter } from '../common/colorFormatter';
import { IColorPresentation } from 'vs/editor/common/modes';
export class ColorPickerModel {
@@ -26,9 +25,21 @@ export class ColorPickerModel {
this._onDidChangeColor.fire(color);
}
get formatter(): IColorFormatter { return this.formatters[this.formatterIndex]; }
get presentation(): IColorPresentation { return this.colorPresentations[this.presentationIndex]; }
readonly formatters: IColorFormatter[];
private _colorPresentations: IColorPresentation[];
get colorPresentations(): IColorPresentation[] {
return this._colorPresentations;
}
set colorPresentations(colorPresentations: IColorPresentation[]) {
this._colorPresentations = colorPresentations;
if (this.presentationIndex > colorPresentations.length - 1) {
this.presentationIndex = 0;
}
this._onDidChangePresentation.fire(this.presentation);
}
private _onColorFlushed = new Emitter<Color>();
readonly onColorFlushed: Event<Color> = this._onColorFlushed.event;
@@ -36,29 +47,26 @@ export class ColorPickerModel {
private _onDidChangeColor = new Emitter<Color>();
readonly onDidChangeColor: Event<Color> = this._onDidChangeColor.event;
private _onDidChangeFormatter = new Emitter<IColorFormatter>();
readonly onDidChangeFormatter: Event<IColorFormatter> = this._onDidChangeFormatter.event;
private _onDidChangePresentation = new Emitter<IColorPresentation>();
readonly onDidChangePresentation: Event<IColorPresentation> = this._onDidChangePresentation.event;
constructor(color: Color, private formatterIndex: number) {
constructor(color: Color, availableColorPresentations: IColorPresentation[], private presentationIndex: number) {
this.originalColor = color;
this._color = color;
this.formatters = [
new RGBFormatter(),
new HexFormatter(),
new HSLFormatter()
];
this._colorPresentations = availableColorPresentations;
}
selectNextColorFormat(): void {
this.formatterIndex = (this.formatterIndex + 1) % this.formatters.length;
selectNextColorPresentation(): void {
this.presentationIndex = (this.presentationIndex + 1) % this.colorPresentations.length;
this.flushColor();
this._onDidChangeFormatter.fire(this.formatter);
this._onDidChangePresentation.fire(this.presentation);
}
guessColorFormat(color: Color, originalText: string): void {
for (let i = 0; i < this.formatters.length; i++) {
if (originalText === this.formatters[i].format(color)) {
this.formatterIndex = i;
guessColorPresentation(color: Color, originalText: string): void {
for (let i = 0; i < this.colorPresentations.length; i++) {
if (originalText === this.colorPresentations[i].label) {
this.presentationIndex = i;
this._onDidChangePresentation.fire(this.presentation);
break;
}
}
@@ -38,24 +38,25 @@ export class ColorPickerHeader extends Disposable {
this.backgroundColor = theme.getColor(editorHoverBackground) || Color.white;
}));
this._register(dom.addDisposableListener(this.pickedColorNode, dom.EventType.CLICK, () => this.model.selectNextColorFormat()));
this._register(dom.addDisposableListener(this.pickedColorNode, dom.EventType.CLICK, () => this.model.selectNextColorPresentation()));
this._register(dom.addDisposableListener(colorBox, dom.EventType.CLICK, () => {
this.model.color = this.model.originalColor;
this.model.flushColor();
}));
this._register(model.onDidChangeColor(this.onDidChangeColor, this));
this._register(model.onDidChangeFormatter(this.onDidChangeFormatter, this));
this.onDidChangeColor(this.model.color);
this._register(model.onDidChangePresentation(this.onDidChangePresentation, this));
this.pickedColorNode.style.backgroundColor = Color.Format.CSS.format(model.color);
dom.toggleClass(this.pickedColorNode, 'light', model.color.rgba.a < 0.5 ? this.backgroundColor.isLighter() : model.color.isLighter());
}
private onDidChangeColor(color: Color): void {
this.pickedColorNode.style.backgroundColor = Color.Format.CSS.format(color);
dom.toggleClass(this.pickedColorNode, 'light', color.rgba.a < 0.5 ? this.backgroundColor.isLighter() : color.isLighter());
this.onDidChangeFormatter();
this.onDidChangePresentation();
}
private onDidChangeFormatter(): void {
this.pickedColorNode.textContent = this.model.formatter.format(this.model.color);
private onDidChangePresentation(): void {
this.pickedColorNode.textContent = this.model.presentation.label;
}
}
@@ -4,22 +4,22 @@
*--------------------------------------------------------------------------------------------*/
import { TPromise } from 'vs/base/common/winjs.base';
import { ColorProviderRegistry, DocumentColorProvider, IColorRange, IColor, ColorFormat } from 'vs/editor/common/modes';
import { ColorProviderRegistry, DocumentColorProvider, IColorInformation, IColorPresentation } from 'vs/editor/common/modes';
import { asWinJsPromise } from 'vs/base/common/async';
import { IReadOnlyModel } from 'vs/editor/common/editorCommon';
export interface IColorData {
colorRange: IColorRange;
colorInfo: IColorInformation;
provider: DocumentColorProvider;
}
export function getColors(model: IReadOnlyModel): TPromise<IColorData[]> {
const colors: IColorData[] = [];
const providers = ColorProviderRegistry.ordered(model).reverse();
const promises = providers.map(provider => asWinJsPromise(token => provider.provideColorRanges(model, token)).then(result => {
const promises = providers.map(provider => asWinJsPromise(token => provider.provideDocumentColors(model, token)).then(result => {
if (Array.isArray(result)) {
for (let colorRange of result) {
colors.push({ colorRange, provider });
for (let colorInfo of result) {
colors.push({ colorInfo, provider });
}
}
}));
@@ -27,6 +27,6 @@ export function getColors(model: IReadOnlyModel): TPromise<IColorData[]> {
return TPromise.join(promises).then(() => colors);
}
export function resolveColor(color: IColor, colorFormat: ColorFormat, provider: DocumentColorProvider): TPromise<string> {
return asWinJsPromise(token => provider.resolveColor(color, colorFormat, token));
export function getColorPresentations(colorInfo: IColorInformation, provider: DocumentColorProvider): TPromise<IColorPresentation[]> {
return asWinJsPromise(token => provider.provideColorPresentations(colorInfo, token));
}
@@ -1,58 +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 { IColorFormatter, ColorFormat } from 'vs/editor/common/modes';
import { Color } from 'vs/base/common/color';
function normalize(value: number, min: number, max: number): number {
return value * (max - min) + min;
}
export class RGBFormatter implements IColorFormatter {
readonly supportsTransparency: boolean = true;
readonly colorFormat: ColorFormat = ColorFormat.RGB;
format(color: Color): string {
const rgb = color.rgba;
if (rgb.a === 1) {
return `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`;
} else {
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${rgb.a})`;
}
}
}
export class HexFormatter implements IColorFormatter {
readonly supportsTransparency: boolean = false;
readonly colorFormat: ColorFormat = ColorFormat.HEX;
_toTwoDigitHex(n: number): string {
const r = n.toString(16);
return r.length !== 2 ? '0' + r : r;
}
format(color: Color): string {
const rgb = color.rgba;
if (rgb.a === 1) {
return `#${this._toTwoDigitHex(rgb.r).toUpperCase()}${this._toTwoDigitHex(rgb.g).toUpperCase()}${this._toTwoDigitHex(rgb.b).toUpperCase()}`;
} else {
return `#${this._toTwoDigitHex(rgb.r).toUpperCase()}${this._toTwoDigitHex(rgb.g).toUpperCase()}${this._toTwoDigitHex(rgb.b).toUpperCase()}${this._toTwoDigitHex(Math.round(rgb.a * 255)).toUpperCase()}`;
}
}
}
export class HSLFormatter implements IColorFormatter {
readonly supportsTransparency: boolean = true;
readonly colorFormat: ColorFormat = ColorFormat.HSL;
format(color: Color): string {
const hsla = color.hsla;
if (hsla.a === 1) {
return `hsl(${hsla.h}, ${normalize(hsla.s, 0, 100).toFixed(0)}%, ${normalize(hsla.l, 0, 100).toFixed(0)}%)`;
} else {
return `hsla(${hsla.h}, ${normalize(hsla.s, 0, 100).toFixed(0)}%, ${normalize(hsla.l, 0, 100).toFixed(0)}%, ${hsla.a})`;
}
}
}
@@ -1,32 +0,0 @@
/*---------------------------------------------------------------------------------------------
* 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 { Color, RGBA, HSLA } from 'vs/base/common/color';
import { RGBFormatter, HexFormatter, HSLFormatter } from 'vs/editor/contrib/colorPicker/common/colorFormatter';
suite('ColorFormatter', () => {
test('documentation', () => {
const color = new Color(new RGBA(255, 127, 0));
const rgb = new RGBFormatter();
assert.equal(rgb.format(color), 'rgb(255, 127, 0)');
const hex = new HexFormatter();
assert.equal(hex.format(color), '#FF7F00');
const hsl = new HSLFormatter();
assert.equal(hsl.format(color), 'hsl(30, 100%, 50%)');
});
test('bug#32323', () => {
const color = new Color(new HSLA(121, 0.45, 0.29, 0.61));
const rgba = color.rgba;
const color2 = new Color(new RGBA(rgba.r, rgba.g, rgba.b, rgba.a));
const hsla = new HSLFormatter();
assert.equal(hsla.format(color2), 'hsla(121, 45%, 29%, 0.61)');
});
});
@@ -22,7 +22,7 @@ import { ColorPickerWidget } from 'vs/editor/contrib/colorPicker/browser/colorPi
import { ColorDetector } from 'vs/editor/contrib/colorPicker/browser/colorDetector';
import { Color, RGBA } from 'vs/base/common/color';
import { IDisposable, empty as EmptyDisposable, dispose, combinedDisposable } from 'vs/base/common/lifecycle';
import { resolveColor } from 'vs/editor/contrib/colorPicker/common/color';
import { getColorPresentations } from 'vs/editor/contrib/colorPicker/common/color';
const $ = dom.$;
class ColorHover {
@@ -96,7 +96,7 @@ class ModesContentComputer implements IHoverComputer<HoverPart[]> {
if (!didFindColor && colorData) {
didFindColor = true;
const { color } = colorData.colorRange;
const { color } = colorData.colorInfo;
return new ColorHover(d.range, color, colorData.provider);
} else {
if (isEmptyMarkdownString(d.options.hoverMessage)) {
@@ -294,6 +294,7 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
highlightRange = messages[0].range,
fragment = document.createDocumentFragment();
let containColorPicker = false;
messages.forEach((msg) => {
if (!msg.range) {
return;
@@ -310,46 +311,88 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
fragment.appendChild($('div.hover-row', null, renderedContents));
});
} else {
containColorPicker = true;
const { red, green, blue, alpha } = msg.color;
const rgba = new RGBA(red * 255, green * 255, blue * 255, alpha);
const color = new Color(rgba);
const model = new ColorPickerModel(color, 0);
const originalText = this._editor.getModel().getValueInRange(msg.range);
model.guessColorFormat(color, originalText);
const widget = new ColorPickerWidget(fragment, model, this._editor.getConfiguration().pixelRatio);
const editorModel = this._editor.getModel();
let range = new Range(msg.range.startLineNumber, msg.range.startColumn, msg.range.endLineNumber, msg.range.endColumn);
let colorInfo = { range: msg.range, color: msg.color };
const updateEditorModel = () => {
const color = {
red: model.color.rgba.r / 255,
green: model.color.rgba.g / 255,
blue: model.color.rgba.b / 255,
alpha: model.color.rgba.a
};
resolveColor(color, model.formatter.colorFormat, msg.provider).then(text => {
editorModel.pushEditOperations([], [{ identifier: null, range, text, forceMoveMarkers: false }], () => []);
// create blank olor picker model and widget first to ensure it's positioned correctly.
const model = new ColorPickerModel(color, [], 0);
const widget = new ColorPickerWidget(fragment, model, this._editor.getConfiguration().pixelRatio);
getColorPresentations(colorInfo, msg.provider).then(colorPresentations => {
model.colorPresentations = colorPresentations;
const originalText = this._editor.getModel().getValueInRange(msg.range);
model.guessColorPresentation(color, originalText);
const updateEditorModel = () => {
let textEdits;
let newRange;
if (model.presentation.textEdit) {
textEdits = [model.presentation.textEdit];
console.log('insert text');
newRange = new Range(
model.presentation.textEdit.range.startLineNumber,
model.presentation.textEdit.range.startColumn,
model.presentation.textEdit.range.endLineNumber,
model.presentation.textEdit.range.endColumn
);
newRange = newRange.setEndPosition(newRange.endLineNumber, newRange.startColumn + model.presentation.textEdit.text.length);
} else {
textEdits = [{ identifier: null, range, text: model.presentation.label, forceMoveMarkers: false }];
newRange = range.setEndPosition(range.endLineNumber, range.startColumn + model.presentation.label.length);
}
editorModel.pushEditOperations([], textEdits, () => []);
if (model.presentation.additionalTextEdits) {
textEdits = [...model.presentation.additionalTextEdits];
editorModel.pushEditOperations([], textEdits, () => []);
this.hide();
}
this._editor.pushUndoStop();
range = range.setEndPosition(range.endLineNumber, range.startColumn + text.length);
range = newRange;
};
const updateColorPresentations = (color: Color) => {
return getColorPresentations({
range: range,
color: {
red: color.rgba.r / 255,
green: color.rgba.g / 255,
blue: color.rgba.b / 255,
alpha: color.rgba.a
}
}, msg.provider).then((colorPresentations) => {
model.colorPresentations = colorPresentations;
});
};
const colorListener = model.onColorFlushed((color: Color) => {
updateColorPresentations(color).then(updateEditorModel);
});
};
const colorChangeListener = model.onDidChangeColor(updateColorPresentations);
const colorListener = model.onColorFlushed(updateEditorModel);
this._colorPicker = widget;
this.showAt(new Position(renderRange.startLineNumber, renderColumn), this._shouldFocus);
this.updateContents(fragment);
this._colorPicker.layout();
this._colorPicker = widget;
this.renderDisposable = combinedDisposable([colorListener, widget]);
this.renderDisposable = combinedDisposable([colorListener, colorChangeListener, widget]);
});
}
});
// show
this.showAt(new Position(renderRange.startLineNumber, renderColumn), this._shouldFocus);
this.updateContents(fragment);
if (this._colorPicker) {
this._colorPicker.layout();
if (!containColorPicker) {
this.showAt(new Position(renderRange.startLineNumber, renderColumn), this._shouldFocus);
this.updateContents(fragment);
}
this._isChangingDecorations = true;
@@ -738,7 +738,6 @@ export function createMonacoLanguagesAPI(): typeof monaco.languages {
DocumentHighlightKind: modes.DocumentHighlightKind,
CompletionItemKind: CompletionItemKind,
SymbolKind: modes.SymbolKind,
IndentAction: IndentAction,
ColorFormat: modes.ColorFormat
IndentAction: IndentAction
};
}
+22 -9
View File
@@ -4823,18 +4823,31 @@ declare module monaco.languages {
}
/**
* Represents a color format
* String representations for a color
*/
export enum ColorFormat {
RGB = 0,
HEX = 1,
HSL = 2,
export interface IColorPresentation {
/**
* The label of this color presentation. It will be shown on the color
* picker header. By default this is also the text that is inserted when selecting
* this color presentation.
*/
label: string;
/**
* An [edit](#TextEdit) which is applied to a document when selecting
* this presentation for the color.
*/
textEdit?: TextEdit;
/**
* An optional array of additional [text edits](#TextEdit) that are applied when
* selecting this color presentation.
*/
additionalTextEdits?: TextEdit[];
}
/**
* A color range is a range in a text model which represents a color.
*/
export interface IColorRange {
export interface IColorInformation {
/**
* The range within the model.
*/
@@ -4852,11 +4865,11 @@ declare module monaco.languages {
/**
* Provides the color ranges for a specific model.
*/
provideColorRanges(model: editor.IReadOnlyModel, token: CancellationToken): IColorRange[] | Thenable<IColorRange[]>;
provideDocumentColors(model: editor.IReadOnlyModel, token: CancellationToken): IColorInformation[] | Thenable<IColorInformation[]>;
/**
* Provide the string representation for a color.
* Provide the string representations for a color.
*/
resolveColor(color: IColor, colorFormat: ColorFormat, token: CancellationToken): string | Thenable<string>;
provideColorPresentations(colorInfo: IColorInformation, token: CancellationToken): IColorPresentation[] | Thenable<IColorPresentation[]>;
}
export interface IResourceEdit {
@@ -24,6 +24,7 @@ export interface ICommandAction {
title: string | ILocalizedString;
category?: string | ILocalizedString;
iconClass?: string;
iconPath?: string;
}
export interface IMenuItem {
@@ -52,6 +53,7 @@ export class MenuId {
static readonly CommandPalette = new MenuId('14');
static readonly ViewTitle = new MenuId('15');
static readonly ViewItemContext = new MenuId('16');
static readonly TouchBarContext = new MenuId('17');
constructor(private _id: string) {
@@ -30,6 +30,7 @@ namespace schema {
export function parseMenuId(value: string): MenuId {
switch (value) {
case 'commandPalette': return MenuId.CommandPalette;
case 'touchBar': return MenuId.TouchBarContext;
case 'editor/title': return MenuId.EditorTitle;
case 'editor/context': return MenuId.EditorContext;
case 'explorer/context': return MenuId.ExplorerContext;
@@ -104,6 +105,11 @@ namespace schema {
type: 'array',
items: menuItem
},
'touchBar': {
description: localize('menus.touchBar', "The touch bar (macOS only)"),
type: 'array',
items: menuItem
},
'editor/title': {
description: localize('menus.editorTitle', "The editor title menu"),
type: 'array',
@@ -278,20 +284,23 @@ ExtensionsRegistry.registerExtensionPoint<schema.IUserFriendlyCommand | schema.I
let { icon, category, title, command } = userFriendlyCommand;
let iconClass: string;
let iconPath: string;
if (icon) {
iconClass = ids.nextId();
if (typeof icon === 'string') {
const path = join(extension.description.extensionFolderPath, icon);
createCSSRule(`.icon.${iconClass}`, `background-image: url("${URI.file(path).toString()}")`);
iconPath = join(extension.description.extensionFolderPath, icon);
createCSSRule(`.icon.${iconClass}`, `background-image: url("${URI.file(iconPath).toString()}")`);
} else {
const light = join(extension.description.extensionFolderPath, icon.light);
const dark = join(extension.description.extensionFolderPath, icon.dark);
createCSSRule(`.icon.${iconClass}`, `background-image: url("${URI.file(light).toString()}")`);
createCSSRule(`.vs-dark .icon.${iconClass}, .hc-black .icon.${iconClass}`, `background-image: url("${URI.file(dark).toString()}")`);
iconPath = join(extension.description.extensionFolderPath, icon.dark);
}
}
if (MenuRegistry.addCommand({ id: command, title, category, iconClass })) {
if (MenuRegistry.addCommand({ id: command, title, category, iconClass, iconPath })) {
extension.collector.info(localize('dup', "Command `{0}` appears multiple times in the `commands` section.", userFriendlyCommand.command));
}
}
@@ -46,6 +46,14 @@ class MockExtensionService implements IExtensionService {
public restartExtensionHost(): void {
throw new Error('Method not implemented.');
}
public startExtensionHost(): void {
throw new Error('Method not implemented.');
}
public stopExtensionHost(): void {
throw new Error('Method not implemented.');
}
}
const extensionService = new MockExtensionService();
@@ -35,6 +35,10 @@ class SimpleExtensionService implements IExtensionService {
}
restartExtensionHost(): void {
}
startExtensionHost(): void {
}
stopExtensionHost(): void {
}
}
suite('CommandService', function () {
@@ -41,6 +41,7 @@ export interface ParsedArgs {
'open-url'?: string | string[];
'skip-getting-started'?: boolean;
'sticky-quickopen'?: boolean;
'export-default-configuration'?: string;
}
export const IEnvironmentService = createDecorator<IEnvironmentService>('environmentService');
+2 -1
View File
@@ -26,7 +26,8 @@ const options: minimist.Opts = {
'debugSearch',
'debugBrkSearch',
'open-url',
'enable-proposed-api'
'enable-proposed-api',
'export-default-configuration'
],
boolean: [
'help',
@@ -250,7 +250,7 @@ export interface IExtensionManagementService {
onDidUninstallExtension: Event<DidUninstallExtensionEvent>;
install(zipPath: string): TPromise<void>;
installFromGallery(extension: IGalleryExtension, promptToInstallDependencies?: boolean): TPromise<void>;
installFromGallery(extension: IGalleryExtension): TPromise<void>;
uninstall(extension: ILocalExtension, force?: boolean): TPromise<void>;
getInstalled(type?: LocalExtensionType): TPromise<ILocalExtension[]>;
}
@@ -43,7 +43,7 @@ export class ExtensionManagementChannel implements IExtensionManagementChannel {
case 'event:onUninstallExtension': return eventToCall(this.onUninstallExtension);
case 'event:onDidUninstallExtension': return eventToCall(this.onDidUninstallExtension);
case 'install': return this.service.install(arg);
case 'installFromGallery': return this.service.installFromGallery(arg[0], arg[1]);
case 'installFromGallery': return this.service.installFromGallery(arg[0]);
case 'uninstall': return this.service.uninstall(arg[0], arg[1]);
case 'getInstalled': return this.service.getInstalled(arg);
}
@@ -73,8 +73,8 @@ export class ExtensionManagementChannelClient implements IExtensionManagementSer
return this.channel.call('install', zipPath);
}
installFromGallery(extension: IGalleryExtension, promptToInstallDependencies: boolean = true): TPromise<void> {
return this.channel.call('installFromGallery', [extension, promptToInstallDependencies]);
installFromGallery(extension: IGalleryExtension): TPromise<void> {
return this.channel.call('installFromGallery', [extension]);
}
uninstall(extension: ILocalExtension, force = false): TPromise<void> {
@@ -336,6 +336,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
text = text.trim();
if (text) {
text = text.length < 200 ? text : text.substring(0, 200);
query = query.withFilter(FilterType.SearchText, text);
}
@@ -121,7 +121,7 @@ export class ExtensionManagementService implements IExtensionManagementService {
});
}
installFromGallery(extension: IGalleryExtension, promptToInstallDependencies: boolean = true): TPromise<void> {
installFromGallery(extension: IGalleryExtension): TPromise<void> {
const id = getLocalExtensionIdFromGallery(extension, extension.version);
return this.isObsolete(id).then(isObsolete => {
@@ -129,7 +129,7 @@ export class ExtensionManagementService implements IExtensionManagementService {
return TPromise.wrapError<void>(new Error(nls.localize('restartCode', "Please restart Code before reinstalling {0}.", extension.displayName || extension.name)));
}
this._onInstallExtension.fire({ id, gallery: extension });
return this.installCompatibleVersion(extension, true, promptToInstallDependencies)
return this.installCompatibleVersion(extension, true)
.then(
local => this._onDidInstallExtension.fire({ id, local, gallery: extension }),
error => {
@@ -140,31 +140,10 @@ export class ExtensionManagementService implements IExtensionManagementService {
});
}
private installCompatibleVersion(extension: IGalleryExtension, installDependencies: boolean, promptToInstallDependencies: boolean): TPromise<ILocalExtension> {
private installCompatibleVersion(extension: IGalleryExtension, installDependencies: boolean): TPromise<ILocalExtension> {
return this.galleryService.loadCompatibleVersion(extension)
.then(compatibleVersion => this.getDependenciesToInstall(extension, installDependencies)
.then(dependencies => {
if (!dependencies.length) {
return this.downloadAndInstall(compatibleVersion);
}
if (promptToInstallDependencies) {
const message = nls.localize('installDependeciesConfirmation', "Installing '{0}' also installs its dependencies. Would you like to continue?", extension.displayName);
const options = [
nls.localize('install', "Yes"),
nls.localize('doNotInstall', "No")
];
return this.choiceService.choose(Severity.Info, message, options, 1, true)
.then(value => {
if (value === 0) {
return this.installWithDependencies(compatibleVersion);
}
return TPromise.wrapError<ILocalExtension>(errors.canceled());
}, error => TPromise.wrapError<ILocalExtension>(errors.canceled()));
} else {
return this.installWithDependencies(compatibleVersion);
}
})
);
.then(dependencies => dependencies.length ? this.installWithDependencies(compatibleVersion) : this.downloadAndInstall(compatibleVersion)));
}
private getDependenciesToInstall(extension: IGalleryExtension, checkDependecies: boolean): TPromise<string[]> {
@@ -202,7 +181,7 @@ export class ExtensionManagementService implements IExtensionManagementService {
}
return this.downloadAndInstall(extension)
.then(localExtension => {
return TPromise.join(dependecies.map((dep) => this.installCompatibleVersion(dep, false, false)))
return TPromise.join(dependecies.map((dep) => this.installCompatibleVersion(dep, false)))
.then(installedLocalExtensions => {
for (const installedLocalExtension of installedLocalExtensions) {
const gallery = this.getGalleryExtensionForLocalExtension(dependecies, installedLocalExtension);
@@ -294,14 +273,26 @@ export class ExtensionManagementService implements IExtensionManagementService {
}
uninstall(extension: ILocalExtension, force = false): TPromise<void> {
return this.removeOutdatedExtensions().then(() => {
return this.scanUserExtensions().then(installed => {
const promises = installed
.filter(e => e.manifest.publisher === extension.manifest.publisher && e.manifest.name === extension.manifest.name)
.map(e => this.checkForDependenciesAndUninstall(e, installed, force));
return TPromise.join(promises);
});
}).then(() => { /* drop resolved value */ });
return this.removeOutdatedExtensions()
.then(() =>
this.scanUserExtensions()
.then(installed => {
const promises = installed
.filter(e => e.manifest.publisher === extension.manifest.publisher && e.manifest.name === extension.manifest.name)
.map(e => this.checkForDependenciesAndUninstall(e, installed, force));
return TPromise.join(promises).then(null, errors => TPromise.wrapError(this.joinErrors(errors)));
}))
.then(() => { /* drop resolved value */ });
}
private joinErrors(errors: (Error | string)[]): Error {
if (errors.length === 1) {
return errors[0] instanceof Error ? <Error>errors[0] : new Error(<string>errors[0]);
}
return errors.reduce<Error>((previousValue: Error, currentValue: Error | string) => {
return new Error(`${previousValue.message}\n${currentValue instanceof Error ? currentValue.message : currentValue}`);
}, new Error(''));
}
private checkForDependenciesAndUninstall(extension: ILocalExtension, installed: ILocalExtension[], force: boolean): TPromise<void> {
@@ -102,4 +102,14 @@ export interface IExtensionService {
* Restarts the extension host.
*/
restartExtensionHost(): void;
/**
* Starts the extension host.
*/
startExtensionHost(): void;
/**
* Stops the extension host.
*/
stopExtensionHost(): void;
}
+6 -4
View File
@@ -170,12 +170,12 @@ export function parseStorage(storage: IStorage): IParsedStorage {
};
}
export function migrateStorageToMultiRootWorkspace(fromWorkspaceId: string, toWorkspaceId: IWorkspaceIdentifier, storage: IStorage): void {
export function migrateStorageToMultiRootWorkspace(fromWorkspaceId: string, toWorkspace: IWorkspaceIdentifier, storage: IStorage): string {
const parsed = parseStorage(storage);
const newStorageKey = URI.from({ path: toWorkspaceId.id, scheme: 'root' }).toString();
const newWorkspaceId = URI.from({ path: toWorkspace.id, scheme: 'root' }).toString();
// Find in which location the workspace storage is to be migrated rom
// Find in which location the workspace storage is to be migrated from
let storageForWorkspace: StorageObject;
if (parsed.multiRoot.has(fromWorkspaceId)) {
storageForWorkspace = parsed.multiRoot.get(fromWorkspaceId);
@@ -192,7 +192,9 @@ export function migrateStorageToMultiRootWorkspace(fromWorkspaceId: string, toWo
return; // make sure to never migrate the workspace identifier
}
storage.setItem(`${StorageService.WORKSPACE_PREFIX}${newStorageKey}/${key}`, storageForWorkspace[key]);
storage.setItem(`${StorageService.WORKSPACE_PREFIX}${newWorkspaceId}/${key}`, storageForWorkspace[key]);
});
}
return newWorkspaceId;
}
@@ -33,16 +33,27 @@ export class StorageService implements IStorageService {
private _globalStorage: IStorage;
private workspaceKey: string;
private _workspaceId: string;
constructor(
globalStorage: IStorage,
workspaceStorage: IStorage,
private workspaceId?: string,
workspaceId?: string,
legacyWorkspaceId?: number
) {
this._globalStorage = globalStorage;
this._workspaceStorage = workspaceStorage || globalStorage;
this.setWorkspaceId(workspaceId, legacyWorkspaceId);
}
public get workspaceId(): string {
return this._workspaceId;
}
public setWorkspaceId(workspaceId: string, legacyWorkspaceId?: number): void {
this._workspaceId = workspaceId;
// Calculate workspace storage key
this.workspaceKey = this.getWorkspaceKey(workspaceId);
@@ -53,10 +64,6 @@ export class StorageService implements IStorageService {
}
}
public get storageId(): string {
return this.workspaceId;
}
public get globalStorage(): IStorage {
return this._globalStorage;
}
+14 -4
View File
@@ -13,6 +13,7 @@ import { IProcessEnvironment } from 'vs/base/common/platform';
import { ParsedArgs } from 'vs/platform/environment/common/environment';
import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { IRecentlyOpened } from 'vs/platform/history/common/history';
import { ICommandAction } from 'vs/platform/actions/common/actions';
export const IWindowsService = createDecorator<IWindowsService>('windowsService');
@@ -26,6 +27,11 @@ export interface INativeOpenDialogOptions {
telemetryExtraData?: ITelemetryData;
}
export interface IEnterWorkspaceResult {
workspace: IWorkspaceIdentifier;
backupPath: string;
}
export interface IWindowsService {
_serviceBrand: any;
@@ -42,8 +48,8 @@ export interface IWindowsService {
toggleDevTools(windowId: number): TPromise<void>;
closeWorkspace(windowId: number): TPromise<void>;
openWorkspace(windowId: number): TPromise<void>;
createAndOpenWorkspace(windowId: number, folders?: string[], path?: string): TPromise<void>;
saveAndOpenWorkspace(windowId: number, path: string): TPromise<void>;
createAndEnterWorkspace(windowId: number, folders?: string[], path?: string): TPromise<IEnterWorkspaceResult>;
saveAndEnterWorkspace(windowId: number, path: string): TPromise<IEnterWorkspaceResult>;
toggleFullScreen(windowId: number): TPromise<void>;
setRepresentedFilename(windowId: number, fileName: string): TPromise<void>;
addRecentlyOpened(files: string[]): TPromise<void>;
@@ -68,6 +74,9 @@ export interface IWindowsService {
mergeAllWindowTabs(): TPromise<void>;
toggleWindowTabsBar(): TPromise<void>;
// macOS TouchBar
updateTouchBar(windowId: number, items: ICommandAction[][]): TPromise<void>;
// Shared process
whenSharedProcessReady(): TPromise<void>;
toggleSharedProcess(): TPromise<void>;
@@ -106,8 +115,9 @@ export interface IWindowService {
toggleDevTools(): TPromise<void>;
closeWorkspace(): TPromise<void>;
openWorkspace(): TPromise<void>;
createAndOpenWorkspace(folders?: string[], path?: string): TPromise<void>;
saveAndOpenWorkspace(path: string): TPromise<void>;
updateTouchBar(items: ICommandAction[][]): TPromise<void>;
createAndEnterWorkspace(folders?: string[], path?: string): TPromise<IEnterWorkspaceResult>;
saveAndEnterWorkspace(path: string): TPromise<IEnterWorkspaceResult>;
toggleFullScreen(): TPromise<void>;
setRepresentedFilename(fileName: string): TPromise<void>;
getRecentlyOpened(): TPromise<IRecentlyOpened>;
+16 -9
View File
@@ -8,9 +8,10 @@
import { TPromise } from 'vs/base/common/winjs.base';
import Event, { buffer } from 'vs/base/common/event';
import { IChannel, eventToCall, eventFromCall } from 'vs/base/parts/ipc/common/ipc';
import { IWindowsService, INativeOpenDialogOptions } from './windows';
import { IWindowsService, INativeOpenDialogOptions, IEnterWorkspaceResult } from './windows';
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { IRecentlyOpened } from 'vs/platform/history/common/history';
import { ICommandAction } from 'vs/platform/actions/common/actions';
export interface IWindowsChannel extends IChannel {
call(command: 'event:onWindowOpen'): TPromise<number>;
@@ -23,8 +24,8 @@ export interface IWindowsChannel extends IChannel {
call(command: 'toggleDevTools', arg: number): TPromise<void>;
call(command: 'closeWorkspace', arg: number): TPromise<void>;
call(command: 'openWorkspace', arg: number): TPromise<void>;
call(command: 'createAndOpenWorkspace', arg: [number, string[], string]): TPromise<void>;
call(command: 'saveAndOpenWorkspace', arg: [number, string]): TPromise<void>;
call(command: 'createAndEnterWorkspace', arg: [number, string[], string]): TPromise<IEnterWorkspaceResult>;
call(command: 'saveAndEnterWorkspace', arg: [number, string]): TPromise<IEnterWorkspaceResult>;
call(command: 'toggleFullScreen', arg: number): TPromise<void>;
call(command: 'setRepresentedFilename', arg: [number, string]): TPromise<void>;
call(command: 'addRecentlyOpened', arg: string[]): TPromise<void>;
@@ -36,6 +37,7 @@ export interface IWindowsChannel extends IChannel {
call(command: 'moveWindowTabToNewWindow', arg: number): TPromise<void>;
call(command: 'mergeAllWindowTabs', arg: number): TPromise<void>;
call(command: 'toggleWindowTabsBar', arg: number): TPromise<void>;
call(command: 'updateTouchBar', arg: [number, ICommandAction[][]]): TPromise<void>;
call(command: 'focusWindow', arg: number): TPromise<void>;
call(command: 'closeWindow', arg: number): TPromise<void>;
call(command: 'isFocused', arg: number): TPromise<boolean>;
@@ -85,8 +87,8 @@ export class WindowsChannel implements IWindowsChannel {
case 'toggleDevTools': return this.service.toggleDevTools(arg);
case 'closeWorkspace': return this.service.closeWorkspace(arg);
case 'openWorkspace': return this.service.openWorkspace(arg);
case 'createAndOpenWorkspace': return this.service.createAndOpenWorkspace(arg[0], arg[1], arg[2]);
case 'saveAndOpenWorkspace': return this.service.saveAndOpenWorkspace(arg[0], arg[1]);
case 'createAndEnterWorkspace': return this.service.createAndEnterWorkspace(arg[0], arg[1], arg[2]);
case 'saveAndEnterWorkspace': return this.service.saveAndEnterWorkspace(arg[0], arg[1]);
case 'toggleFullScreen': return this.service.toggleFullScreen(arg);
case 'setRepresentedFilename': return this.service.setRepresentedFilename(arg[0], arg[1]);
case 'addRecentlyOpened': return this.service.addRecentlyOpened(arg);
@@ -97,6 +99,7 @@ export class WindowsChannel implements IWindowsChannel {
case 'moveWindowTabToNewWindow': return this.service.moveWindowTabToNewWindow();
case 'mergeAllWindowTabs': return this.service.mergeAllWindowTabs();
case 'toggleWindowTabsBar': return this.service.toggleWindowTabsBar();
case 'updateTouchBar': return this.service.updateTouchBar(arg[0], arg[1]);
case 'getRecentlyOpened': return this.service.getRecentlyOpened(arg);
case 'focusWindow': return this.service.focusWindow(arg);
case 'closeWindow': return this.service.closeWindow(arg);
@@ -171,12 +174,12 @@ export class WindowsChannelClient implements IWindowsService {
return this.channel.call('openWorkspace', windowId);
}
createAndOpenWorkspace(windowId: number, folders?: string[], path?: string): TPromise<void> {
return this.channel.call('createAndOpenWorkspace', [windowId, folders, path]);
createAndEnterWorkspace(windowId: number, folders?: string[], path?: string): TPromise<IEnterWorkspaceResult> {
return this.channel.call('createAndEnterWorkspace', [windowId, folders, path]);
}
saveAndOpenWorkspace(windowId: number, path: string): TPromise<void> {
return this.channel.call('saveAndOpenWorkspace', [windowId, path]);
saveAndEnterWorkspace(windowId: number, path: string): TPromise<IEnterWorkspaceResult> {
return this.channel.call('saveAndEnterWorkspace', [windowId, path]);
}
toggleFullScreen(windowId: number): TPromise<void> {
@@ -306,4 +309,8 @@ export class WindowsChannelClient implements IWindowsService {
startCrashReporter(config: Electron.CrashReporterStartOptions): TPromise<void> {
return this.channel.call('startCrashReporter', config);
}
updateTouchBar(windowId: number, items: ICommandAction[][]): TPromise<void> {
return this.channel.call('updateTouchBar', [windowId, items]);
}
}
@@ -7,9 +7,10 @@
import Event, { filterEvent, mapEvent, any } from 'vs/base/common/event';
import { TPromise } from 'vs/base/common/winjs.base';
import { IWindowService, IWindowsService, INativeOpenDialogOptions } from 'vs/platform/windows/common/windows';
import { IWindowService, IWindowsService, INativeOpenDialogOptions, IEnterWorkspaceResult } from 'vs/platform/windows/common/windows';
import { remote } from 'electron';
import { IRecentlyOpened } from 'vs/platform/history/common/history';
import { ICommandAction } from 'vs/platform/actions/common/actions';
export class WindowService implements IWindowService {
@@ -68,12 +69,12 @@ export class WindowService implements IWindowService {
return this.windowsService.openWorkspace(this.windowId);
}
createAndOpenWorkspace(folders?: string[], path?: string): TPromise<void> {
return this.windowsService.createAndOpenWorkspace(this.windowId, folders, path);
createAndEnterWorkspace(folders?: string[], path?: string): TPromise<IEnterWorkspaceResult> {
return this.windowsService.createAndEnterWorkspace(this.windowId, folders, path);
}
saveAndOpenWorkspace(path: string): TPromise<void> {
return this.windowsService.saveAndOpenWorkspace(this.windowId, path);
saveAndEnterWorkspace(path: string): TPromise<IEnterWorkspaceResult> {
return this.windowsService.saveAndEnterWorkspace(this.windowId, path);
}
closeWindow(): TPromise<void> {
@@ -143,4 +144,8 @@ export class WindowService implements IWindowService {
return remote.dialog.showOpenDialog(remote.getCurrentWindow(), options); // https://github.com/electron/electron/issues/4936
}
updateTouchBar(items: ICommandAction[][]): TPromise<void> {
return this.windowsService.updateTouchBar(this.windowId, items);
}
}
@@ -6,12 +6,13 @@
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { OpenContext, IWindowConfiguration, ReadyState, INativeOpenDialogOptions } from 'vs/platform/windows/common/windows';
import { OpenContext, IWindowConfiguration, ReadyState, INativeOpenDialogOptions, IEnterWorkspaceResult } from 'vs/platform/windows/common/windows';
import { ParsedArgs } from 'vs/platform/environment/common/environment';
import Event from 'vs/base/common/event';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IProcessEnvironment } from 'vs/base/common/platform';
import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { ICommandAction } from 'vs/platform/actions/common/actions';
export interface ICodeWindow {
id: number;
@@ -35,6 +36,8 @@ export interface ICodeWindow {
setRepresentedFilename(name: string): void;
getRepresentedFilename(): string;
onWindowTitleDoubleClick(): void;
updateTouchBar(items: ICommandAction[][]): void;
}
export const IWindowsMainService = createDecorator<IWindowsMainService>('windowsMainService');
@@ -58,8 +61,8 @@ export interface IWindowsMainService {
ready(initialUserEnv: IProcessEnvironment): void;
reload(win: ICodeWindow, cli?: ParsedArgs): void;
openWorkspace(win?: ICodeWindow): void;
createAndOpenWorkspace(win: ICodeWindow, folders?: string[], path?: string): void;
saveAndOpenWorkspace(win: ICodeWindow, path: string): void;
createAndEnterWorkspace(win: ICodeWindow, folders?: string[], path?: string): TPromise<IEnterWorkspaceResult>;
saveAndEnterWorkspace(win: ICodeWindow, path: string): TPromise<IEnterWorkspaceResult>;
closeWorkspace(win: ICodeWindow): void;
open(openConfig: IOpenConfiguration): ICodeWindow[];
openExtensionDevelopmentHostWindow(openConfig: IOpenConfiguration): void;
@@ -9,7 +9,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { assign } from 'vs/base/common/objects';
import URI from 'vs/base/common/uri';
import { IWindowsService, OpenContext, INativeOpenDialogOptions } from 'vs/platform/windows/common/windows';
import { IWindowsService, OpenContext, INativeOpenDialogOptions, IEnterWorkspaceResult } from 'vs/platform/windows/common/windows';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { shell, crashReporter, app, Menu } from 'electron';
import Event, { chain } from 'vs/base/common/event';
@@ -19,6 +19,7 @@ import { ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycle
import { IWindowsMainService, ISharedProcess } from 'vs/platform/windows/electron-main/windows';
import { IHistoryMainService, IRecentlyOpened } from 'vs/platform/history/common/history';
import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { ICommandAction } from 'vs/platform/actions/common/actions';
export class WindowsService implements IWindowsService, IDisposable {
@@ -104,6 +105,16 @@ export class WindowsService implements IWindowsService, IDisposable {
return TPromise.as(null);
}
updateTouchBar(windowId: number, items: ICommandAction[][]): TPromise<void> {
const codeWindow = this.windowsMainService.getWindowById(windowId);
if (codeWindow) {
codeWindow.updateTouchBar(items);
}
return TPromise.as(null);
}
closeWorkspace(windowId: number): TPromise<void> {
const codeWindow = this.windowsMainService.getWindowById(windowId);
@@ -124,21 +135,21 @@ export class WindowsService implements IWindowsService, IDisposable {
return TPromise.as(null);
}
createAndOpenWorkspace(windowId: number, folders?: string[], path?: string): TPromise<void> {
createAndEnterWorkspace(windowId: number, folders?: string[], path?: string): TPromise<IEnterWorkspaceResult> {
const codeWindow = this.windowsMainService.getWindowById(windowId);
if (codeWindow) {
this.windowsMainService.createAndOpenWorkspace(codeWindow, folders, path);
return this.windowsMainService.createAndEnterWorkspace(codeWindow, folders, path);
}
return TPromise.as(null);
}
saveAndOpenWorkspace(windowId: number, path: string): TPromise<void> {
saveAndEnterWorkspace(windowId: number, path: string): TPromise<IEnterWorkspaceResult> {
const codeWindow = this.windowsMainService.getWindowById(windowId);
if (codeWindow) {
this.windowsMainService.saveAndOpenWorkspace(codeWindow, path);
return this.windowsMainService.saveAndEnterWorkspace(codeWindow, path);
}
return TPromise.as(null);
+20 -4
View File
@@ -129,15 +129,23 @@ export class Workspace implements IWorkspace {
private _folders: WorkspaceFolder[];
constructor(
public readonly id: string,
private _name: string,
folders: WorkspaceFolder[],
private _id: string,
private _name: string = '',
folders: WorkspaceFolder[] = [],
private _configuration: URI = null,
public readonly ctime?: number
private _ctime?: number
) {
this.folders = folders;
}
public update(workspace: Workspace) {
this._id = workspace.id;
this._name = workspace.name;
this._configuration = workspace.configuration;
this._ctime = workspace.ctime;
this.folders = workspace.folders;
}
public get folders(): WorkspaceFolder[] {
return this._folders;
}
@@ -147,6 +155,14 @@ export class Workspace implements IWorkspace {
this.updateFoldersMap();
}
public get id(): string {
return this._id;
}
public get ctime(): number {
return this._ctime;
}
public get name(): string {
return this._name;
}
@@ -50,7 +50,7 @@ suite('Workspace', () => {
const actual = toWorkspaceFolders([{ path: '/src/test' }]);
assert.equal(actual.length, 1);
assert.equal(actual[0].uri.fsPath, '/src/test');
assert.equal(actual[0].uri.fsPath, URI.file('/src/test').fsPath);
assert.equal(actual[0].raw.path, '/src/test');
assert.equal(actual[0].index, 0);
assert.equal(actual[0].name, 'test');
@@ -60,7 +60,7 @@ suite('Workspace', () => {
const actual = toWorkspaceFolders([{ path: './test' }], URI.file('src'));
assert.equal(actual.length, 1);
assert.equal(actual[0].uri.fsPath, '/src/test');
assert.equal(actual[0].uri.fsPath, URI.file('/src/test').fsPath);
assert.equal(actual[0].raw.path, './test');
assert.equal(actual[0].index, 0);
assert.equal(actual[0].name, 'test');
@@ -70,7 +70,7 @@ suite('Workspace', () => {
const actual = toWorkspaceFolders([{ path: '/src/test', name: 'hello' }]);
assert.equal(actual.length, 1);
assert.equal(actual[0].uri.fsPath, '/src/test');
assert.equal(actual[0].uri.fsPath, URI.file('/src/test').fsPath);
assert.equal(actual[0].raw.path, '/src/test');
assert.equal(actual[0].index, 0);
assert.equal(actual[0].name, 'hello');
@@ -80,17 +80,17 @@ suite('Workspace', () => {
const actual = toWorkspaceFolders([{ path: '/src/test2' }, { path: '/src/test3' }, { path: '/src/test1' }]);
assert.equal(actual.length, 3);
assert.equal(actual[0].uri.fsPath, '/src/test2');
assert.equal(actual[0].uri.fsPath, URI.file('/src/test2').fsPath);
assert.equal(actual[0].raw.path, '/src/test2');
assert.equal(actual[0].index, 0);
assert.equal(actual[0].name, 'test2');
assert.equal(actual[1].uri.fsPath, '/src/test3');
assert.equal(actual[1].uri.fsPath, URI.file('/src/test3').fsPath);
assert.equal(actual[1].raw.path, '/src/test3');
assert.equal(actual[1].index, 1);
assert.equal(actual[1].name, 'test3');
assert.equal(actual[2].uri.fsPath, '/src/test1');
assert.equal(actual[2].uri.fsPath, URI.file('/src/test1').fsPath);
assert.equal(actual[2].raw.path, '/src/test1');
assert.equal(actual[2].index, 2);
assert.equal(actual[2].name, 'test1');
@@ -100,17 +100,17 @@ suite('Workspace', () => {
const actual = toWorkspaceFolders([{ path: '/src/test2' }, { path: '/src/test3', name: 'noName' }, { path: '/src/test1' }]);
assert.equal(actual.length, 3);
assert.equal(actual[0].uri.fsPath, '/src/test2');
assert.equal(actual[0].uri.fsPath, URI.file('/src/test2').fsPath);
assert.equal(actual[0].raw.path, '/src/test2');
assert.equal(actual[0].index, 0);
assert.equal(actual[0].name, 'test2');
assert.equal(actual[1].uri.fsPath, '/src/test3');
assert.equal(actual[1].uri.fsPath, URI.file('/src/test3').fsPath);
assert.equal(actual[1].raw.path, '/src/test3');
assert.equal(actual[1].index, 1);
assert.equal(actual[1].name, 'noName');
assert.equal(actual[2].uri.fsPath, '/src/test1');
assert.equal(actual[2].uri.fsPath, URI.file('/src/test1').fsPath);
assert.equal(actual[2].raw.path, '/src/test1');
assert.equal(actual[2].index, 2);
assert.equal(actual[2].name, 'test1');
@@ -120,17 +120,17 @@ suite('Workspace', () => {
const actual = toWorkspaceFolders([{ path: '/src/test2' }, { path: '/abc/test3', name: 'noName' }, { path: './test1' }], URI.file('src'));
assert.equal(actual.length, 3);
assert.equal(actual[0].uri.fsPath, '/src/test2');
assert.equal(actual[0].uri.fsPath, URI.file('/src/test2').fsPath);
assert.equal(actual[0].raw.path, '/src/test2');
assert.equal(actual[0].index, 0);
assert.equal(actual[0].name, 'test2');
assert.equal(actual[1].uri.fsPath, '/abc/test3');
assert.equal(actual[1].uri.fsPath, URI.file('/abc/test3').fsPath);
assert.equal(actual[1].raw.path, '/abc/test3');
assert.equal(actual[1].index, 1);
assert.equal(actual[1].name, 'noName');
assert.equal(actual[2].uri.fsPath, '/src/test1');
assert.equal(actual[2].uri.fsPath, URI.file('/src/test1').fsPath);
assert.equal(actual[2].raw.path, './test1');
assert.equal(actual[2].index, 2);
assert.equal(actual[2].name, 'test1');
@@ -140,12 +140,12 @@ suite('Workspace', () => {
const actual = toWorkspaceFolders([{ path: '/src/test2' }, { path: '/src/test2', name: 'noName' }, { path: '/src/test1' }]);
assert.equal(actual.length, 2);
assert.equal(actual[0].uri.fsPath, '/src/test2');
assert.equal(actual[0].uri.fsPath, URI.file('/src/test2').fsPath);
assert.equal(actual[0].raw.path, '/src/test2');
assert.equal(actual[0].index, 0);
assert.equal(actual[0].name, 'test2');
assert.equal(actual[1].uri.fsPath, '/src/test1');
assert.equal(actual[1].uri.fsPath, URI.file('/src/test1').fsPath);
assert.equal(actual[1].raw.path, '/src/test1');
assert.equal(actual[1].index, 1);
assert.equal(actual[1].name, 'test1');
@@ -155,17 +155,17 @@ suite('Workspace', () => {
const actual = toWorkspaceFolders([{ path: '/src/test2' }, { path: '/src/test3', name: 'noName' }, { path: './test3' }, { path: '/abc/test1' }], URI.file('src'));
assert.equal(actual.length, 3);
assert.equal(actual[0].uri.fsPath, '/src/test2');
assert.equal(actual[0].uri.fsPath, URI.file('/src/test2').fsPath);
assert.equal(actual[0].raw.path, '/src/test2');
assert.equal(actual[0].index, 0);
assert.equal(actual[0].name, 'test2');
assert.equal(actual[1].uri.fsPath, '/src/test3');
assert.equal(actual[1].uri.fsPath, URI.file('/src/test3').fsPath);
assert.equal(actual[1].raw.path, '/src/test3');
assert.equal(actual[1].index, 1);
assert.equal(actual[1].name, 'noName');
assert.equal(actual[2].uri.fsPath, '/abc/test1');
assert.equal(actual[2].uri.fsPath, URI.file('/abc/test1').fsPath);
assert.equal(actual[2].raw.path, '/abc/test1');
assert.equal(actual[2].index, 2);
assert.equal(actual[2].name, 'test1');
@@ -175,17 +175,17 @@ suite('Workspace', () => {
const actual = toWorkspaceFolders([{ path: '/src/test2' }, { path: '', name: 'noName' }, { path: './test3' }, { path: '/abc/test1' }], URI.file('src'));
assert.equal(actual.length, 3);
assert.equal(actual[0].uri.fsPath, '/src/test2');
assert.equal(actual[0].uri.fsPath, URI.file('/src/test2').fsPath);
assert.equal(actual[0].raw.path, '/src/test2');
assert.equal(actual[0].index, 0);
assert.equal(actual[0].name, 'test2');
assert.equal(actual[1].uri.fsPath, '/src/test3');
assert.equal(actual[1].uri.fsPath, URI.file('/src/test3').fsPath);
assert.equal(actual[1].raw.path, './test3');
assert.equal(actual[1].index, 1);
assert.equal(actual[1].name, 'test3');
assert.equal(actual[2].uri.fsPath, '/abc/test1');
assert.equal(actual[2].uri.fsPath, URI.file('/abc/test1').fsPath);
assert.equal(actual[2].raw.path, '/abc/test1');
assert.equal(actual[2].index, 2);
assert.equal(actual[2].name, 'test1');
+1 -1
View File
@@ -5689,7 +5689,7 @@ declare module 'vscode' {
* or by directly passing a [DebugConfiguration](#DebugConfiguration).
* The named configurations are looked up in '.vscode/launch.json' found in the given folder.
* Before debugging starts, all unsaved files are saved and the launch configurations are brought up-to-date.
* Folder specific variables used in the configuration (e.g. '${workspaceRoot}') are resolved against the given folder.
* Folder specific variables used in the configuration (e.g. '${workspaceFolder}') are resolved against the given folder.
* @param folder The [workspace folder](#WorkspaceFolder) for looking up named configurations and resolving variables or `undefined` for a non-folder setup.
* @param nameOrConfiguration Either the name of a debug or compound configuration or a [DebugConfiguration](#DebugConfiguration) object.
* @return A thenable that resolves when debugging could be successfully started.
+25 -14
View File
@@ -135,19 +135,10 @@ declare module 'vscode' {
constructor(red: number, green: number, blue: number, alpha: number);
}
/**
* Represents a color format
*/
export enum ColorFormat {
RGB = 0,
HEX = 1,
HSL = 2
}
/**
* Represents a color range from a document.
*/
export class ColorRange {
export class ColorInformation {
/**
* The range in the document where this color appers.
@@ -169,6 +160,26 @@ declare module 'vscode' {
constructor(range: Range, color: Color);
}
export class ColorPresentation {
/**
* The label of this color presentation. It will be shown on the color
* picker header. By default this is also the text that is inserted when selecting
* this color presentation.
*/
label: string;
/**
* An [edit](#TextEdit) which is applied to a document when selecting
* this presentation for the color. When `falsy` the [label](#ColorPresentation.label)
* is used.
*/
textEdit?: TextEdit;
/**
* An optional array of additional [text edits](#TextEdit) that are applied when
* selecting this color presentation. Edits must not overlap with the main [edit](#ColorPresentation.textEdit) nor with themselves.
*/
additionalTextEdits?: TextEdit[];
}
/**
* The document color provider defines the contract between extensions and feature of
* picking and modifying colors in the editor.
@@ -179,14 +190,14 @@ declare module 'vscode' {
*
* @param document The document in which the command was invoked.
* @param token A cancellation token.
* @return An array of [color ranges](#ColorRange) or a thenable that resolves to such. The lack of a result
* @return An array of [color informations](#ColorInformation) or a thenable that resolves to such. The lack of a result
* can be signaled by returning `undefined`, `null`, or an empty array.
*/
provideDocumentColors(document: TextDocument, token: CancellationToken): ProviderResult<ColorRange[]>;
provideDocumentColors(document: TextDocument, token: CancellationToken): ProviderResult<ColorInformation[]>;
/**
* Provide the string representation for a color.
* Provide representations for a color.
*/
resolveDocumentColor(color: Color, colorFormat: ColorFormat): ProviderResult<string>;
provideColorPresentations(colorInfo: ColorInformation, token: CancellationToken): ProviderResult<ColorPresentation[]>;
}
export namespace languages {
@@ -4,10 +4,11 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import URI from 'vs/base/common/uri';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import uri from 'vs/base/common/uri';
import { IDebugService, IConfig, IDebugConfigurationProvider } from 'vs/workbench/parts/debug/common/debug';
import { TPromise } from 'vs/base/common/winjs.base';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { ExtHostContext, ExtHostDebugServiceShape, MainThreadDebugServiceShape, DebugSessionUUID, MainContext, IExtHostContext } from '../node/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
@@ -19,7 +20,8 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape {
constructor(
extHostContext: IExtHostContext,
@IDebugService private debugService: IDebugService
@IDebugService private debugService: IDebugService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
) {
this._proxy = extHostContext.get(ExtHostContext.ExtHostDebugService);
this._toDispose = [];
@@ -69,19 +71,22 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape {
return TPromise.as<void>(undefined);
}
public $startDebugging(folderUri: URI | undefined, nameOrConfiguration: string | IConfig): TPromise<boolean> {
return this.debugService.startDebugging(folderUri, nameOrConfiguration).then(x => {
public $startDebugging(folderUri: uri | undefined, nameOrConfiguration: string | IConfig): TPromise<boolean> {
const folder = folderUri ? this.contextService.getWorkspace().folders.filter(wf => wf.uri.toString() === folderUri.toString()).pop() : undefined;
return this.debugService.startDebugging(folder, nameOrConfiguration).then(x => {
return true;
}, err => {
return TPromise.wrapError(err && err.message ? err.message : 'cannot start debugging');
});
}
public $startDebugSession(folderUri: URI | undefined, configuration: IConfig): TPromise<DebugSessionUUID> {
public $startDebugSession(folderUri: uri | undefined, configuration: IConfig): TPromise<DebugSessionUUID> {
if (configuration.request !== 'launch' && configuration.request !== 'attach') {
return TPromise.wrapError(new Error(`only 'launch' or 'attach' allowed for 'request' attribute`));
}
return this.debugService.createProcess(folderUri, configuration).then(process => {
const folder = folderUri ? this.contextService.getWorkspace().folders.filter(wf => wf.uri.toString() === folderUri.toString()).pop() : undefined;
return this.debugService.createProcess(folder, configuration).then(process => {
if (process) {
return <DebugSessionUUID>process.getId();
}
@@ -250,7 +250,7 @@ export class MainThreadDocumentsAndEditors {
const mainThreadDocuments = new MainThreadDocuments(this, extHostContext, this._modelService, modeService, this._textFileService, fileService, textModelResolverService, untitledEditorService);
extHostContext.set(MainContext.MainThreadDocuments, mainThreadDocuments);
const mainThreadEditors = new MainThreadEditors(this, extHostContext, codeEditorService, this._workbenchEditorService, editorGroupService, telemetryService);
const mainThreadEditors = new MainThreadEditors(this, extHostContext, codeEditorService, this._workbenchEditorService, editorGroupService, telemetryService, textModelResolverService, fileService, this._modelService);
extHostContext.set(MainContext.MainThreadEditors, mainThreadEditors);
// It is expected that the ctor of the state computer calls our `_onDelta`.
@@ -8,7 +8,7 @@ import URI from 'vs/base/common/uri';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { disposed } from 'vs/base/common/errors';
import { TPromise } from 'vs/base/common/winjs.base';
import { ISingleEditOperation, IDecorationRenderOptions, IDecorationOptions, ILineChange } from 'vs/editor/common/editorCommon';
import { ISingleEditOperation, IDecorationRenderOptions, IDecorationOptions, ILineChange, ICommonCodeEditor, isCommonCodeEditor } from 'vs/editor/common/editorCommon';
import { ICodeEditorService } from 'vs/editor/common/services/codeEditorService';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService';
@@ -18,9 +18,13 @@ import { ITextEditorConfigurationUpdate, TextEditorRevealType, IApplyEditsOption
import { MainThreadDocumentsAndEditors } from './mainThreadDocumentsAndEditors';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { equals as objectEquals } from 'vs/base/common/objects';
import { ExtHostContext, MainThreadEditorsShape, ExtHostEditorsShape, ITextDocumentShowOptions, ITextEditorPositionData, IExtHostContext } from '../node/extHost.protocol';
import { ExtHostContext, MainThreadEditorsShape, ExtHostEditorsShape, ITextDocumentShowOptions, ITextEditorPositionData, IExtHostContext, IWorkspaceResourceEdit } from '../node/extHost.protocol';
import { IRange } from 'vs/editor/common/core/range';
import { ISelection } from 'vs/editor/common/core/selection';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { IFileService } from 'vs/platform/files/common/files';
import { bulkEdit, IResourceEdit } from 'vs/editor/common/services/bulkEdit';
import { IModelService } from 'vs/editor/common/services/modelService';
export class MainThreadEditors implements MainThreadEditorsShape {
@@ -38,7 +42,10 @@ export class MainThreadEditors implements MainThreadEditorsShape {
@ICodeEditorService private _codeEditorService: ICodeEditorService,
@IWorkbenchEditorService workbenchEditorService: IWorkbenchEditorService,
@IEditorGroupService editorGroupService: IEditorGroupService,
@ITelemetryService telemetryService: ITelemetryService
@ITelemetryService telemetryService: ITelemetryService,
@ITextModelService private readonly _textModelResolverService: ITextModelService,
@IFileService private readonly _fileService: IFileService,
@IModelService private readonly _modelService: IModelService,
) {
this._proxy = extHostContext.get(ExtHostContext.ExtHostEditors);
this._documentsAndEditors = documentsAndEditors;
@@ -194,6 +201,52 @@ export class MainThreadEditors implements MainThreadEditorsShape {
return TPromise.as(this._documentsAndEditors.getEditor(id).applyEdits(modelVersionId, edits, opts));
}
$tryApplyWorkspaceEdit(workspaceResourceEdits: IWorkspaceResourceEdit[]): TPromise<boolean> {
// First check if loaded models were not changed in the meantime
for (let i = 0, len = workspaceResourceEdits.length; i < len; i++) {
const workspaceResourceEdit = workspaceResourceEdits[i];
if (workspaceResourceEdit.modelVersionId) {
let model = this._modelService.getModel(workspaceResourceEdit.resource);
if (model && model.getVersionId() !== workspaceResourceEdit.modelVersionId) {
// model changed in the meantime
return TPromise.as(false);
}
}
}
// Convert to shape expected by bulkEdit below
let resourceEdits: IResourceEdit[] = [];
for (let i = 0, len = workspaceResourceEdits.length; i < len; i++) {
const workspaceResourceEdit = workspaceResourceEdits[i];
const uri = workspaceResourceEdit.resource;
const edits = workspaceResourceEdit.edits;
for (let j = 0, lenJ = edits.length; j < lenJ; j++) {
const edit = edits[j];
resourceEdits.push({
resource: <URI>uri,
newText: edit.newText,
newEol: edit.newEol,
range: edit.range
});
}
}
let codeEditor: ICommonCodeEditor;
let editor = this._workbenchEditorService.getActiveEditor();
if (editor) {
let candidate = editor.getControl();
if (isCommonCodeEditor(candidate)) {
codeEditor = candidate;
}
}
return bulkEdit(this._textModelResolverService, codeEditor, resourceEdits, this._fileService)
.then(() => true);
}
$tryInsertSnippet(id: string, template: string, ranges: IRange[], opts: IUndoStopOptions): TPromise<boolean> {
if (!this._documentsAndEditors.getEditor(id)) {
return TPromise.wrapError<boolean>(disposed(`TextEditor(${id})`));
@@ -286,7 +286,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
$registerDocumentColorProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
const proxy = this._proxy;
this._registrations[handle] = modes.ColorProviderRegistry.register(selector, <modes.DocumentColorProvider>{
provideColorRanges: (model, token) => {
provideDocumentColors: (model, token) => {
return wireCancellationToken(token, proxy.$provideDocumentColors(handle, model.uri))
.then(documentColors => {
return documentColors.map(documentColor => {
@@ -305,8 +305,12 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
});
});
},
resolveColor: (color, format, token) => {
return wireCancellationToken(token, proxy.$resolveDocumentColor(handle, color, format));
provideColorPresentations: (colorInfo, token) => {
return wireCancellationToken(token, proxy.$provideColorPresentations(handle, {
color: [colorInfo.color.red, colorInfo.color.green, colorInfo.color.blue, colorInfo.color.alpha],
range: colorInfo.range
}));
}
});
@@ -6,6 +6,9 @@
import { TPromise } from 'vs/base/common/winjs.base';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { ContributedTask, ExtensionTaskSourceTransfer } from 'vs/workbench/parts/tasks/common/tasks';
import { ITaskService } from 'vs/workbench/parts/tasks/common/taskService';
import { ExtHostContext, MainThreadTaskShape, ExtHostTaskShape, MainContext, IExtHostContext } from '../node/extHost.protocol';
@@ -19,7 +22,8 @@ export class MainThreadTask implements MainThreadTaskShape {
constructor(
extHostContext: IExtHostContext,
@ITaskService private _taskService: ITaskService
@ITaskService private _taskService: ITaskService,
@IWorkspaceContextService private _workspaceContextServer: IWorkspaceContextService
) {
this._proxy = extHostContext.get(ExtHostContext.ExtHostTask);
this._activeHandles = Object.create(null);
@@ -35,7 +39,17 @@ export class MainThreadTask implements MainThreadTaskShape {
public $registerTaskProvider(handle: number): TPromise<void> {
this._taskService.registerTaskProvider(handle, {
provideTasks: () => {
return this._proxy.$provideTasks(handle);
return this._proxy.$provideTasks(handle).then((value) => {
for (let task of value.tasks) {
if (ContributedTask.is(task)) {
let uri = (task._source as any as ExtensionTaskSourceTransfer).__workspaceFolder;
if (uri) {
(task._source as any).workspaceFolder = this._workspaceContextServer.getWorkspaceFolder(uri);
}
}
}
return value;
});
}
});
this._activeHandles[handle] = true;
@@ -8,13 +8,9 @@ import { isPromiseCanceledError } from 'vs/base/common/errors';
import URI from 'vs/base/common/uri';
import { ISearchService, QueryType, ISearchQuery } from 'vs/platform/search/common/search';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { ICommonCodeEditor, isCommonCodeEditor } from 'vs/editor/common/editorCommon';
import { bulkEdit, IResourceEdit } from 'vs/editor/common/services/bulkEdit';
import { TPromise } from 'vs/base/common/winjs.base';
import { MainThreadWorkspaceShape, ExtHostWorkspaceShape, ExtHostContext, MainContext, IExtHostContext } from '../node/extHost.protocol';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { IFileService } from 'vs/platform/files/common/files';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
@@ -32,13 +28,11 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
@ISearchService private readonly _searchService: ISearchService,
@IWorkspaceContextService private readonly _contextService: IWorkspaceContextService,
@ITextFileService private readonly _textFileService: ITextFileService,
@IWorkbenchEditorService private readonly _editorService: IWorkbenchEditorService,
@ITextModelService private readonly _textModelResolverService: ITextModelService,
@IExperimentService private _experimentService: IExperimentService,
@IFileService private readonly _fileService: IFileService
) {
this._proxy = extHostContext.get(ExtHostContext.ExtHostWorkspace);
this._contextService.onDidChangeWorkspaceFolders(this._onDidChangeWorkspace, this, this._toDispose);
this._contextService.onDidChangeWorkbenchState(this._onDidChangeWorkspaceState, this, this._toDispose);
}
dispose(): void {
@@ -52,7 +46,7 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
// --- workspace ---
private _onDidChangeWorkspace(): void {
private _onDidChangeWorkspaceState(): void {
this._proxy.$acceptWorkspaceData(this._contextService.getWorkbenchState() === WorkbenchState.EMPTY ? null : this._contextService.getWorkspace());
}
@@ -106,20 +100,5 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
return result.results.every(each => each.success === true);
});
}
$applyWorkspaceEdit(edits: IResourceEdit[]): TPromise<boolean> {
let codeEditor: ICommonCodeEditor;
let editor = this._editorService.getActiveEditor();
if (editor) {
let candidate = editor.getControl();
if (isCommonCodeEditor(candidate)) {
codeEditor = candidate;
}
}
return bulkEdit(this._textModelResolverService, codeEditor, edits, this._fileService)
.then(() => true);
}
}
@@ -86,7 +86,7 @@ export function createApiFactory(
const extHostDocumentsAndEditors = threadService.set(ExtHostContext.ExtHostDocumentsAndEditors, new ExtHostDocumentsAndEditors(threadService, extensionService));
const extHostDocuments = threadService.set(ExtHostContext.ExtHostDocuments, new ExtHostDocuments(threadService, extHostDocumentsAndEditors));
const extHostDocumentContentProviders = threadService.set(ExtHostContext.ExtHostDocumentContentProviders, new ExtHostDocumentContentProvider(threadService, extHostDocumentsAndEditors));
const extHostDocumentSaveParticipant = threadService.set(ExtHostContext.ExtHostDocumentSaveParticipant, new ExtHostDocumentSaveParticipant(extHostDocuments, threadService.get(MainContext.MainThreadWorkspace)));
const extHostDocumentSaveParticipant = threadService.set(ExtHostContext.ExtHostDocumentSaveParticipant, new ExtHostDocumentSaveParticipant(extHostDocuments, threadService.get(MainContext.MainThreadEditors)));
const extHostEditors = threadService.set(ExtHostContext.ExtHostEditors, new ExtHostEditors(threadService, extHostDocumentsAndEditors));
const extHostCommands = threadService.set(ExtHostContext.ExtHostCommands, new ExtHostCommands(threadService, extHostHeapService));
const extHostTreeViews = threadService.set(ExtHostContext.ExtHostTreeViews, new ExtHostTreeViews(threadService.get(MainContext.MainThreadTreeViews), extHostCommands));
@@ -420,7 +420,7 @@ export function createApiFactory(
return extHostWorkspace.saveAll(includeUntitled);
},
applyEdit(edit: vscode.WorkspaceEdit): TPromise<boolean> {
return extHostWorkspace.appyEdit(edit);
return extHostEditors.applyWorkspaceEdit(edit);
},
createFileSystemWatcher: (pattern, ignoreCreate, ignoreChange, ignoreDelete): vscode.FileSystemWatcher => {
return extHostFileSystemEvent.createFileSystemWatcher(pattern, ignoreCreate, ignoreChange, ignoreDelete);
@@ -554,8 +554,8 @@ export function createApiFactory(
CancellationTokenSource: CancellationTokenSource,
CodeLens: extHostTypes.CodeLens,
Color: extHostTypes.Color,
ColorFormat: extHostTypes.ColorFormat,
ColorRange: extHostTypes.ColorRange,
ColorPresentation: extHostTypes.ColorPresentation,
ColorInformation: extHostTypes.ColorInformation,
EndOfLine: extHostTypes.EndOfLine,
CompletionItem: extHostTypes.CompletionItem,
CompletionItemKind: extHostTypes.CompletionItemKind,
+14 -5
View File
@@ -26,7 +26,6 @@ import { IProgressOptions, IProgressStep } from 'vs/platform/progress/common/pro
import * as editorCommon from 'vs/editor/common/editorCommon';
import * as modes from 'vs/editor/common/modes';
import { IResourceEdit } from 'vs/editor/common/services/bulkEdit';
import { ITextSource } from 'vs/editor/common/model/textSource';
import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing';
@@ -190,6 +189,16 @@ export interface ITextDocumentShowOptions {
selection?: IRange;
}
export interface IWorkspaceResourceEdit {
resource: URI;
modelVersionId?: number;
edits: {
range?: IRange;
newText: string;
newEol?: editorCommon.EndOfLineSequence;
}[];
}
export interface MainThreadEditorsShape extends IDisposable {
$tryShowTextDocument(resource: URI, options: ITextDocumentShowOptions): TPromise<string>;
$registerTextEditorDecorationType(key: string, options: editorCommon.IDecorationRenderOptions): void;
@@ -201,6 +210,7 @@ export interface MainThreadEditorsShape extends IDisposable {
$tryRevealRange(id: string, range: IRange, revealType: TextEditorRevealType): TPromise<any>;
$trySetSelections(id: string, selections: ISelection[]): TPromise<any>;
$tryApplyEdits(id: string, modelVersionId: number, edits: editorCommon.ISingleEditOperation[], opts: IApplyEditsOptions): TPromise<boolean>;
$tryApplyWorkspaceEdit(workspaceResourceEdits: IWorkspaceResourceEdit[]): TPromise<boolean>;
$tryInsertSnippet(id: string, template: string, selections: IRange[], opts: IUndoStopOptions): TPromise<any>;
$getDiffInformation(id: string): TPromise<editorCommon.ILineChange[]>;
}
@@ -302,7 +312,6 @@ export interface MainThreadWorkspaceShape extends IDisposable {
$startSearch(include: string, exclude: string, maxResults: number, requestId: number): Thenable<URI[]>;
$cancelSearch(requestId: number): Thenable<boolean>;
$saveAll(includeUntitled?: boolean): Thenable<boolean>;
$applyWorkspaceEdit(edits: IResourceEdit[]): TPromise<boolean>;
}
export interface MainThreadFileSystemShape extends IDisposable {
@@ -377,8 +386,8 @@ export type DebugSessionUUID = string;
export interface MainThreadDebugServiceShape extends IDisposable {
$registerDebugConfigurationProvider(type: string, hasProvideMethod: boolean, hasResolveMethod: boolean, handle: number): TPromise<any>;
$unregisterDebugConfigurationProvider(handle: number): TPromise<any>;
$startDebugging(folderUri: URI | undefined, nameOrConfig: string | vscode.DebugConfiguration): TPromise<boolean>;
$startDebugSession(folderUri: URI | undefined, config: vscode.DebugConfiguration): TPromise<DebugSessionUUID>;
$startDebugging(folder: URI | undefined, nameOrConfig: string | vscode.DebugConfiguration): TPromise<boolean>;
$startDebugSession(folder: URI | undefined, config: vscode.DebugConfiguration): TPromise<DebugSessionUUID>;
$customDebugAdapterRequest(id: DebugSessionUUID, command: string, args: any): TPromise<any>;
}
@@ -550,7 +559,7 @@ export interface ExtHostLanguageFeaturesShape {
$provideDocumentLinks(handle: number, resource: URI): TPromise<modes.ILink[]>;
$resolveDocumentLink(handle: number, link: modes.ILink): TPromise<modes.ILink>;
$provideDocumentColors(handle: number, resource: URI): TPromise<IRawColorInfo[]>;
$resolveDocumentColor(handle: number, color: modes.IColor, colorFormat: modes.ColorFormat): TPromise<string>;
$provideColorPresentations(handle: number, colorInfo: IRawColorInfo): TPromise<modes.IColorPresentation[]>;
}
export interface ExtHostQuickOpenShape {
@@ -95,12 +95,10 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
}
public startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration): TPromise<boolean> {
return this._debugServiceProxy.$startDebugging(folder ? <URI>folder.uri : undefined, nameOrConfig);
}
public startDebugSession(folder: vscode.WorkspaceFolder | undefined, config: vscode.DebugConfiguration): TPromise<vscode.DebugSession> {
return this._debugServiceProxy.$startDebugSession(folder ? <URI>folder.uri : undefined, config).then((id: DebugSessionUUID) => {
const debugSession = new ExtHostDebugSession(this._debugServiceProxy, id, config.type, config.name);
this._debugSessions.set(id, debugSession);
@@ -10,10 +10,9 @@ import URI from 'vs/base/common/uri';
import { sequence, always } from 'vs/base/common/async';
import { illegalState } from 'vs/base/common/errors';
import { TPromise } from 'vs/base/common/winjs.base';
import { MainThreadWorkspaceShape, ExtHostDocumentSaveParticipantShape } from 'vs/workbench/api/node/extHost.protocol';
import { ExtHostDocumentSaveParticipantShape, MainThreadEditorsShape, IWorkspaceResourceEdit } from 'vs/workbench/api/node/extHost.protocol';
import { TextEdit } from 'vs/workbench/api/node/extHostTypes';
import { fromRange, TextDocumentSaveReason, EndOfLine } from 'vs/workbench/api/node/extHostTypeConverters';
import { IResourceEdit } from 'vs/editor/common/services/bulkEdit';
import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
import * as vscode from 'vscode';
@@ -21,14 +20,14 @@ import * as vscode from 'vscode';
export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSaveParticipantShape {
private _documents: ExtHostDocuments;
private _workspace: MainThreadWorkspaceShape;
private _mainThreadEditors: MainThreadEditorsShape;
private _callbacks = new CallbackList();
private _badListeners = new WeakMap<Function, number>();
private _thresholds: { timeout: number; errors: number; };
constructor(documents: ExtHostDocuments, workspace: MainThreadWorkspaceShape, thresholds: { timeout: number; errors: number; } = { timeout: 1500, errors: 3 }) {
constructor(documents: ExtHostDocuments, mainThreadEditors: MainThreadEditorsShape, thresholds: { timeout: number; errors: number; } = { timeout: 1500, errors: 3 }) {
this._documents = documents;
this._workspace = workspace;
this._mainThreadEditors = mainThreadEditors;
this._thresholds = thresholds;
}
@@ -133,13 +132,15 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
}).then(values => {
let edits: IResourceEdit[] = [];
let workspaceResourceEdit: IWorkspaceResourceEdit = {
resource: <URI>document.uri,
edits: []
};
for (const value of values) {
if (Array.isArray(value) && (<vscode.TextEdit[]>value).every(e => e instanceof TextEdit)) {
for (const { newText, newEol, range } of value) {
edits.push({
resource: <URI>document.uri,
workspaceResourceEdit.edits.push({
range: range && fromRange(range),
newText,
newEol: EndOfLine.from(newEol)
@@ -150,12 +151,12 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
// apply edits if any and if document
// didn't change somehow in the meantime
if (edits.length === 0) {
if (workspaceResourceEdit.edits.length === 0) {
return undefined;
}
if (version === document.version) {
return this._workspace.$applyWorkspaceEdit(edits);
return this._mainThreadEditors.$tryApplyWorkspaceEdit([workspaceResourceEdit]);
}
// TODO@joh bubble this to listener?

Some files were not shown because too many files have changed in this diff Show More