Merge VS Code 1.21 source code (#1067)

* Initial VS Code 1.21 file copy with patches

* A few more merges

* Post npm install

* Fix batch of build breaks

* Fix more build breaks

* Fix more build errors

* Fix more build breaks

* Runtime fixes 1

* Get connection dialog working with some todos

* Fix a few packaging issues

* Copy several node_modules to package build to fix loader issues

* Fix breaks from master

* A few more fixes

* Make tests pass

* First pass of license header updates

* Second pass of license header updates

* Fix restore dialog issues

* Remove add additional themes menu items

* fix select box issues where the list doesn't show up

* formatting

* Fix editor dispose issue

* Copy over node modules to correct location on all platforms
This commit is contained in:
Karl Burtram
2018-04-04 15:27:51 -07:00
committed by GitHub
parent 5fba3e31b4
commit dafb780987
9412 changed files with 141255 additions and 98813 deletions
+103 -23
View File
@@ -17,12 +17,12 @@ import fs = require('fs');
import URI from 'vscode-uri';
import * as URL from 'url';
import Strings = require('./utils/strings');
import { formatError, runSafe } from './utils/errors';
import { JSONDocument, JSONSchema, LanguageSettings, getLanguageService, DocumentLanguageSettings } from 'vscode-json-languageservice';
import { formatError, runSafe, runSafeAsync } from './utils/errors';
import { JSONDocument, JSONSchema, getLanguageService, DocumentLanguageSettings, SchemaConfiguration } from 'vscode-json-languageservice';
import { getLanguageModelCache } from './languageModelCache';
import { createScanner, SyntaxKind } from 'jsonc-parser';
import * as nls from 'vscode-nls';
nls.config(process.env['VSCODE_NLS_CONFIG']);
import { FoldingRangeType, FoldingRangesRequest, FoldingRange, FoldingRangeList, FoldingProviderServerCapabilities } from './protocol/foldingProvider.proposed';
interface ISchemaAssociations {
[pattern: string]: string[];
@@ -43,7 +43,7 @@ namespace SchemaContentChangeNotification {
// Create a connection for the server
let connection: IConnection = createConnection();
process.on('unhandledRejection', e => {
process.on('unhandledRejection', (e: any) => {
connection.console.error(formatError(`Unhandled exception`, e));
});
@@ -65,7 +65,7 @@ let clientDynamicRegisterSupport = false;
connection.onInitialize((params: InitializeParams): InitializeResult => {
function hasClientCapability(...keys: string[]) {
let c = params.capabilities;
let c = params.capabilities as any;
for (let i = 0; c && i < keys.length; i++) {
c = c[keys[i]];
}
@@ -74,14 +74,15 @@ connection.onInitialize((params: InitializeParams): InitializeResult => {
clientSnippetSupport = hasClientCapability('textDocument', 'completion', 'completionItem', 'snippetSupport');
clientDynamicRegisterSupport = hasClientCapability('workspace', 'symbol', 'dynamicRegistration');
let capabilities: ServerCapabilities & CPServerCapabilities = {
let capabilities: ServerCapabilities & CPServerCapabilities & FoldingProviderServerCapabilities = {
// Tell the client that the server works in FULL text document sync mode
textDocumentSync: documents.syncKind,
completionProvider: clientSnippetSupport ? { resolveProvider: true, triggerCharacters: ['"', ':'] } : null,
completionProvider: clientSnippetSupport ? { resolveProvider: true, triggerCharacters: ['"', ':'] } : void 0,
hoverProvider: true,
documentSymbolProvider: true,
documentRangeFormattingProvider: false,
colorProvider: true
colorProvider: true,
foldingProvider: true
};
return { capabilities };
@@ -105,7 +106,7 @@ let schemaRequestService = (uri: string): Thenable<string> => {
return connection.sendRequest(VSCodeContentRequest.type, uri).then(responseText => {
return responseText;
}, error => {
return error.message;
return Promise.reject(error.message);
});
}
if (uri.indexOf('//schema.management.azure.com/') !== -1) {
@@ -149,9 +150,9 @@ interface JSONSchemaSettings {
schema?: JSONSchema;
}
let jsonConfigurationSettings: JSONSchemaSettings[] = void 0;
let schemaAssociations: ISchemaAssociations = void 0;
let formatterRegistration: Thenable<Disposable> = null;
let jsonConfigurationSettings: JSONSchemaSettings[] | undefined = void 0;
let schemaAssociations: ISchemaAssociations | undefined = void 0;
let formatterRegistration: Thenable<Disposable> | null = null;
// The settings have changed. Is send on server activation as well.
connection.onDidChangeConfiguration((change) => {
@@ -187,10 +188,10 @@ connection.onNotification(SchemaContentChangeNotification.type, uri => {
});
function updateConfiguration() {
let languageSettings: LanguageSettings = {
let languageSettings = {
validate: true,
allowComments: true,
schemas: []
schemas: new Array<SchemaConfiguration>()
};
if (schemaAssociations) {
for (var pattern in schemaAssociations) {
@@ -232,7 +233,7 @@ documents.onDidClose(event => {
});
let pendingValidationRequests: { [uri: string]: NodeJS.Timer; } = {};
const validationDelayMs = 200;
const validationDelayMs = 500;
function cleanPendingValidation(textDocument: TextDocument): void {
let request = pendingValidationRequests[textDocument.uri];
@@ -295,7 +296,7 @@ function getJSONDocument(document: TextDocument): JSONDocument {
}
connection.onCompletion(textDocumentPosition => {
return runSafe(() => {
return runSafeAsync(() => {
let document = documents.get(textDocumentPosition.textDocument.uri);
let jsonDocument = getJSONDocument(document);
return languageService.doComplete(document, textDocumentPosition.position, jsonDocument);
@@ -303,13 +304,13 @@ connection.onCompletion(textDocumentPosition => {
});
connection.onCompletionResolve(completionItem => {
return runSafe(() => {
return runSafeAsync(() => {
return languageService.doResolve(completionItem);
}, null, `Error while resolving completion proposal`);
}, completionItem, `Error while resolving completion proposal`);
});
connection.onHover(textDocumentPositionParams => {
return runSafe(() => {
return runSafeAsync(() => {
let document = documents.get(textDocumentPositionParams.textDocument.uri);
let jsonDocument = getJSONDocument(document);
return languageService.doHover(document, textDocumentPositionParams.position, jsonDocument);
@@ -332,13 +333,13 @@ connection.onDocumentRangeFormatting(formatParams => {
});
connection.onRequest(DocumentColorRequest.type, params => {
return runSafe(() => {
return runSafeAsync(() => {
let document = documents.get(params.textDocument.uri);
if (document) {
let jsonDocument = getJSONDocument(document);
return languageService.findDocumentColors(document, jsonDocument);
}
return [];
return Promise.resolve([]);
}, [], `Error while computing document colors for ${params.textDocument.uri}`);
});
@@ -350,7 +351,86 @@ connection.onRequest(ColorPresentationRequest.type, params => {
return languageService.getColorPresentations(document, jsonDocument, params.color, params.range);
}
return [];
}, [], `Error while computing color presentationsd for ${params.textDocument.uri}`);
}, [], `Error while computing color presentations for ${params.textDocument.uri}`);
});
connection.onRequest(FoldingRangesRequest.type, params => {
return runSafe(() => {
let document = documents.get(params.textDocument.uri);
if (document) {
let ranges: FoldingRange[] = [];
let stack: FoldingRange[] = [];
let prevStart = -1;
let scanner = createScanner(document.getText(), false);
let token = scanner.scan();
while (token !== SyntaxKind.EOF) {
switch (token) {
case SyntaxKind.OpenBraceToken:
case SyntaxKind.OpenBracketToken: {
let startLine = document.positionAt(scanner.getTokenOffset()).line;
let range = { startLine, endLine: startLine, type: token === SyntaxKind.OpenBraceToken ? 'object' : 'array' };
stack.push(range);
break;
}
case SyntaxKind.CloseBraceToken:
case SyntaxKind.CloseBracketToken: {
let type = token === SyntaxKind.CloseBraceToken ? 'object' : 'array';
if (stack.length > 0 && stack[stack.length - 1].type === type) {
let range = stack.pop();
let line = document.positionAt(scanner.getTokenOffset()).line;
if (range && line > range.startLine + 1 && prevStart !== range.startLine) {
range.endLine = line - 1;
ranges.push(range);
prevStart = range.startLine;
}
}
break;
}
case SyntaxKind.BlockCommentTrivia: {
let startLine = document.positionAt(scanner.getTokenOffset()).line;
let endLine = document.positionAt(scanner.getTokenOffset() + scanner.getTokenLength()).line;
if (startLine < endLine) {
ranges.push({ startLine, endLine, type: FoldingRangeType.Comment });
prevStart = startLine;
}
break;
}
case SyntaxKind.LineCommentTrivia: {
let text = document.getText().substr(scanner.getTokenOffset(), scanner.getTokenLength());
let m = text.match(/^\/\/\s*#(region\b)|(endregion\b)/);
if (m) {
let line = document.positionAt(scanner.getTokenOffset()).line;
if (m[1]) { // start pattern match
let range = { startLine: line, endLine: line, type: FoldingRangeType.Region };
stack.push(range);
} else {
let i = stack.length - 1;
while (i >= 0 && stack[i].type !== FoldingRangeType.Region) {
i--;
}
if (i >= 0) {
let range = stack[i];
stack.length = i;
if (line > range.startLine && prevStart !== range.startLine) {
range.endLine = line;
ranges.push(range);
prevStart = range.startLine;
}
}
}
}
break;
}
}
token = scanner.scan();
}
return <FoldingRangeList>{ ranges };
}
return null;
}, null, `Error while computing folding ranges for ${params.textDocument.uri}`);
});
// Listen on the connection
@@ -16,7 +16,7 @@ export function getLanguageModelCache<T>(maxEntries: number, cleanupIntervalTime
let languageModels: { [uri: string]: { version: number, languageId: string, cTime: number, languageModel: T } } = {};
let nModels = 0;
let cleanupInterval = void 0;
let cleanupInterval: NodeJS.Timer | undefined = void 0;
if (cleanupIntervalTimeInSec > 0) {
cleanupInterval = setInterval(() => {
let cutoffTime = Date.now() - cleanupIntervalTimeInSec * 1000;
@@ -0,0 +1,89 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { TextDocumentIdentifier } from 'vscode-languageserver-types';
import { RequestType, TextDocumentRegistrationOptions, StaticRegistrationOptions } from 'vscode-languageserver-protocol';
// ---- capabilities
export interface FoldingProviderClientCapabilities {
/**
* The text document client capabilities
*/
textDocument?: {
/**
* Capabilities specific to the foldingProvider
*/
foldingProvider?: {
/**
* Whether implementation supports dynamic registration. If this is set to `true`
* the client supports the new `(FoldingProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions)`
* return value for the corresponding server capability as well.
*/
dynamicRegistration?: boolean;
};
};
}
export interface FoldingProviderOptions {
}
export interface FoldingProviderServerCapabilities {
/**
* The server provides folding provider support.
*/
foldingProvider?: FoldingProviderOptions | (FoldingProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions);
}
export interface FoldingRangeList {
/**
* The folding ranges.
*/
ranges: FoldingRange[];
}
export enum FoldingRangeType {
/**
* Folding range for a comment
*/
Comment = 'comment',
/**
* Folding range for a imports or includes
*/
Imports = 'imports',
/**
* Folding range for a region (e.g. `#region`)
*/
Region = 'region'
}
export interface FoldingRange {
/**
* The start line number
*/
startLine: number;
/**
* The end line number
*/
endLine: number;
/**
* The actual color value for this folding range.
*/
type?: FoldingRangeType | string;
}
export interface FoldingRangeRequestParam {
/**
* The text document.
*/
textDocument: TextDocumentIdentifier;
}
export namespace FoldingRangesRequest {
export const type: RequestType<FoldingRangeRequestParam, FoldingRangeList | null, any, any> = new RequestType('textDocument/foldingRanges');
}
+9 -9
View File
@@ -16,16 +16,16 @@ export function formatError(message: string, err: any): string {
return message;
}
export function runSafe<T>(func: () => Thenable<T> | T, errorVal: T, errorMessage: string): Thenable<T> | T {
export function runSafeAsync<T>(func: () => Thenable<T>, errorVal: T, errorMessage: string): Thenable<T> {
let t = func();
return t.then(void 0, e => {
console.error(formatError(errorMessage, e));
return errorVal;
});
}
export function runSafe<T>(func: () => T, errorVal: T, errorMessage: string): T {
try {
let t = func();
if (t instanceof Promise) {
return t.then(void 0, e => {
console.error(formatError(errorMessage, e));
return errorVal;
});
}
return t;
return func();
} catch (e) {
console.error(formatError(errorMessage, e));
return errorVal;
-351
View File
@@ -1,351 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
function _encode(ch: string): string {
return '%' + ch.charCodeAt(0).toString(16).toUpperCase();
}
// see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent
function encodeURIComponent2(str: string): string {
return encodeURIComponent(str).replace(/[!'()*]/g, _encode);
}
function encodeNoop(str: string): string {
return str;
}
/**
* Uniform Resource Identifier (URI) http://tools.ietf.org/html/rfc3986.
* This class is a simple parser which creates the basic component paths
* (http://tools.ietf.org/html/rfc3986#section-3) with minimal validation
* and encoding.
*
* foo://example.com:8042/over/there?name=ferret#nose
* \_/ \______________/\_________/ \_________/ \__/
* | | | | |
* scheme authority path query fragment
* | _____________________|__
* / \ / \
* urn:example:animal:ferret:nose
*
*
*/
export default class URI {
private static _empty = '';
private static _slash = '/';
private static _regexp = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/;
private static _driveLetterPath = /^\/[a-zA-z]:/;
private static _upperCaseDrive = /^(\/)?([A-Z]:)/;
private _scheme: string;
private _authority: string;
private _path: string;
private _query: string;
private _fragment: string;
private _formatted: string;
private _fsPath: string;
constructor() {
this._scheme = URI._empty;
this._authority = URI._empty;
this._path = URI._empty;
this._query = URI._empty;
this._fragment = URI._empty;
this._formatted = null;
this._fsPath = null;
}
/**
* scheme is the 'http' part of 'http://www.msft.com/some/path?query#fragment'.
* The part before the first colon.
*/
get scheme() {
return this._scheme;
}
/**
* authority is the 'www.msft.com' part of 'http://www.msft.com/some/path?query#fragment'.
* The part between the first double slashes and the next slash.
*/
get authority() {
return this._authority;
}
/**
* path is the '/some/path' part of 'http://www.msft.com/some/path?query#fragment'.
*/
get path() {
return this._path;
}
/**
* query is the 'query' part of 'http://www.msft.com/some/path?query#fragment'.
*/
get query() {
return this._query;
}
/**
* fragment is the 'fragment' part of 'http://www.msft.com/some/path?query#fragment'.
*/
get fragment() {
return this._fragment;
}
// ---- filesystem path -----------------------
/**
* Returns a string representing the corresponding file system path of this URI.
* Will handle UNC paths and normalize windows drive letters to lower-case. Also
* uses the platform specific path separator. Will *not* validate the path for
* invalid characters and semantics. Will *not* look at the scheme of this URI.
*/
get fsPath() {
if (!this._fsPath) {
var value: string;
if (this._authority && this.scheme === 'file') {
// unc path: file://shares/c$/far/boo
value = `//${this._authority}${this._path}`;
} else if (URI._driveLetterPath.test(this._path)) {
// windows drive letter: file:///c:/far/boo
value = this._path[1].toLowerCase() + this._path.substr(2);
} else {
// other path
value = this._path;
}
if (process.platform === 'win32') {
value = value.replace(/\//g, '\\');
}
this._fsPath = value;
}
return this._fsPath;
}
// ---- modify to new -------------------------
public with(scheme: string, authority: string, path: string, query: string, fragment: string): URI {
var ret = new URI();
ret._scheme = scheme || this.scheme;
ret._authority = authority || this.authority;
ret._path = path || this.path;
ret._query = query || this.query;
ret._fragment = fragment || this.fragment;
URI._validate(ret);
return ret;
}
public withScheme(value: string): URI {
return this.with(value, undefined, undefined, undefined, undefined);
}
public withAuthority(value: string): URI {
return this.with(undefined, value, undefined, undefined, undefined);
}
public withPath(value: string): URI {
return this.with(undefined, undefined, value, undefined, undefined);
}
public withQuery(value: string): URI {
return this.with(undefined, undefined, undefined, value, undefined);
}
public withFragment(value: string): URI {
return this.with(undefined, undefined, undefined, undefined, value);
}
// ---- parse & validate ------------------------
public static parse(value: string): URI {
const ret = new URI();
const data = URI._parseComponents(value);
ret._scheme = data.scheme;
ret._authority = decodeURIComponent(data.authority);
ret._path = decodeURIComponent(data.path);
ret._query = decodeURIComponent(data.query);
ret._fragment = decodeURIComponent(data.fragment);
URI._validate(ret);
return ret;
}
public static file(path: string): URI {
const ret = new URI();
ret._scheme = 'file';
// normalize to fwd-slashes
path = path.replace(/\\/g, URI._slash);
// check for authority as used in UNC shares
// or use the path as given
if (path[0] === URI._slash && path[0] === path[1]) {
let idx = path.indexOf(URI._slash, 2);
if (idx === -1) {
ret._authority = path.substring(2);
} else {
ret._authority = path.substring(2, idx);
ret._path = path.substring(idx);
}
} else {
ret._path = path;
}
// Ensure that path starts with a slash
// or that it is at least a slash
if (ret._path[0] !== URI._slash) {
ret._path = URI._slash + ret._path;
}
URI._validate(ret);
return ret;
}
private static _parseComponents(value: string): UriComponents {
const ret: UriComponents = {
scheme: URI._empty,
authority: URI._empty,
path: URI._empty,
query: URI._empty,
fragment: URI._empty,
};
const match = URI._regexp.exec(value);
if (match) {
ret.scheme = match[2] || ret.scheme;
ret.authority = match[4] || ret.authority;
ret.path = match[5] || ret.path;
ret.query = match[7] || ret.query;
ret.fragment = match[9] || ret.fragment;
}
return ret;
}
public static create(scheme?: string, authority?: string, path?: string, query?: string, fragment?: string): URI {
return new URI().with(scheme, authority, path, query, fragment);
}
private static _validate(ret: URI): void {
// validation
// path, http://tools.ietf.org/html/rfc3986#section-3.3
// If a URI contains an authority component, then the path component
// must either be empty or begin with a slash ("/") character. If a URI
// does not contain an authority component, then the path cannot begin
// with two slash characters ("//").
if (ret.authority && ret.path && ret.path[0] !== '/') {
throw new Error('[UriError]: If a URI contains an authority component, then the path component must either be empty or begin with a slash ("/") character');
}
if (!ret.authority && ret.path.indexOf('//') === 0) {
throw new Error('[UriError]: If a URI does not contain an authority component, then the path cannot begin with two slash characters ("//")');
}
}
// ---- printing/externalize ---------------------------
/**
*
* @param skipEncoding Do not encode the result, default is `false`
*/
public toString(skipEncoding: boolean = false): string {
if (!skipEncoding) {
if (!this._formatted) {
this._formatted = URI._asFormatted(this, false);
}
return this._formatted;
} else {
// we don't cache that
return URI._asFormatted(this, true);
}
}
private static _asFormatted(uri: URI, skipEncoding: boolean): string {
const encoder = !skipEncoding
? encodeURIComponent2
: encodeNoop;
const parts: string[] = [];
let { scheme, authority, path, query, fragment } = uri;
if (scheme) {
parts.push(scheme, ':');
}
if (authority || scheme === 'file') {
parts.push('//');
}
if (authority) {
authority = authority.toLowerCase();
let idx = authority.indexOf(':');
if (idx === -1) {
parts.push(encoder(authority));
} else {
parts.push(encoder(authority.substr(0, idx)), authority.substr(idx));
}
}
if (path) {
// lower-case windown drive letters in /C:/fff
const m = URI._upperCaseDrive.exec(path);
if (m) {
path = m[1] + m[2].toLowerCase() + path.substr(m[1].length + m[2].length);
}
// encode every segement but not slashes
// make sure that # and ? are always encoded
// when occurring in paths - otherwise the result
// cannot be parsed back again
let lastIdx = 0;
while (true) {
let idx = path.indexOf(URI._slash, lastIdx);
if (idx === -1) {
parts.push(encoder(path.substring(lastIdx)).replace(/[#?]/, _encode));
break;
}
parts.push(encoder(path.substring(lastIdx, idx)).replace(/[#?]/, _encode), URI._slash);
lastIdx = idx + 1;
};
}
if (query) {
parts.push('?', encoder(query));
}
if (fragment) {
parts.push('#', encoder(fragment));
}
return parts.join(URI._empty);
}
public toJSON(): any {
return <UriState>{
scheme: this.scheme,
authority: this.authority,
path: this.path,
fsPath: this.fsPath,
query: this.query,
fragment: this.fragment,
external: this.toString(),
$mid: 1
};
}
}
interface UriComponents {
scheme: string;
authority: string;
path: string;
query: string;
fragment: string;
}
interface UriState extends UriComponents {
$mid: number;
fsPath: string;
external: string;
}