mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-07 23:36:03 +01:00
Merge branch 'master' into git-ext-strict
This commit is contained in:
Vendored
+3
-3
@@ -33,11 +33,11 @@
|
||||
"task": "tslint",
|
||||
"label": "Run tslint",
|
||||
"problemMatcher": [
|
||||
"$tslint4"
|
||||
"$tslint5"
|
||||
]
|
||||
},
|
||||
{
|
||||
"taskName": "Run tests",
|
||||
"label": "Run tests",
|
||||
"type": "shell",
|
||||
"command": "./scripts/test.sh",
|
||||
"windows": {
|
||||
@@ -50,7 +50,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"taskName": "Run Dev",
|
||||
"label": "Run Dev",
|
||||
"type": "shell",
|
||||
"command": "./scripts/code.sh",
|
||||
"windows": {
|
||||
|
||||
+15
-14
@@ -123,7 +123,8 @@ const tslintFilter = [
|
||||
'!**/node_modules/**',
|
||||
'!extensions/typescript/test/colorize-fixtures/**',
|
||||
'!extensions/vscode-api-tests/testWorkspace/**',
|
||||
'!extensions/**/*.test.ts'
|
||||
'!extensions/**/*.test.ts',
|
||||
'!extensions/html/server/lib/jquery.d.ts'
|
||||
];
|
||||
|
||||
const copyrightHeader = [
|
||||
@@ -133,17 +134,6 @@ const copyrightHeader = [
|
||||
' *--------------------------------------------------------------------------------------------*/'
|
||||
].join('\n');
|
||||
|
||||
function reportFailures(failures) {
|
||||
failures.forEach(failure => {
|
||||
const name = failure.name || failure.fileName;
|
||||
const position = failure.startPosition;
|
||||
const line = position.lineAndCharacter ? position.lineAndCharacter.line : position.line;
|
||||
const character = position.lineAndCharacter ? position.lineAndCharacter.character : position.character;
|
||||
|
||||
console.error(`${name}:${line + 1}:${character + 1}:${failure.failure}`);
|
||||
});
|
||||
}
|
||||
|
||||
gulp.task('eslint', () => {
|
||||
return vfs.src(all, { base: '.', follow: true, allowEmpty: true })
|
||||
.pipe(filter(eslintFilter))
|
||||
@@ -153,12 +143,12 @@ gulp.task('eslint', () => {
|
||||
});
|
||||
|
||||
gulp.task('tslint', () => {
|
||||
const options = { summarizeFailureOutput: true };
|
||||
const options = { emitError: false };
|
||||
|
||||
return vfs.src(all, { base: '.', follow: true, allowEmpty: true })
|
||||
.pipe(filter(tslintFilter))
|
||||
.pipe(gulptslint({ rulesDirectory: 'build/lib/tslint' }))
|
||||
.pipe(gulptslint.report(reportFailures, options));
|
||||
.pipe(gulptslint.report(options));
|
||||
});
|
||||
|
||||
const hygiene = exports.hygiene = (some, options) => {
|
||||
@@ -219,6 +209,17 @@ const hygiene = exports.hygiene = (some, options) => {
|
||||
cb(err);
|
||||
});
|
||||
});
|
||||
|
||||
function reportFailures(failures) {
|
||||
failures.forEach(failure => {
|
||||
const name = failure.name || failure.fileName;
|
||||
const position = failure.startPosition;
|
||||
const line = position.lineAndCharacter ? position.lineAndCharacter.line : position.line;
|
||||
const character = position.lineAndCharacter ? position.lineAndCharacter.character : position.character;
|
||||
|
||||
console.error(`${name}:${line + 1}:${character + 1}:${failure.failure}`);
|
||||
});
|
||||
}
|
||||
|
||||
const tsl = es.through(function (file) {
|
||||
const configuration = tslint.Configuration.findConfiguration(null, '.');
|
||||
|
||||
@@ -452,7 +452,7 @@ gulp.task('upload-vscode-sourcemaps', ['minify-vscode'], () => {
|
||||
const allConfigDetailsPath = path.join(os.tmpdir(), 'configuration.json');
|
||||
gulp.task('upload-vscode-configuration', ['generate-vscode-configuration'], () => {
|
||||
const branch = process.env.BUILD_SOURCEBRANCH;
|
||||
if (!branch.endsWith('/master') && !branch.indexOf('/release/') >= 0) {
|
||||
if (!branch.endsWith('/master') && !branch.startsWith('release/')) {
|
||||
console.log(`Only runs on master and release branches, not ${branch}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -88,10 +88,11 @@ var NoUnexternalizedStringsRuleWalker = /** @class */ (function (_super) {
|
||||
var info = this.findDescribingParent(node);
|
||||
// Ignore strings in import and export nodes.
|
||||
if (info && info.isImport && doubleQuoted) {
|
||||
this.addFailureAtNode(node, NoUnexternalizedStringsRuleWalker.ImportFailureMessage, new Lint.Fix(NoUnexternalizedStringsRuleWalker.ImportFailureMessage, [
|
||||
this.createReplacement(node.getStart(), 1, '\''),
|
||||
this.createReplacement(node.getStart() + text.length - 1, 1, '\''),
|
||||
]));
|
||||
var fix = [
|
||||
Lint.Replacement.replaceFromTo(node.getStart(), 1, '\''),
|
||||
Lint.Replacement.replaceFromTo(node.getStart() + text.length - 1, 1, '\''),
|
||||
];
|
||||
this.addFailureAtNode(node, NoUnexternalizedStringsRuleWalker.ImportFailureMessage, fix);
|
||||
return;
|
||||
}
|
||||
var callInfo = info ? info.callInfo : null;
|
||||
@@ -101,8 +102,9 @@ var NoUnexternalizedStringsRuleWalker = /** @class */ (function (_super) {
|
||||
}
|
||||
if (doubleQuoted && (!callInfo || callInfo.argIndex === -1 || !this.signatures[functionName])) {
|
||||
var s = node.getText();
|
||||
var replacement = new Lint.Replacement(node.getStart(), node.getWidth(), "nls.localize('KEY-" + s.substring(1, s.length - 1) + "', " + s + ")");
|
||||
var fix = new Lint.Fix('Unexternalitzed string', [replacement]);
|
||||
var fix = [
|
||||
Lint.Replacement.replaceFromTo(node.getStart(), node.getWidth(), "nls.localize('KEY-" + s.substring(1, s.length - 1) + "', " + s + ")"),
|
||||
];
|
||||
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), "Unexternalized string found: " + node.getText(), fix));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -104,13 +104,14 @@ class NoUnexternalizedStringsRuleWalker extends Lint.RuleWalker {
|
||||
let info = this.findDescribingParent(node);
|
||||
// Ignore strings in import and export nodes.
|
||||
if (info && info.isImport && doubleQuoted) {
|
||||
const fix = [
|
||||
Lint.Replacement.replaceFromTo(node.getStart(), 1, '\''),
|
||||
Lint.Replacement.replaceFromTo(node.getStart() + text.length - 1, 1, '\''),
|
||||
];
|
||||
this.addFailureAtNode(
|
||||
node,
|
||||
NoUnexternalizedStringsRuleWalker.ImportFailureMessage,
|
||||
new Lint.Fix(NoUnexternalizedStringsRuleWalker.ImportFailureMessage, [
|
||||
this.createReplacement(node.getStart(), 1, '\''),
|
||||
this.createReplacement(node.getStart() + text.length - 1, 1, '\''),
|
||||
])
|
||||
fix
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -122,8 +123,9 @@ class NoUnexternalizedStringsRuleWalker extends Lint.RuleWalker {
|
||||
|
||||
if (doubleQuoted && (!callInfo || callInfo.argIndex === -1 || !this.signatures[functionName])) {
|
||||
const s = node.getText();
|
||||
const replacement = new Lint.Replacement(node.getStart(), node.getWidth(), `nls.localize('KEY-${s.substring(1, s.length - 1)}', ${s})`);
|
||||
const fix = new Lint.Fix('Unexternalitzed string', [replacement]);
|
||||
const fix = [
|
||||
Lint.Replacement.replaceFromTo(node.getStart(), node.getWidth(), `nls.localize('KEY-${s.substring(1, s.length - 1)}', ${s})`),
|
||||
];
|
||||
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), `Unexternalized string found: ${node.getText()}`, fix));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
pat
|
||||
pat
|
||||
*.js
|
||||
@@ -0,0 +1,42 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 { DocumentClient } from 'documentdb';
|
||||
|
||||
interface Config {
|
||||
id: string;
|
||||
frozen: boolean;
|
||||
}
|
||||
|
||||
function createDefaultConfig(quality: string): Config {
|
||||
return {
|
||||
id: quality,
|
||||
frozen: false
|
||||
};
|
||||
}
|
||||
|
||||
function getConfig(quality: string): Promise<Config> {
|
||||
const client = new DocumentClient(process.env['AZURE_DOCUMENTDB_ENDPOINT'], { masterKey: process.env['AZURE_DOCUMENTDB_MASTERKEY'] });
|
||||
const collection = 'dbs/builds/colls/config';
|
||||
const query = {
|
||||
query: `SELECT TOP 1 * FROM c WHERE c.id = @quality`,
|
||||
parameters: [
|
||||
{ name: '@quality', value: quality }
|
||||
]
|
||||
};
|
||||
|
||||
return new Promise<Config>((c, e) => {
|
||||
client.queryDocuments(collection, query).toArray((err, results) => {
|
||||
if (err && err.code !== 409) { return e(err); }
|
||||
|
||||
c(!results || results.length === 0 ? createDefaultConfig(quality) : results[0] as any as Config);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getConfig(process.argv[2])
|
||||
.then(c => console.log(c.frozen), e => console.error(e));
|
||||
@@ -55,8 +55,12 @@ step "Publish RPM package" \
|
||||
# SNAP_FILENAME="$(ls $REPO/.build/linux/snap/$ARCH/ | grep .snap)"
|
||||
# SNAP_PATH="$REPO/.build/linux/snap/$ARCH/$SNAP_FILENAME"
|
||||
|
||||
IS_FROZEN="$(node build/tfs/linux/frozen-check.js $VSCODE_QUALITY)"
|
||||
|
||||
if [ -z "$VSCODE_QUALITY" ]; then
|
||||
echo "VSCODE_QUALITY is not set, skipping repo package publish"
|
||||
elif [ "$IS_FROZEN" = "true" ]; then
|
||||
echo "$VSCODE_QUALITY is frozen, skipping repo package publish"
|
||||
else
|
||||
if [ "$BUILD_SOURCEBRANCH" = "master" ] || [ "$BUILD_SOURCEBRANCH" = "refs/heads/master" ]; then
|
||||
if [[ $BUILD_QUEUEDBY = *"Project Collection Service Accounts"* || $BUILD_QUEUEDBY = *"Microsoft.VisualStudio.Services.TFS"* ]]; then
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
"outDir": "./out",
|
||||
"noUnusedLocals": true,
|
||||
"lib": [
|
||||
"es5", "es2015.promise"
|
||||
]
|
||||
|
||||
@@ -20,5 +20,11 @@
|
||||
["(", ")"],
|
||||
["\"", "\""],
|
||||
["'", "'"]
|
||||
]
|
||||
}
|
||||
],
|
||||
"folding": {
|
||||
"markers": {
|
||||
"start": "^\\s*\\/\\*\\s*#region\\b\\s*(.*?)\\s*\\*\\/",
|
||||
"end": "^\\s*\\/\\*\\s*#endregion\\b.*\\*\\/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
"outDir": "./out",
|
||||
"noUnusedLocals": true,
|
||||
"lib": [
|
||||
"es5"
|
||||
]
|
||||
|
||||
@@ -17,8 +17,8 @@ interface ExpandAbbreviationInput {
|
||||
filter?: string;
|
||||
}
|
||||
|
||||
export function wrapWithAbbreviation(args) {
|
||||
if (!validate(false)) {
|
||||
export function wrapWithAbbreviation(args: any) {
|
||||
if (!validate(false) || !vscode.window.activeTextEditor) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -50,8 +50,8 @@ export function wrapWithAbbreviation(args) {
|
||||
});
|
||||
}
|
||||
|
||||
export function wrapIndividualLinesWithAbbreviation(args) {
|
||||
if (!validate(false)) {
|
||||
export function wrapIndividualLinesWithAbbreviation(args: any) {
|
||||
if (!validate(false) || !vscode.window.activeTextEditor) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ export function wrapIndividualLinesWithAbbreviation(args) {
|
||||
|
||||
}
|
||||
|
||||
export function expandEmmetAbbreviation(args): Thenable<boolean> {
|
||||
export function expandEmmetAbbreviation(args: any): Thenable<boolean> {
|
||||
const syntax = getSyntaxFromArgs(args);
|
||||
if (!syntax || !validate()) {
|
||||
return fallbackTab();
|
||||
@@ -179,7 +179,7 @@ export function expandEmmetAbbreviation(args): Thenable<boolean> {
|
||||
});
|
||||
}
|
||||
|
||||
function fallbackTab(): Thenable<boolean> {
|
||||
function fallbackTab(): Thenable<boolean | undefined> | undefined {
|
||||
if (vscode.workspace.getConfiguration('emmet')['triggerExpansionOnTab'] === true) {
|
||||
return vscode.commands.executeCommand('tab');
|
||||
}
|
||||
@@ -226,7 +226,8 @@ export function isValidLocationForEmmetAbbreviation(currentNode: Node, syntax: s
|
||||
|
||||
const currentHtmlNode = <HtmlNode>currentNode;
|
||||
if (currentHtmlNode.close) {
|
||||
return getInnerRange(currentHtmlNode).contains(position);
|
||||
const innerRange = getInnerRange(currentHtmlNode);
|
||||
return !!innerRange && innerRange.contains(position);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -247,7 +248,7 @@ function expandAbbreviationInRange(editor: vscode.TextEditor, expandAbbrList: Ex
|
||||
// Snippet to replace at multiple cursors are not the same
|
||||
// `editor.insertSnippet` will have to be called for each instance separately
|
||||
// We will not be able to maintain multiple cursors after snippet insertion
|
||||
let insertPromises = [];
|
||||
let insertPromises: Thenable<boolean>[] = [];
|
||||
if (!insertSameSnippet) {
|
||||
expandAbbrList.forEach((expandAbbrInput: ExpandAbbreviationInput) => {
|
||||
let expandedText = expandAbbr(expandAbbrInput);
|
||||
@@ -278,7 +279,7 @@ function expandAbbreviationInRange(editor: vscode.TextEditor, expandAbbrList: Ex
|
||||
/**
|
||||
* Expands abbreviation as detailed in given input.
|
||||
*/
|
||||
function expandAbbr(input: ExpandAbbreviationInput): string {
|
||||
function expandAbbr(input: ExpandAbbreviationInput): string | undefined {
|
||||
const helper = getEmmetHelper();
|
||||
const expandOptions = helper.getExpandOptions(input.syntax, getEmmetConfiguration(input.syntax), input.filter);
|
||||
|
||||
@@ -322,7 +323,7 @@ function expandAbbr(input: ExpandAbbreviationInput): string {
|
||||
|
||||
}
|
||||
|
||||
function getSyntaxFromArgs(args: any): string {
|
||||
function getSyntaxFromArgs(args: any): string | undefined {
|
||||
let editor = vscode.window.activeTextEditor;
|
||||
if (!editor) {
|
||||
vscode.window.showInformationMessage('No editor is active.');
|
||||
|
||||
@@ -16,11 +16,10 @@ export function balanceIn() {
|
||||
}
|
||||
|
||||
function balance(out: boolean) {
|
||||
let editor = vscode.window.activeTextEditor;
|
||||
if (!validate(false)) {
|
||||
if (!validate(false) || !vscode.window.activeTextEditor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
let rootNode = <HtmlNode>parseDocument(editor.document);
|
||||
if (!rootNode) {
|
||||
return;
|
||||
@@ -30,7 +29,7 @@ function balance(out: boolean) {
|
||||
let newSelections: vscode.Selection[] = [];
|
||||
editor.selections.forEach(selection => {
|
||||
let range = getRangeFunction(editor.document, selection, rootNode);
|
||||
newSelections.push(range ? range : selection);
|
||||
newSelections.push(range);
|
||||
});
|
||||
|
||||
editor.selection = newSelections[0];
|
||||
@@ -40,7 +39,7 @@ function balance(out: boolean) {
|
||||
function getRangeToBalanceOut(document: vscode.TextDocument, selection: vscode.Selection, rootNode: HtmlNode): vscode.Selection {
|
||||
let nodeToBalance = <HtmlNode>getNode(rootNode, selection.start);
|
||||
if (!nodeToBalance) {
|
||||
return;
|
||||
return selection;
|
||||
}
|
||||
if (!nodeToBalance.close) {
|
||||
return new vscode.Selection(nodeToBalance.start, nodeToBalance.end);
|
||||
@@ -55,13 +54,13 @@ function getRangeToBalanceOut(document: vscode.TextDocument, selection: vscode.S
|
||||
if (outerSelection.contains(selection) && !outerSelection.isEqual(selection)) {
|
||||
return outerSelection;
|
||||
}
|
||||
return;
|
||||
return selection;
|
||||
}
|
||||
|
||||
function getRangeToBalanceIn(document: vscode.TextDocument, selection: vscode.Selection, rootNode: HtmlNode): vscode.Selection {
|
||||
let nodeToBalance = <HtmlNode>getNode(rootNode, selection.start, true);
|
||||
if (!nodeToBalance) {
|
||||
return;
|
||||
return selection;
|
||||
}
|
||||
|
||||
if (selection.start.isEqual(nodeToBalance.start)
|
||||
@@ -71,7 +70,7 @@ function getRangeToBalanceIn(document: vscode.TextDocument, selection: vscode.Se
|
||||
}
|
||||
|
||||
if (!nodeToBalance.firstChild) {
|
||||
return;
|
||||
return selection;
|
||||
}
|
||||
|
||||
if (selection.start.isEqual(nodeToBalance.firstChild.start)
|
||||
|
||||
@@ -43,20 +43,16 @@ export class DocumentStreamReader {
|
||||
|
||||
/**
|
||||
* Creates a new stream instance which is limited to given range for given document
|
||||
* @param {Position} start
|
||||
* @param {Position} end
|
||||
* @return {DocumentStreamReader}
|
||||
*/
|
||||
limit(start, end) {
|
||||
limit(start: Position, end: Position): DocumentStreamReader {
|
||||
return new DocumentStreamReader(this.document, start, new Range(start, end));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next character code in the stream without advancing it.
|
||||
* Will return NaN at the end of the file.
|
||||
* @returns {Number}
|
||||
*/
|
||||
peek() {
|
||||
peek(): number {
|
||||
if (this.eof()) {
|
||||
return NaN;
|
||||
}
|
||||
@@ -67,9 +63,8 @@ export class DocumentStreamReader {
|
||||
/**
|
||||
* Returns the next character in the stream and advances it.
|
||||
* Also returns NaN when no more characters are available.
|
||||
* @returns {Number}
|
||||
*/
|
||||
next() {
|
||||
next(): number {
|
||||
if (this.eof()) {
|
||||
return NaN;
|
||||
}
|
||||
@@ -95,9 +90,8 @@ export class DocumentStreamReader {
|
||||
/**
|
||||
* Backs up the stream n characters. Backing it up further than the
|
||||
* start of the current token will cause things to break, so be careful.
|
||||
* @param {Number} n
|
||||
*/
|
||||
backUp(n) {
|
||||
backUp(n: number) {
|
||||
let row = this.pos.line;
|
||||
let column = this.pos.character;
|
||||
column -= (n || 1);
|
||||
@@ -117,28 +111,22 @@ export class DocumentStreamReader {
|
||||
/**
|
||||
* Get the string between the start of the current token and the
|
||||
* current stream position.
|
||||
* @returns {String}
|
||||
*/
|
||||
current() {
|
||||
current(): string {
|
||||
return this.substring(this.start, this.pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns contents for given range
|
||||
* @param {Position} from
|
||||
* @param {Position} to
|
||||
* @return {String}
|
||||
*/
|
||||
substring(from, to) {
|
||||
substring(from: Position, to: Position): string {
|
||||
return this.document.getText(new Range(from, to));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates error object with current stream state
|
||||
* @param {String} message
|
||||
* @return {Error}
|
||||
*/
|
||||
error(message) {
|
||||
error(message: string): Error {
|
||||
const err = new Error(`${message} at row ${this.pos.line}, column ${this.pos.character}`);
|
||||
|
||||
return err;
|
||||
@@ -146,10 +134,8 @@ export class DocumentStreamReader {
|
||||
|
||||
/**
|
||||
* Returns line length of given row, including line ending
|
||||
* @param {Number} row
|
||||
* @return {Number}
|
||||
*/
|
||||
_lineLength(row) {
|
||||
_lineLength(row: number): number {
|
||||
if (row === this.document.lineCount - 1) {
|
||||
return this.document.lineAt(row).text.length;
|
||||
}
|
||||
@@ -161,10 +147,8 @@ export class DocumentStreamReader {
|
||||
* and returns a boolean. If the next character in the stream 'matches'
|
||||
* the given argument, it is consumed and returned.
|
||||
* Otherwise, `false` is returned.
|
||||
* @param {Number|Function} match
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
eat(match) {
|
||||
eat(match: number | Function): boolean {
|
||||
const ch = this.peek();
|
||||
const ok = typeof match === 'function' ? match(ch) : ch === match;
|
||||
|
||||
@@ -178,10 +162,8 @@ export class DocumentStreamReader {
|
||||
/**
|
||||
* Repeatedly calls <code>eat</code> with the given argument, until it
|
||||
* fails. Returns <code>true</code> if any characters were eaten.
|
||||
* @param {Object} match
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
eatWhile(match) {
|
||||
eatWhile(match: number | Function): boolean {
|
||||
const start = this.pos;
|
||||
while (!this.eof() && this.eat(match)) { }
|
||||
return !this.pos.isEqual(start);
|
||||
|
||||
@@ -12,7 +12,7 @@ const allowedMimeTypesInScriptTag = ['text/html', 'text/plain', 'text/x-template
|
||||
|
||||
export class DefaultCompletionItemProvider implements vscode.CompletionItemProvider {
|
||||
|
||||
public provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Thenable<vscode.CompletionList> {
|
||||
public provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Thenable<vscode.CompletionList | undefined> | undefined {
|
||||
const mappedLanguages = getMappingForIncludedLanguages();
|
||||
const emmetConfig = vscode.workspace.getConfiguration('emmet');
|
||||
|
||||
@@ -45,8 +45,8 @@ export class DefaultCompletionItemProvider implements vscode.CompletionItemProvi
|
||||
if (abbreviation.startsWith('this.')) {
|
||||
noiseCheckPromise = Promise.resolve(true);
|
||||
} else {
|
||||
noiseCheckPromise = vscode.commands.executeCommand('vscode.executeDocumentSymbolProvider', document.uri).then((symbols: vscode.SymbolInformation[]) => {
|
||||
return symbols.find(x => abbreviation === x.name || (abbreviation.startsWith(x.name + '.') && !/>|\*|\+/.test(abbreviation)));
|
||||
noiseCheckPromise = vscode.commands.executeCommand<vscode.SymbolInformation[]>('vscode.executeDocumentSymbolProvider', document.uri).then((symbols: vscode.SymbolInformation[] | undefined) => {
|
||||
return symbols && symbols.find(x => abbreviation === x.name || (abbreviation.startsWith(x.name + '.') && !/>|\*|\+/.test(abbreviation)));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -88,7 +88,7 @@ export class DefaultCompletionItemProvider implements vscode.CompletionItemProvi
|
||||
* @param document vscode.Textdocument
|
||||
* @param position vscode.Position position of the abbreviation that needs to be expanded
|
||||
*/
|
||||
private syntaxHelper(syntax: string, document: vscode.TextDocument, position: vscode.Position): string {
|
||||
private syntaxHelper(syntax: string | undefined, document: vscode.TextDocument, position: vscode.Position): string | undefined {
|
||||
if (!syntax) {
|
||||
return syntax;
|
||||
}
|
||||
|
||||
@@ -7,40 +7,42 @@ import * as vscode from 'vscode';
|
||||
import { validate } from './util';
|
||||
|
||||
export function fetchEditPoint(direction: string): void {
|
||||
let editor = vscode.window.activeTextEditor;
|
||||
if (!validate()) {
|
||||
if (!validate() || !vscode.window.activeTextEditor) {
|
||||
return;
|
||||
}
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
|
||||
let newSelections: vscode.Selection[] = [];
|
||||
editor.selections.forEach(selection => {
|
||||
let updatedSelection = direction === 'next' ? nextEditPoint(selection.anchor, editor) : prevEditPoint(selection.anchor, editor);
|
||||
newSelections.push(updatedSelection ? updatedSelection : selection);
|
||||
let updatedSelection = direction === 'next' ? nextEditPoint(selection, editor) : prevEditPoint(selection, editor);
|
||||
newSelections.push(updatedSelection);
|
||||
});
|
||||
editor.selections = newSelections;
|
||||
editor.revealRange(editor.selections[editor.selections.length - 1]);
|
||||
}
|
||||
|
||||
function nextEditPoint(position: vscode.Position, editor: vscode.TextEditor): vscode.Selection {
|
||||
for (let lineNum = position.line; lineNum < editor.document.lineCount; lineNum++) {
|
||||
let updatedSelection = findEditPoint(lineNum, editor, position, 'next');
|
||||
function nextEditPoint(selection: vscode.Selection, editor: vscode.TextEditor): vscode.Selection {
|
||||
for (let lineNum = selection.anchor.line; lineNum < editor.document.lineCount; lineNum++) {
|
||||
let updatedSelection = findEditPoint(lineNum, editor, selection.anchor, 'next');
|
||||
if (updatedSelection) {
|
||||
return updatedSelection;
|
||||
}
|
||||
}
|
||||
return selection;
|
||||
}
|
||||
|
||||
function prevEditPoint(position: vscode.Position, editor: vscode.TextEditor): vscode.Selection {
|
||||
for (let lineNum = position.line; lineNum >= 0; lineNum--) {
|
||||
let updatedSelection = findEditPoint(lineNum, editor, position, 'prev');
|
||||
function prevEditPoint(selection: vscode.Selection, editor: vscode.TextEditor): vscode.Selection {
|
||||
for (let lineNum = selection.anchor.line; lineNum >= 0; lineNum--) {
|
||||
let updatedSelection = findEditPoint(lineNum, editor, selection.anchor, 'prev');
|
||||
if (updatedSelection) {
|
||||
return updatedSelection;
|
||||
}
|
||||
}
|
||||
return selection;
|
||||
}
|
||||
|
||||
|
||||
function findEditPoint(lineNum: number, editor: vscode.TextEditor, position: vscode.Position, direction: string): vscode.Selection {
|
||||
function findEditPoint(lineNum: number, editor: vscode.TextEditor, position: vscode.Position, direction: string): vscode.Selection | undefined {
|
||||
let line = editor.document.lineAt(lineNum);
|
||||
let lineContent = line.text;
|
||||
|
||||
|
||||
@@ -10,11 +10,11 @@ import evaluate from '@emmetio/math-expression';
|
||||
import { DocumentStreamReader } from './bufferStream';
|
||||
|
||||
export function evaluateMathExpression() {
|
||||
let editor = vscode.window.activeTextEditor;
|
||||
if (!editor) {
|
||||
if (!vscode.window.activeTextEditor) {
|
||||
vscode.window.showInformationMessage('No editor is active');
|
||||
return;
|
||||
}
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
const stream = new DocumentStreamReader(editor.document);
|
||||
editor.edit(editBuilder => {
|
||||
editor.selections.forEach(selection => {
|
||||
|
||||
@@ -19,20 +19,16 @@ const reUrl = /^https?:/;
|
||||
/**
|
||||
* Get size of given image file. Supports files from local filesystem,
|
||||
* as well as URLs
|
||||
* @param {String} file Path to local file or URL
|
||||
* @return {Promise}
|
||||
*/
|
||||
export function getImageSize(file) {
|
||||
export function getImageSize(file: string) {
|
||||
file = file.replace(/^file:\/\//, '');
|
||||
return reUrl.test(file) ? getImageSizeFromURL(file) : getImageSizeFromFile(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image size from file on local file system
|
||||
* @param {String} file
|
||||
* @return {Promise}
|
||||
*/
|
||||
function getImageSizeFromFile(file) {
|
||||
function getImageSizeFromFile(file: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const isDataUrl = file.match(/^data:.+?;base64,/);
|
||||
|
||||
@@ -46,7 +42,7 @@ function getImageSizeFromFile(file) {
|
||||
}
|
||||
}
|
||||
|
||||
sizeOf(file, (err, size) => {
|
||||
sizeOf(file, (err: any, size: any) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
@@ -58,15 +54,13 @@ function getImageSizeFromFile(file) {
|
||||
|
||||
/**
|
||||
* Get image size from given remove URL
|
||||
* @param {String} url
|
||||
* @return {Promise}
|
||||
*/
|
||||
function getImageSizeFromURL(url) {
|
||||
function getImageSizeFromURL(urlStr: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
url = parseUrl(url);
|
||||
const url = parseUrl(urlStr);
|
||||
const getTransport = url.protocol === 'https:' ? https.get : http.get;
|
||||
|
||||
getTransport(url, resp => {
|
||||
getTransport(url as any, resp => {
|
||||
const chunks = [];
|
||||
let bufSize = 0;
|
||||
|
||||
@@ -102,11 +96,8 @@ function getImageSizeFromURL(url) {
|
||||
/**
|
||||
* Returns size object for given file name. If file name contains `@Nx` token,
|
||||
* the final dimentions will be downscaled by N
|
||||
* @param {String} fileName
|
||||
* @param {Object} size
|
||||
* @return {Object}
|
||||
*/
|
||||
function sizeForFileName(fileName, size) {
|
||||
function sizeForFileName(fileName: string, size: any) {
|
||||
const m = fileName.match(/@(\d+)x\./);
|
||||
const scale = m ? +m[1] : 1;
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ import * as vscode from 'vscode';
|
||||
import { getDeepestNode, findNextWord, findPrevWord, getNode } from './util';
|
||||
import { HtmlNode } from 'EmmetNode';
|
||||
|
||||
export function nextItemHTML(selectionStart: vscode.Position, selectionEnd: vscode.Position, editor: vscode.TextEditor, rootNode: HtmlNode): vscode.Selection {
|
||||
export function nextItemHTML(selectionStart: vscode.Position, selectionEnd: vscode.Position, editor: vscode.TextEditor, rootNode: HtmlNode): vscode.Selection | undefined {
|
||||
let currentNode = <HtmlNode>getNode(rootNode, selectionEnd);
|
||||
let nextNode: HtmlNode;
|
||||
let nextNode: HtmlNode | undefined = undefined;
|
||||
|
||||
if (!currentNode) {
|
||||
return;
|
||||
@@ -50,12 +50,12 @@ export function nextItemHTML(selectionStart: vscode.Position, selectionEnd: vsco
|
||||
}
|
||||
}
|
||||
|
||||
return getSelectionFromNode(nextNode, editor.document);
|
||||
return nextNode && getSelectionFromNode(nextNode, editor.document);
|
||||
}
|
||||
|
||||
export function prevItemHTML(selectionStart: vscode.Position, selectionEnd: vscode.Position, editor: vscode.TextEditor, rootNode: HtmlNode): vscode.Selection {
|
||||
export function prevItemHTML(selectionStart: vscode.Position, selectionEnd: vscode.Position, editor: vscode.TextEditor, rootNode: HtmlNode): vscode.Selection | undefined {
|
||||
let currentNode = <HtmlNode>getNode(rootNode, selectionStart);
|
||||
let prevNode: HtmlNode;
|
||||
let prevNode: HtmlNode | undefined = undefined;
|
||||
|
||||
if (!currentNode) {
|
||||
return;
|
||||
@@ -68,7 +68,7 @@ export function prevItemHTML(selectionStart: vscode.Position, selectionEnd: vsco
|
||||
} else {
|
||||
// Select the child that appears just before the cursor and is not a comment
|
||||
prevNode = currentNode.firstChild;
|
||||
let oldOption: HtmlNode;
|
||||
let oldOption: HtmlNode | undefined = undefined;
|
||||
while (prevNode.nextSibling && selectionStart.isAfterOrEqual(prevNode.nextSibling.end)) {
|
||||
if (prevNode && prevNode.type !== 'comment') {
|
||||
oldOption = prevNode;
|
||||
@@ -94,20 +94,25 @@ export function prevItemHTML(selectionStart: vscode.Position, selectionEnd: vsco
|
||||
|
||||
}
|
||||
|
||||
if (!prevNode) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let attrSelection = getPrevAttribute(selectionStart, selectionEnd, editor.document, prevNode);
|
||||
return attrSelection ? attrSelection : getSelectionFromNode(prevNode, editor.document);
|
||||
}
|
||||
|
||||
function getSelectionFromNode(node: HtmlNode, document: vscode.TextDocument): vscode.Selection {
|
||||
function getSelectionFromNode(node: HtmlNode, document: vscode.TextDocument): vscode.Selection | undefined {
|
||||
if (node && node.open) {
|
||||
let selectionStart = (<vscode.Position>node.open.start).translate(0, 1);
|
||||
let selectionEnd = selectionStart.translate(0, node.name.length);
|
||||
|
||||
return new vscode.Selection(selectionStart, selectionEnd);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getNextAttribute(selectionStart: vscode.Position, selectionEnd: vscode.Position, document: vscode.TextDocument, node: HtmlNode): vscode.Selection {
|
||||
function getNextAttribute(selectionStart: vscode.Position, selectionEnd: vscode.Position, document: vscode.TextDocument, node: HtmlNode): vscode.Selection | undefined {
|
||||
|
||||
if (!node.attributes || node.attributes.length === 0 || node.type === 'comment') {
|
||||
return;
|
||||
@@ -158,7 +163,7 @@ function getNextAttribute(selectionStart: vscode.Position, selectionEnd: vscode.
|
||||
}
|
||||
}
|
||||
|
||||
function getPrevAttribute(selectionStart: vscode.Position, selectionEnd: vscode.Position, document: vscode.TextDocument, node: HtmlNode): vscode.Selection {
|
||||
function getPrevAttribute(selectionStart: vscode.Position, selectionEnd: vscode.Position, document: vscode.TextDocument, node: HtmlNode): vscode.Selection | undefined {
|
||||
|
||||
if (!node.attributes || node.attributes.length === 0 || node.type === 'comment') {
|
||||
return;
|
||||
|
||||
@@ -7,7 +7,7 @@ import * as vscode from 'vscode';
|
||||
import { getDeepestNode, findNextWord, findPrevWord, getNode } from './util';
|
||||
import { Node, CssNode, Rule, Property } from 'EmmetNode';
|
||||
|
||||
export function nextItemStylesheet(startOffset: vscode.Position, endOffset: vscode.Position, editor: vscode.TextEditor, rootNode: Node): vscode.Selection {
|
||||
export function nextItemStylesheet(startOffset: vscode.Position, endOffset: vscode.Position, editor: vscode.TextEditor, rootNode: Node): vscode.Selection | undefined {
|
||||
let currentNode = <CssNode>getNode(rootNode, endOffset, true);
|
||||
if (!currentNode) {
|
||||
currentNode = <CssNode>rootNode;
|
||||
@@ -50,7 +50,7 @@ export function nextItemStylesheet(startOffset: vscode.Position, endOffset: vsco
|
||||
|
||||
}
|
||||
|
||||
export function prevItemStylesheet(startOffset: vscode.Position, endOffset: vscode.Position, editor: vscode.TextEditor, rootNode: CssNode): vscode.Selection {
|
||||
export function prevItemStylesheet(startOffset: vscode.Position, endOffset: vscode.Position, editor: vscode.TextEditor, rootNode: CssNode): vscode.Selection | undefined {
|
||||
let currentNode = <CssNode>getNode(rootNode, startOffset);
|
||||
if (!currentNode) {
|
||||
currentNode = rootNode;
|
||||
@@ -88,7 +88,7 @@ export function prevItemStylesheet(startOffset: vscode.Position, endOffset: vsco
|
||||
}
|
||||
|
||||
|
||||
function getSelectionFromNode(node: Node, document: vscode.TextDocument): vscode.Selection {
|
||||
function getSelectionFromNode(node: Node, document: vscode.TextDocument): vscode.Selection | undefined {
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
@@ -98,7 +98,7 @@ function getSelectionFromNode(node: Node, document: vscode.TextDocument): vscode
|
||||
}
|
||||
|
||||
|
||||
function getSelectionFromProperty(node: Node, document: vscode.TextDocument, selectionStart: vscode.Position, selectionEnd: vscode.Position, selectFullValue: boolean, direction: string): vscode.Selection {
|
||||
function getSelectionFromProperty(node: Node, document: vscode.TextDocument, selectionStart: vscode.Position, selectionEnd: vscode.Position, selectFullValue: boolean, direction: string): vscode.Selection | undefined {
|
||||
if (!node || node.type !== 'property') {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -8,11 +8,11 @@ import { HtmlNode } from 'EmmetNode';
|
||||
import { getNode, parseDocument, validate } from './util';
|
||||
|
||||
export function splitJoinTag() {
|
||||
let editor = vscode.window.activeTextEditor;
|
||||
if (!validate(false)) {
|
||||
if (!validate(false) || !vscode.window.activeTextEditor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
let rootNode = <HtmlNode>parseDocument(editor.document);
|
||||
if (!rootNode) {
|
||||
return;
|
||||
@@ -20,23 +20,19 @@ export function splitJoinTag() {
|
||||
|
||||
return editor.edit(editBuilder => {
|
||||
editor.selections.reverse().forEach(selection => {
|
||||
let textEdit = getRangesToReplace(editor.document, selection, rootNode);
|
||||
if (textEdit) {
|
||||
let nodeToUpdate = <HtmlNode>getNode(rootNode, selection.start);
|
||||
if (nodeToUpdate) {
|
||||
let textEdit = getRangesToReplace(editor.document, nodeToUpdate);
|
||||
editBuilder.replace(textEdit.range, textEdit.newText);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getRangesToReplace(document: vscode.TextDocument, selection: vscode.Selection, rootNode: HtmlNode): vscode.TextEdit {
|
||||
let nodeToUpdate = <HtmlNode>getNode(rootNode, selection.start);
|
||||
function getRangesToReplace(document: vscode.TextDocument, nodeToUpdate: HtmlNode): vscode.TextEdit {
|
||||
let rangeToReplace: vscode.Range;
|
||||
let textToReplaceWith: string;
|
||||
|
||||
if (!nodeToUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nodeToUpdate.close) {
|
||||
// Split Tag
|
||||
let nodeText = document.getText(new vscode.Range(nodeToUpdate.start, nodeToUpdate.end));
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'mocha';
|
||||
import * as assert from 'assert';
|
||||
import { Selection, workspace } from 'vscode';
|
||||
import { withRandomFileEditor, closeAllEditors } from './testUtils';
|
||||
@@ -221,13 +222,13 @@ m10
|
||||
.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
|
||||
new Selection(5, 15, 5, 15) // in the value part of property value
|
||||
];
|
||||
return expandEmmetAbbreviation(null).then(() => {
|
||||
assert.equal(editor.document.getText(), scssContentsNoExpand);
|
||||
@@ -344,7 +345,7 @@ suite('Tests for Wrap with Abbreviations', () => {
|
||||
|
||||
suite('Tests for jsx, xml and xsl', () => {
|
||||
teardown(closeAllEditors);
|
||||
|
||||
|
||||
test('Expand abbreviation with className instead of class in jsx', () => {
|
||||
return withRandomFileEditor('ul.nav', 'javascriptreact', (editor, doc) => {
|
||||
editor.selection = new Selection(0, 6, 0, 6);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'mocha';
|
||||
import * as assert from 'assert';
|
||||
import { Selection } from 'vscode';
|
||||
import { withRandomFileEditor, closeAllEditors } from './testUtils';
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'mocha';
|
||||
import * as assert from 'assert';
|
||||
import { Selection } from 'vscode';
|
||||
import { withRandomFileEditor, closeAllEditors } from './testUtils';
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'mocha';
|
||||
import * as assert from 'assert';
|
||||
import { Selection, commands } from 'vscode';
|
||||
import { Selection } from 'vscode';
|
||||
import { withRandomFileEditor, closeAllEditors } from './testUtils';
|
||||
import { reflectCssValue } from '../reflectCssValue';
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'mocha';
|
||||
import * as assert from 'assert';
|
||||
import { Selection } from 'vscode';
|
||||
import { withRandomFileEditor, closeAllEditors } from './testUtils';
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'mocha';
|
||||
import * as assert from 'assert';
|
||||
import { Selection } from 'vscode';
|
||||
import { withRandomFileEditor, closeAllEditors } from './testUtils';
|
||||
|
||||
@@ -3,15 +3,14 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'mocha';
|
||||
import * as assert from 'assert';
|
||||
import { Selection } from 'vscode';
|
||||
import { withRandomFileEditor, closeAllEditors } from './testUtils';
|
||||
import { updateImageSize } from '../updateImageSize';
|
||||
import * as path from 'path';
|
||||
|
||||
suite('Tests for Emmet actions on html tags', () => {
|
||||
teardown(closeAllEditors);
|
||||
const filePath = path.join(__dirname, '../../../../resources/linux/code.png');
|
||||
|
||||
test('update image css with multiple cursors in css file', () => {
|
||||
const cssContents = `
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { getNodesInBetween, getNode, parseDocument, sameNodes, isStyleSheet } from './util';
|
||||
import { getNodesInBetween, getNode, parseDocument, sameNodes, isStyleSheet, validate } from './util';
|
||||
import { Node, Stylesheet, Rule, HtmlNode } from 'EmmetNode';
|
||||
import parseStylesheet from '@emmetio/css-parser';
|
||||
import { DocumentStreamReader } from './bufferStream';
|
||||
@@ -14,14 +14,12 @@ const endCommentStylesheet = '*/';
|
||||
const startCommentHTML = '<!--';
|
||||
const endCommentHTML = '-->';
|
||||
|
||||
export function toggleComment(): Thenable<boolean> {
|
||||
let editor = vscode.window.activeTextEditor;
|
||||
if (!editor) {
|
||||
vscode.window.showInformationMessage('No editor is active');
|
||||
export function toggleComment(): Thenable<boolean> | undefined {
|
||||
if (!validate() || !vscode.window.activeTextEditor) {
|
||||
return;
|
||||
}
|
||||
|
||||
let toggleCommentInternal;
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
let toggleCommentInternal: (document: vscode.TextDocument, selection: vscode.Selection, rootNode: Node) => vscode.TextEdit[];
|
||||
|
||||
if (isStyleSheet(editor.document.languageId)) {
|
||||
toggleCommentInternal = toggleCommentStylesheet;
|
||||
|
||||
-1
@@ -5,4 +5,3 @@
|
||||
|
||||
/// <reference path='../../../../src/vs/vscode.d.ts'/>
|
||||
/// <reference types='@types/node'/>
|
||||
/// <reference types='@types/mocha'/>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
import { TextEditor, Range, Position, window, TextEdit } from 'vscode';
|
||||
import * as path from 'path';
|
||||
import { getImageSize } from './imageSizeHelper';
|
||||
import { parseDocument, getNode, iterateCSSToken, getCssPropertyFromRule, isStyleSheet } from './util';
|
||||
import { parseDocument, getNode, iterateCSSToken, getCssPropertyFromRule, isStyleSheet, validate } from './util';
|
||||
import { HtmlNode, CssToken, HtmlToken, Attribute, Property } from 'EmmetNode';
|
||||
import { locateFile } from './locateFile';
|
||||
import parseStylesheet from '@emmetio/css-parser';
|
||||
@@ -20,11 +20,10 @@ import { DocumentStreamReader } from './bufferStream';
|
||||
* Updates size of context image in given editor
|
||||
*/
|
||||
export function updateImageSize() {
|
||||
let editor = window.activeTextEditor;
|
||||
if (!editor) {
|
||||
window.showInformationMessage('No editor is active.');
|
||||
if (!validate() || !window.activeTextEditor) {
|
||||
return;
|
||||
}
|
||||
const editor = window.activeTextEditor;
|
||||
|
||||
let allUpdatesPromise = editor.selections.reverse().map(selection => {
|
||||
let position = selection.isReversed ? selection.active : selection.anchor;
|
||||
@@ -49,7 +48,7 @@ export function updateImageSize() {
|
||||
/**
|
||||
* Updates image size of context tag of HTML model
|
||||
*/
|
||||
function updateImageSizeHTML(editor: TextEditor, position: Position): Promise<TextEdit[]> {
|
||||
function updateImageSizeHTML(editor: TextEditor, position: Position): Promise<TextEdit[] | undefined> {
|
||||
const src = getImageSrcHTML(getImageHTMLNode(editor, position));
|
||||
|
||||
if (!src) {
|
||||
@@ -70,7 +69,7 @@ function updateImageSizeHTML(editor: TextEditor, position: Position): Promise<Te
|
||||
}
|
||||
|
||||
function updateImageSizeStyleTag(editor: TextEditor, position: Position): Promise<TextEdit[]> {
|
||||
let getPropertyInsiderStyleTag = (editor) => {
|
||||
const getPropertyInsiderStyleTag = (editor: TextEditor): Property | undefined => {
|
||||
const rootNode = parseDocument(editor.document);
|
||||
const currentNode = <HtmlNode>getNode(rootNode, position);
|
||||
if (currentNode && currentNode.name === 'style'
|
||||
@@ -79,7 +78,7 @@ function updateImageSizeStyleTag(editor: TextEditor, position: Position): Promis
|
||||
let buffer = new DocumentStreamReader(editor.document, currentNode.open.end, new Range(currentNode.open.end, currentNode.close.start));
|
||||
let rootNode = parseStylesheet(buffer);
|
||||
const node = getNode(rootNode, position);
|
||||
return (node && node.type === 'property') ? <Property>node : null;
|
||||
return (node && node.type === 'property') ? <Property>node : undefined;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -93,7 +92,7 @@ function updateImageSizeCSSFile(editor: TextEditor, position: Position): Promise
|
||||
/**
|
||||
* Updates image size of context rule of stylesheet model
|
||||
*/
|
||||
function updateImageSizeCSS(editor: TextEditor, position: Position, fetchNode: (editor, position) => Property): Promise<TextEdit[]> {
|
||||
function updateImageSizeCSS(editor: TextEditor, position: Position, fetchNode: (editor: TextEditor, position: Position) => Property | undefined): Promise<TextEdit[]> {
|
||||
|
||||
const src = getImageSrcCSS(fetchNode(editor, position), position);
|
||||
|
||||
@@ -141,10 +140,8 @@ function getImageCSSNode(editor: TextEditor, position: Position): Property {
|
||||
|
||||
/**
|
||||
* Returns image source from given <img> node
|
||||
* @param {HtmlNode} node
|
||||
* @return {string}
|
||||
*/
|
||||
function getImageSrcHTML(node: HtmlNode): string {
|
||||
function getImageSrcHTML(node: HtmlNode): string | undefined {
|
||||
const srcAttr = getAttribute(node, 'src');
|
||||
if (!srcAttr) {
|
||||
return;
|
||||
@@ -155,11 +152,8 @@ function getImageSrcHTML(node: HtmlNode): string {
|
||||
|
||||
/**
|
||||
* Returns image source from given `url()` token
|
||||
* @param {Property} node
|
||||
* @param {Position}
|
||||
* @return {string}
|
||||
*/
|
||||
function getImageSrcCSS(node: Property, position: Position): string {
|
||||
function getImageSrcCSS(node: Property | undefined, position: Position): string | undefined {
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
@@ -213,10 +207,6 @@ function updateHTMLTag(editor: TextEditor, node: HtmlNode, width: number, height
|
||||
|
||||
/**
|
||||
* Updates size of given CSS rule
|
||||
* @param {TextEditor} editor
|
||||
* @param {Property} srcProp
|
||||
* @param {number} width
|
||||
* @param {number} height
|
||||
*/
|
||||
function updateCSSNode(editor: TextEditor, srcProp: Property, width: number, height: number): TextEdit[] {
|
||||
const rule = srcProp.parent;
|
||||
@@ -252,36 +242,28 @@ function updateCSSNode(editor: TextEditor, srcProp: Property, width: number, hei
|
||||
|
||||
/**
|
||||
* Returns attribute object with `attrName` name from given HTML node
|
||||
* @param {Node} node
|
||||
* @param {String} attrName
|
||||
* @return {Object}
|
||||
*/
|
||||
function getAttribute(node, attrName): Attribute {
|
||||
function getAttribute(node: HtmlNode, attrName: string): Attribute {
|
||||
attrName = attrName.toLowerCase();
|
||||
return node && node.open.attributes.find(attr => attr.name.value.toLowerCase() === attrName);
|
||||
return node && (node.open as any).attributes.find(attr => attr.name.value.toLowerCase() === attrName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns quote character, used for value of given attribute. May return empty
|
||||
* string if attribute wasn’t quoted
|
||||
* @param {TextEditor} editor
|
||||
* @param {Object} attr
|
||||
* @return {String}
|
||||
|
||||
*/
|
||||
function getAttributeQuote(editor, attr) {
|
||||
function getAttributeQuote(editor: TextEditor, attr: any): string {
|
||||
const range = new Range(attr.value ? attr.value.end : attr.end, attr.end);
|
||||
return range.isEmpty ? '' : editor.document.getText(range);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds 'url' token for given `pos` point in given CSS property `node`
|
||||
* @param {Node} node
|
||||
* @param {Position} pos
|
||||
* @return {Token}
|
||||
*/
|
||||
function findUrlToken(node, pos: Position) {
|
||||
for (let i = 0, il = node.parsedValue.length, url; i < il; i++) {
|
||||
iterateCSSToken(node.parsedValue[i], (token: CssToken) => {
|
||||
function findUrlToken(node: Property, pos: Position): CssToken | undefined {
|
||||
for (let i = 0, il = (node as any).parsedValue.length, url; i < il; i++) {
|
||||
iterateCSSToken((node as any).parsedValue[i], (token: CssToken) => {
|
||||
if (token.type === 'url' && token.start.isBeforeOrEqual(pos) && token.end.isAfterOrEqual(pos)) {
|
||||
url = token;
|
||||
return false;
|
||||
@@ -296,11 +278,8 @@ function findUrlToken(node, pos: Position) {
|
||||
|
||||
/**
|
||||
* Returns a string that is used to delimit properties in current node’s rule
|
||||
* @param {TextEditor} editor
|
||||
* @param {Property} node
|
||||
* @return {String}
|
||||
*/
|
||||
function getPropertyDelimitor(editor: TextEditor, node: Property) {
|
||||
function getPropertyDelimitor(editor: TextEditor, node: Property): string {
|
||||
let anchor;
|
||||
if (anchor = (node.previousSibling || node.parent.contentStartToken)) {
|
||||
return editor.document.getText(new Range(anchor.end, node.start));
|
||||
|
||||
@@ -7,17 +7,17 @@ import * as vscode from 'vscode';
|
||||
import { HtmlNode } from 'EmmetNode';
|
||||
import { getNode, parseDocument, validate } from './util';
|
||||
|
||||
export function updateTag(tagName: string): Thenable<boolean> {
|
||||
let editor = vscode.window.activeTextEditor;
|
||||
if (!validate(false)) {
|
||||
export function updateTag(tagName: string): Thenable<boolean> | undefined {
|
||||
if (!validate(false) || !vscode.window.activeTextEditor) {
|
||||
return;
|
||||
}
|
||||
let editor = vscode.window.activeTextEditor;
|
||||
let rootNode = <HtmlNode>parseDocument(editor.document);
|
||||
if (!rootNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
let rangesToUpdate = [];
|
||||
let rangesToUpdate: vscode.Range[] = [];
|
||||
editor.selections.reverse().forEach(selection => {
|
||||
rangesToUpdate = rangesToUpdate.concat(getRangesToUpdate(editor, selection, rootNode));
|
||||
});
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
import * as vscode from 'vscode';
|
||||
import parse from '@emmetio/html-matcher';
|
||||
import parseStylesheet from '@emmetio/css-parser';
|
||||
import { Node, HtmlNode, CssToken, Property } from 'EmmetNode';
|
||||
import { Node, HtmlNode, CssToken, Property, Rule } from 'EmmetNode';
|
||||
import { DocumentStreamReader } from './bufferStream';
|
||||
import * as path from 'path';
|
||||
|
||||
let _emmetHelper;
|
||||
let _currentExtensionsPath = undefined;
|
||||
let _emmetHelper: any;
|
||||
let _currentExtensionsPath: string | undefined = undefined;
|
||||
|
||||
export function getEmmetHelper() {
|
||||
if (!_emmetHelper) {
|
||||
@@ -27,15 +27,15 @@ export function resolveUpdateExtensionsPath() {
|
||||
}
|
||||
let extensionsPath = vscode.workspace.getConfiguration('emmet')['extensionsPath'];
|
||||
if (extensionsPath && !path.isAbsolute(extensionsPath)) {
|
||||
extensionsPath = path.join(vscode.workspace.rootPath, extensionsPath);
|
||||
extensionsPath = path.join(vscode.workspace.rootPath || '', extensionsPath);
|
||||
}
|
||||
if (_currentExtensionsPath !== extensionsPath) {
|
||||
_currentExtensionsPath = extensionsPath;
|
||||
_emmetHelper.updateExtensionsPath(_currentExtensionsPath).then(null, err => vscode.window.showErrorMessage(err));
|
||||
_emmetHelper.updateExtensionsPath(_currentExtensionsPath).then(null, (err: string) => vscode.window.showErrorMessage(err));
|
||||
}
|
||||
}
|
||||
|
||||
export const LANGUAGE_MODES: Object = {
|
||||
export const LANGUAGE_MODES: any = {
|
||||
'html': ['!', '.', '}', ':', '*', '$', ']', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
|
||||
'jade': ['!', '.', '}', ':', '*', '$', ']', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
|
||||
'slim': ['!', '.', '}', ':', '*', '$', ']', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
|
||||
@@ -62,7 +62,7 @@ export const MAPPED_MODES: Object = {
|
||||
'php': 'html'
|
||||
};
|
||||
|
||||
export function isStyleSheet(syntax): boolean {
|
||||
export function isStyleSheet(syntax: string): boolean {
|
||||
let stylesheetSyntaxes = ['css', 'scss', 'sass', 'less', 'stylus'];
|
||||
return (stylesheetSyntaxes.indexOf(syntax) > -1);
|
||||
}
|
||||
@@ -80,7 +80,7 @@ export function validate(allowStylesheet: boolean = true): boolean {
|
||||
}
|
||||
|
||||
export function getMappingForIncludedLanguages(): any {
|
||||
let finalMappedModes = {};
|
||||
const finalMappedModes = Object.create(null);
|
||||
let includeLanguagesConfig = vscode.workspace.getConfiguration('emmet')['includeLanguages'];
|
||||
let includeLanguages = Object.assign({}, MAPPED_MODES, includeLanguagesConfig ? includeLanguagesConfig : {});
|
||||
Object.keys(includeLanguages).forEach(syntax => {
|
||||
@@ -94,13 +94,13 @@ export function getMappingForIncludedLanguages(): any {
|
||||
/**
|
||||
* Get the corresponding emmet mode for given vscode language mode
|
||||
* Eg: jsx for typescriptreact/javascriptreact or pug for jade
|
||||
* If the language is not supported by emmet or has been exlcuded via `exlcudeLanguages` setting,
|
||||
* If the language is not supported by emmet or has been exlcuded via `exlcudeLanguages` setting,
|
||||
* then nothing is returned
|
||||
*
|
||||
* @param language
|
||||
*
|
||||
* @param language
|
||||
* @param exlcudedLanguages Array of language ids that user has chosen to exlcude for emmet
|
||||
*/
|
||||
export function getEmmetMode(language: string, excludedLanguages: string[]): string {
|
||||
export function getEmmetMode(language: string, excludedLanguages: string[]): string | undefined {
|
||||
if (!language || excludedLanguages.indexOf(language) > -1) {
|
||||
return;
|
||||
}
|
||||
@@ -120,34 +120,29 @@ export function getEmmetMode(language: string, excludedLanguages: string[]): str
|
||||
|
||||
/**
|
||||
* Parses the given document using emmet parsing modules
|
||||
* @param document
|
||||
*/
|
||||
export function parseDocument(document: vscode.TextDocument, showError: boolean = true): Node {
|
||||
export function parseDocument(document: vscode.TextDocument, showError: boolean = true): Node | undefined {
|
||||
let parseContent = isStyleSheet(document.languageId) ? parseStylesheet : parse;
|
||||
let rootNode: Node;
|
||||
try {
|
||||
rootNode = parseContent(new DocumentStreamReader(document));
|
||||
return parseContent(new DocumentStreamReader(document));
|
||||
} catch (e) {
|
||||
if (showError) {
|
||||
vscode.window.showErrorMessage('Emmet: Failed to parse the file');
|
||||
}
|
||||
}
|
||||
return rootNode;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns node corresponding to given position in the given root node
|
||||
* @param root
|
||||
* @param position
|
||||
* @param includeNodeBoundary
|
||||
*/
|
||||
export function getNode(root: Node, position: vscode.Position, includeNodeBoundary: boolean = false) {
|
||||
export function getNode(root: Node | undefined, position: vscode.Position, includeNodeBoundary: boolean = false) {
|
||||
if (!root) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let currentNode = root.firstChild;
|
||||
let foundNode: Node = null;
|
||||
let foundNode: Node | null = null;
|
||||
|
||||
while (currentNode) {
|
||||
const nodeStart: vscode.Position = currentNode.start;
|
||||
@@ -170,14 +165,14 @@ export function getNode(root: Node, position: vscode.Position, includeNodeBounda
|
||||
* Returns inner range of an html node.
|
||||
* @param currentNode
|
||||
*/
|
||||
export function getInnerRange(currentNode: HtmlNode): vscode.Range {
|
||||
export function getInnerRange(currentNode: HtmlNode): vscode.Range | undefined {
|
||||
if (!currentNode.close) {
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
return new vscode.Range(currentNode.open.end, currentNode.close.start);
|
||||
}
|
||||
|
||||
export function getDeepestNode(node: Node): Node {
|
||||
export function getDeepestNode(node: Node | undefined): Node | undefined {
|
||||
if (!node || !node.children || node.children.length === 0 || !node.children.find(x => x.type !== 'comment')) {
|
||||
return node;
|
||||
}
|
||||
@@ -186,6 +181,7 @@ export function getDeepestNode(node: Node): Node {
|
||||
return getDeepestNode(node.children[i]);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function findNextWord(propertyValue: string, pos: number): [number, number] {
|
||||
@@ -342,10 +338,8 @@ export function getEmmetConfiguration(syntax: string) {
|
||||
/**
|
||||
* Itereates by each child, as well as nested child’ children, in their order
|
||||
* and invokes `fn` for each. If `fn` function returns `false`, iteration stops
|
||||
* @param {Token} token
|
||||
* @param {Function} fn
|
||||
*/
|
||||
export function iterateCSSToken(token: CssToken, fn) {
|
||||
export function iterateCSSToken(token: CssToken, fn: (x: any) => any) {
|
||||
for (let i = 0, il = token.size; i < il; i++) {
|
||||
if (fn(token.item(i)) === false || iterateCSSToken(token.item(i), fn) === false) {
|
||||
return false;
|
||||
@@ -355,21 +349,16 @@ export function iterateCSSToken(token: CssToken, fn) {
|
||||
|
||||
/**
|
||||
* Returns `name` CSS property from given `rule`
|
||||
* @param {Node} rule
|
||||
* @param {String} name
|
||||
* @return {Property}
|
||||
*/
|
||||
export function getCssPropertyFromRule(rule, name): Property {
|
||||
return rule.children.find(node => node.type === 'property' && node.name === name);
|
||||
export function getCssPropertyFromRule(rule: Rule, name: string): Property | undefined {
|
||||
return rule.children.find(node => node.type === 'property' && node.name === name) as Property;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns css property under caret in given editor or `null` if such node cannot
|
||||
* be found
|
||||
* @param {TextEditor} editor
|
||||
* @return {Property}
|
||||
*/
|
||||
export function getCssPropertyFromDocument(editor: vscode.TextEditor, position: vscode.Position): Property {
|
||||
export function getCssPropertyFromDocument(editor: vscode.TextEditor, position: vscode.Position): Property | undefined {
|
||||
const rootNode = parseDocument(editor.document);
|
||||
const node = getNode(rootNode, position);
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
"es2016"
|
||||
],
|
||||
"module": "commonjs",
|
||||
"outDir": "./out"
|
||||
|
||||
"outDir": "./out",
|
||||
"noUnusedLocals": true
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
|
||||
@@ -54,6 +54,7 @@ export class ExtensionLinter {
|
||||
private timer: NodeJS.Timer;
|
||||
private markdownIt: MarkdownItType.MarkdownIt;
|
||||
|
||||
// @ts-ignore unused property
|
||||
constructor(private context: ExtensionContext) {
|
||||
this.disposables.push(
|
||||
workspace.onDidOpenTextDocument(document => this.queue(document)),
|
||||
@@ -227,7 +228,7 @@ export class ExtensionLinter {
|
||||
}
|
||||
|
||||
this.diagnosticsCollection.set(document.uri, diagnostics);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private locateToken(text: string, begin: number, end: number, token: MarkdownItType.Token, content: string) {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"es2015"
|
||||
],
|
||||
"module": "commonjs",
|
||||
"noUnusedLocals": true,
|
||||
"outDir": "./out"
|
||||
},
|
||||
"include": [
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
'use strict';
|
||||
|
||||
import 'mocha';
|
||||
|
||||
import { GitStatusParser } from '../git';
|
||||
import * as assert from 'assert';
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -4,4 +4,4 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/// <reference path='../../../../src/vs/vscode.d.ts'/>
|
||||
/// <reference path='../../../../src/vs/vscode.proposed.d.ts'/>
|
||||
/// <reference path='../../../../src/vs/vscode.proposed.d.ts'/>
|
||||
@@ -3,6 +3,7 @@
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
"outDir": "./out",
|
||||
"noUnusedLocals": true,
|
||||
"lib": [
|
||||
"es5", "es2015.promise"
|
||||
]
|
||||
|
||||
@@ -68,4 +68,4 @@ export function getCSSMode(documentRegions: LanguageModelCache<HTMLDocumentRegio
|
||||
cssStylesheets.dispose();
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -22,7 +22,7 @@ export interface HTMLDocumentRegions {
|
||||
|
||||
export var CSS_STYLE_RULE = '__';
|
||||
|
||||
interface EmbeddedRegion { languageId: string; start: number; end: number; attributeValue?: boolean; };
|
||||
interface EmbeddedRegion { languageId: string; start: number; end: number; attributeValue?: boolean; }
|
||||
|
||||
|
||||
export function getDocumentRegions(languageService: LanguageService, document: TextDocument): HTMLDocumentRegions {
|
||||
|
||||
@@ -73,7 +73,7 @@ export function format(languageModes: LanguageModes, document: TextDocument, for
|
||||
embeddedEdits.push(edit);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (embeddedEdits.length === 0) {
|
||||
pushAll(result, htmlEdits);
|
||||
|
||||
@@ -69,7 +69,7 @@ export function getHTMLMode(htmlLanguageService: HTMLLanguageService): LanguageM
|
||||
htmlDocuments.dispose();
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function merge(src: any, dst: any): any {
|
||||
for (var key in src) {
|
||||
|
||||
@@ -164,7 +164,7 @@ export function getJavascriptMode(documentRegions: LanguageModelCache<HTMLDocume
|
||||
ret.signatures.push(signature);
|
||||
});
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
return null;
|
||||
},
|
||||
findDocumentHighlight(document: TextDocument, position: Position): DocumentHighlight[] {
|
||||
@@ -177,7 +177,7 @@ export function getJavascriptMode(documentRegions: LanguageModelCache<HTMLDocume
|
||||
kind: <DocumentHighlightKind>(entry.isWriteAccess ? DocumentHighlightKind.Write : DocumentHighlightKind.Text)
|
||||
};
|
||||
});
|
||||
};
|
||||
}
|
||||
return null;
|
||||
},
|
||||
findDocumentSymbols(document: TextDocument): SymbolInformation[] {
|
||||
@@ -286,7 +286,7 @@ export function getJavascriptMode(documentRegions: LanguageModelCache<HTMLDocume
|
||||
jsDocuments.dispose();
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function convertRange(document: TextDocument, span: { start: number, length: number }): Range {
|
||||
let startPosition = document.positionAt(span.start);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import 'mocha';
|
||||
import * as assert from 'assert';
|
||||
import * as embeddedSupport from '../modes/embeddedSupport';
|
||||
import { TextDocument } from 'vscode-languageserver-types';
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import 'mocha';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import 'mocha';
|
||||
import * as assert from 'assert';
|
||||
import { getJavascriptMode } from '../modes/javascriptMode';
|
||||
import { TextDocument } from 'vscode-languageserver-types';
|
||||
|
||||
-1
@@ -1 +0,0 @@
|
||||
/// <reference types='@types/mocha'/>
|
||||
@@ -15,6 +15,7 @@ export function applyEdits(document: TextDocument, edits: TextEdit[]): string {
|
||||
}
|
||||
return startDiff;
|
||||
});
|
||||
// @ts-ignore unused local
|
||||
let lastOffset = text.length;
|
||||
sortedEdits.forEach(e => {
|
||||
let startOffset = document.offsetAt(e.range.start);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
"outDir": "./out",
|
||||
"noUnusedLocals": true,
|
||||
"lib": [
|
||||
"es5", "es2015.promise"
|
||||
]
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
},
|
||||
{
|
||||
"language": "javascriptreact",
|
||||
"path": "./snippets/javascriptreact.json"
|
||||
"path": "./snippets/javascript.json"
|
||||
}
|
||||
],
|
||||
"jsonValidation": [
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
{
|
||||
"define module": {
|
||||
"prefix": "define",
|
||||
"body": [
|
||||
"define([",
|
||||
"\t'require',",
|
||||
"\t'${1:dependency}'",
|
||||
"], function(require, ${2:factory}) {",
|
||||
"\t'use strict';",
|
||||
"\t$0",
|
||||
"});"
|
||||
],
|
||||
"description": "define module"
|
||||
},
|
||||
"For Loop": {
|
||||
"prefix": "for",
|
||||
"body": [
|
||||
"for (let ${1:index} = 0; ${1:index} < ${2:array}.length; ${1:index}++) {",
|
||||
"\tconst ${3:element} = ${2:array}[${1:index}];",
|
||||
"\t$0",
|
||||
"}"
|
||||
],
|
||||
"description": "For Loop"
|
||||
},
|
||||
"For-Each Loop": {
|
||||
"prefix": "foreach",
|
||||
"body": [
|
||||
"${1:array}.forEach(${2:element} => {",
|
||||
"\t$0",
|
||||
"});"
|
||||
],
|
||||
"description": "For-Each Loop"
|
||||
},
|
||||
"For-In Loop": {
|
||||
"prefix": "forin",
|
||||
"body": [
|
||||
"for (const ${1:key} in ${2:object}) {",
|
||||
"\tif (${2:object}.hasOwnProperty(${1:key})) {",
|
||||
"\t\tconst ${3:element} = ${2:object}[${1:key}];",
|
||||
"\t\t$0",
|
||||
"\t}",
|
||||
"}"
|
||||
],
|
||||
"description": "For-In Loop"
|
||||
},
|
||||
"For-Of Loop": {
|
||||
"prefix": "forof",
|
||||
"body": [
|
||||
"for (const ${1:iterator} of ${2:object}) {",
|
||||
"\t$0",
|
||||
"}"
|
||||
],
|
||||
"description": "For-Of Loop"
|
||||
},
|
||||
"Function Statement": {
|
||||
"prefix": "function",
|
||||
"body": [
|
||||
"function ${1:name}(${2:params}) {",
|
||||
"\t$0",
|
||||
"}"
|
||||
],
|
||||
"description": "Function Statement"
|
||||
},
|
||||
"If Statement": {
|
||||
"prefix": "if",
|
||||
"body": [
|
||||
"if (${1:condition}) {",
|
||||
"\t$0",
|
||||
"}"
|
||||
],
|
||||
"description": "If Statement"
|
||||
},
|
||||
"If-Else Statement": {
|
||||
"prefix": "ifelse",
|
||||
"body": [
|
||||
"if (${1:condition}) {",
|
||||
"\t$0",
|
||||
"} else {",
|
||||
"\t",
|
||||
"}"
|
||||
],
|
||||
"description": "If-Else Statement"
|
||||
},
|
||||
"New Statement": {
|
||||
"prefix": "new",
|
||||
"body": [
|
||||
"const ${1:name} = new ${2:type}(${3:arguments});$0"
|
||||
],
|
||||
"description": "New Statement"
|
||||
},
|
||||
"Switch Statement": {
|
||||
"prefix": "switch",
|
||||
"body": [
|
||||
"switch (${1:key}) {",
|
||||
"\tcase ${2:value}:",
|
||||
"\t\t$0",
|
||||
"\t\tbreak;",
|
||||
"",
|
||||
"\tdefault:",
|
||||
"\t\tbreak;",
|
||||
"}"
|
||||
],
|
||||
"description": "Switch Statement"
|
||||
},
|
||||
"While Statement": {
|
||||
"prefix": "while",
|
||||
"body": [
|
||||
"while (${1:condition}) {",
|
||||
"\t$0",
|
||||
"}"
|
||||
],
|
||||
"description": "While Statement"
|
||||
},
|
||||
"Do-While Statement": {
|
||||
"prefix": "dowhile",
|
||||
"body": [
|
||||
"do {",
|
||||
"\t$0",
|
||||
"} while (${1:condition});"
|
||||
],
|
||||
"description": "Do-While Statement"
|
||||
},
|
||||
"Try-Catch Statement": {
|
||||
"prefix": "trycatch",
|
||||
"body": [
|
||||
"try {",
|
||||
"\t$0",
|
||||
"} catch (${1:error}) {",
|
||||
"\t",
|
||||
"}"
|
||||
],
|
||||
"description": "Try-Catch Statement"
|
||||
},
|
||||
"Set Timeout Function": {
|
||||
"prefix": "settimeout",
|
||||
"body": [
|
||||
"setTimeout(() => {",
|
||||
"\t$0",
|
||||
"}, ${1:timeout});"
|
||||
],
|
||||
"description": "Set Timeout Function"
|
||||
},
|
||||
"Import external module.": {
|
||||
"prefix": "import statement",
|
||||
"body": [
|
||||
"import { $0 } from \"${1:module}\";"
|
||||
],
|
||||
"description": "Import external module."
|
||||
},
|
||||
"Region Start": {
|
||||
"prefix": "#region",
|
||||
"body": [
|
||||
"//#region $0"
|
||||
],
|
||||
"description": "Folding Region Start"
|
||||
},
|
||||
"Region End": {
|
||||
"prefix": "#endregion",
|
||||
"body": [
|
||||
"//#endregion"
|
||||
],
|
||||
"description": "Folding Region End"
|
||||
}
|
||||
}
|
||||
@@ -30,8 +30,8 @@ export class BowerJSONContribution implements IJSONContribution {
|
||||
return [{ language: 'json', pattern: '**/bower.json' }, { language: 'json', pattern: '**/.bower.json' }];
|
||||
}
|
||||
|
||||
public collectDefaultSuggestions(resource: string, collector: ISuggestionsCollector): Thenable<any> {
|
||||
let defaultValue = {
|
||||
public collectDefaultSuggestions(_resource: string, collector: ISuggestionsCollector): Thenable<any> {
|
||||
const defaultValue = {
|
||||
'name': '${1:name}',
|
||||
'description': '${2:description}',
|
||||
'authors': ['${3:author}'],
|
||||
@@ -39,37 +39,37 @@ export class BowerJSONContribution implements IJSONContribution {
|
||||
'main': '${5:pathToMain}',
|
||||
'dependencies': {}
|
||||
};
|
||||
let proposal = new CompletionItem(localize('json.bower.default', 'Default bower.json'));
|
||||
const proposal = new CompletionItem(localize('json.bower.default', 'Default bower.json'));
|
||||
proposal.kind = CompletionItemKind.Class;
|
||||
proposal.insertText = new SnippetString(JSON.stringify(defaultValue, null, '\t'));
|
||||
collector.add(proposal);
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
public collectPropertySuggestions(resource: string, location: Location, currentWord: string, addValue: boolean, isLast: boolean, collector: ISuggestionsCollector): Thenable<any> | null {
|
||||
public collectPropertySuggestions(_resource: string, location: Location, currentWord: string, addValue: boolean, isLast: boolean, collector: ISuggestionsCollector): Thenable<any> | null {
|
||||
if ((location.matches(['dependencies']) || location.matches(['devDependencies']))) {
|
||||
if (currentWord.length > 0) {
|
||||
let queryUrl = 'https://bower.herokuapp.com/packages/search/' + encodeURIComponent(currentWord);
|
||||
const queryUrl = 'https://bower.herokuapp.com/packages/search/' + encodeURIComponent(currentWord);
|
||||
|
||||
return this.xhr({
|
||||
url: queryUrl
|
||||
}).then((success) => {
|
||||
if (success.status === 200) {
|
||||
try {
|
||||
let obj = JSON.parse(success.responseText);
|
||||
const obj = JSON.parse(success.responseText);
|
||||
if (Array.isArray(obj)) {
|
||||
let results = <{ name: string; description: string; }[]>obj;
|
||||
const results = <{ name: string; description: string; }[]>obj;
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
let name = results[i].name;
|
||||
let description = results[i].description || '';
|
||||
let insertText = new SnippetString().appendText(JSON.stringify(name));
|
||||
const name = results[i].name;
|
||||
const description = results[i].description || '';
|
||||
const insertText = new SnippetString().appendText(JSON.stringify(name));
|
||||
if (addValue) {
|
||||
insertText.appendText(': ').appendPlaceholder('latest');
|
||||
if (!isLast) {
|
||||
insertText.appendText(',');
|
||||
}
|
||||
}
|
||||
let proposal = new CompletionItem(name);
|
||||
const proposal = new CompletionItem(name);
|
||||
proposal.kind = CompletionItemKind.Property;
|
||||
proposal.insertText = insertText;
|
||||
proposal.filterText = JSON.stringify(name);
|
||||
@@ -85,13 +85,14 @@ export class BowerJSONContribution implements IJSONContribution {
|
||||
collector.error(localize('json.bower.error.repoaccess', 'Request to the bower repository failed: {0}', success.responseText));
|
||||
return 0;
|
||||
}
|
||||
return undefined;
|
||||
}, (error) => {
|
||||
collector.error(localize('json.bower.error.repoaccess', 'Request to the bower repository failed: {0}', error.responseText));
|
||||
return 0;
|
||||
});
|
||||
} else {
|
||||
this.topRanked.forEach((name) => {
|
||||
let insertText = new SnippetString().appendText(JSON.stringify(name));
|
||||
const insertText = new SnippetString().appendText(JSON.stringify(name));
|
||||
if (addValue) {
|
||||
insertText.appendText(': ').appendPlaceholder('latest');
|
||||
if (!isLast) {
|
||||
@@ -99,7 +100,7 @@ export class BowerJSONContribution implements IJSONContribution {
|
||||
}
|
||||
}
|
||||
|
||||
let proposal = new CompletionItem(name);
|
||||
const proposal = new CompletionItem(name);
|
||||
proposal.kind = CompletionItemKind.Property;
|
||||
proposal.insertText = insertText;
|
||||
proposal.filterText = JSON.stringify(name);
|
||||
@@ -113,10 +114,10 @@ export class BowerJSONContribution implements IJSONContribution {
|
||||
return null;
|
||||
}
|
||||
|
||||
public collectValueSuggestions(resource: string, location: Location, collector: ISuggestionsCollector): Thenable<any> {
|
||||
public collectValueSuggestions(_resource: string, location: Location, collector: ISuggestionsCollector): Thenable<any> {
|
||||
if ((location.matches(['dependencies', '*']) || location.matches(['devDependencies', '*']))) {
|
||||
// not implemented. Could be do done calling the bower command. Waiting for web API: https://github.com/bower/registry/issues/26
|
||||
let proposal = new CompletionItem(localize('json.bower.latest.version', 'latest'));
|
||||
const proposal = new CompletionItem(localize('json.bower.latest.version', 'latest'));
|
||||
proposal.insertText = new SnippetString('"${1:latest}"');
|
||||
proposal.filterText = '""';
|
||||
proposal.kind = CompletionItemKind.Value;
|
||||
@@ -135,18 +136,18 @@ export class BowerJSONContribution implements IJSONContribution {
|
||||
}
|
||||
return null;
|
||||
});
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private getInfo(pack: string): Thenable<string | undefined> {
|
||||
let queryUrl = 'https://bower.herokuapp.com/packages/' + encodeURIComponent(pack);
|
||||
const queryUrl = 'https://bower.herokuapp.com/packages/' + encodeURIComponent(pack);
|
||||
|
||||
return this.xhr({
|
||||
url: queryUrl
|
||||
}).then((success) => {
|
||||
try {
|
||||
let obj = JSON.parse(success.responseText);
|
||||
const obj = JSON.parse(success.responseText);
|
||||
if (obj && obj.url) {
|
||||
let url: string = obj.url;
|
||||
if (url.indexOf('git://') === 0) {
|
||||
@@ -161,14 +162,14 @@ export class BowerJSONContribution implements IJSONContribution {
|
||||
// ignore
|
||||
}
|
||||
return void 0;
|
||||
}, (error) => {
|
||||
}, () => {
|
||||
return void 0;
|
||||
});
|
||||
}
|
||||
|
||||
public getInfoContribution(resource: string, location: Location): Thenable<MarkedString[] | null> | null {
|
||||
public getInfoContribution(_resource: string, location: Location): Thenable<MarkedString[] | null> | null {
|
||||
if ((location.matches(['dependencies', '*']) || location.matches(['devDependencies', '*']))) {
|
||||
let pack = location.path[location.path.length - 1];
|
||||
const pack = location.path[location.path.length - 1];
|
||||
if (typeof pack === 'string') {
|
||||
return this.getInfo(pack).then(documentation => {
|
||||
if (documentation) {
|
||||
|
||||
@@ -32,10 +32,10 @@ export interface IJSONContribution {
|
||||
}
|
||||
|
||||
export function addJSONProviders(xhr: XHRRequest): Disposable {
|
||||
let contributions = [new PackageJSONContribution(xhr), new BowerJSONContribution(xhr)];
|
||||
let subscriptions: Disposable[] = [];
|
||||
const contributions = [new PackageJSONContribution(xhr), new BowerJSONContribution(xhr)];
|
||||
const subscriptions: Disposable[] = [];
|
||||
contributions.forEach(contribution => {
|
||||
let selector = contribution.getDocumentSelector();
|
||||
const selector = contribution.getDocumentSelector();
|
||||
subscriptions.push(languages.registerCompletionItemProvider(selector, new JSONCompletionItemProvider(contribution), '"', ':'));
|
||||
subscriptions.push(languages.registerHoverProvider(selector, new JSONHoverProvider(contribution)));
|
||||
});
|
||||
@@ -47,20 +47,20 @@ export class JSONHoverProvider implements HoverProvider {
|
||||
constructor(private jsonContribution: IJSONContribution) {
|
||||
}
|
||||
|
||||
public provideHover(document: TextDocument, position: Position, token: CancellationToken): Thenable<Hover> | null {
|
||||
let fileName = basename(document.fileName);
|
||||
let offset = document.offsetAt(position);
|
||||
let location = getLocation(document.getText(), offset);
|
||||
public provideHover(document: TextDocument, position: Position, _token: CancellationToken): Thenable<Hover> | null {
|
||||
const fileName = basename(document.fileName);
|
||||
const offset = document.offsetAt(position);
|
||||
const location = getLocation(document.getText(), offset);
|
||||
if (!location.previousNode) {
|
||||
return null;
|
||||
}
|
||||
const node = location.previousNode;
|
||||
if (node && node.offset <= offset && offset <= node.offset + node.length) {
|
||||
let promise = this.jsonContribution.getInfoContribution(fileName, location);
|
||||
const promise = this.jsonContribution.getInfoContribution(fileName, location);
|
||||
if (promise) {
|
||||
return promise.then(htmlContent => {
|
||||
let range = new Range(document.positionAt(node.offset), document.positionAt(node.offset + node.length));
|
||||
let result: Hover = {
|
||||
const range = new Range(document.positionAt(node.offset), document.positionAt(node.offset + node.length));
|
||||
const result: Hover = {
|
||||
contents: htmlContent || [],
|
||||
range: range
|
||||
};
|
||||
@@ -77,9 +77,9 @@ export class JSONCompletionItemProvider implements CompletionItemProvider {
|
||||
constructor(private jsonContribution: IJSONContribution) {
|
||||
}
|
||||
|
||||
public resolveCompletionItem(item: CompletionItem, token: CancellationToken): Thenable<CompletionItem | null> {
|
||||
public resolveCompletionItem(item: CompletionItem, _token: CancellationToken): Thenable<CompletionItem | null> {
|
||||
if (this.jsonContribution.resolveSuggestion) {
|
||||
let resolver = this.jsonContribution.resolveSuggestion(item);
|
||||
const resolver = this.jsonContribution.resolveSuggestion(item);
|
||||
if (resolver) {
|
||||
return resolver;
|
||||
}
|
||||
@@ -87,28 +87,28 @@ export class JSONCompletionItemProvider implements CompletionItemProvider {
|
||||
return Promise.resolve(item);
|
||||
}
|
||||
|
||||
public provideCompletionItems(document: TextDocument, position: Position, token: CancellationToken): Thenable<CompletionList | null> | null {
|
||||
public provideCompletionItems(document: TextDocument, position: Position, _token: CancellationToken): Thenable<CompletionList | null> | null {
|
||||
|
||||
let fileName = basename(document.fileName);
|
||||
const fileName = basename(document.fileName);
|
||||
|
||||
let currentWord = this.getCurrentWord(document, position);
|
||||
const currentWord = this.getCurrentWord(document, position);
|
||||
let overwriteRange: Range;
|
||||
|
||||
let items: CompletionItem[] = [];
|
||||
const items: CompletionItem[] = [];
|
||||
let isIncomplete = false;
|
||||
|
||||
let offset = document.offsetAt(position);
|
||||
let location = getLocation(document.getText(), offset);
|
||||
const offset = document.offsetAt(position);
|
||||
const location = getLocation(document.getText(), offset);
|
||||
|
||||
let node = location.previousNode;
|
||||
const node = location.previousNode;
|
||||
if (node && node.offset <= offset && offset <= node.offset + node.length && (node.type === 'property' || node.type === 'string' || node.type === 'number' || node.type === 'boolean' || node.type === 'null')) {
|
||||
overwriteRange = new Range(document.positionAt(node.offset), document.positionAt(node.offset + node.length));
|
||||
} else {
|
||||
overwriteRange = new Range(document.positionAt(offset - currentWord.length), position);
|
||||
}
|
||||
|
||||
let proposed: { [key: string]: boolean } = {};
|
||||
let collector: ISuggestionsCollector = {
|
||||
const proposed: { [key: string]: boolean } = {};
|
||||
const collector: ISuggestionsCollector = {
|
||||
add: (suggestion: CompletionItem) => {
|
||||
if (!proposed[suggestion.label]) {
|
||||
proposed[suggestion.label] = true;
|
||||
@@ -124,8 +124,8 @@ export class JSONCompletionItemProvider implements CompletionItemProvider {
|
||||
let collectPromise: Thenable<any> | null = null;
|
||||
|
||||
if (location.isAtPropertyKey) {
|
||||
let addValue = !location.previousNode || !location.previousNode.columnOffset;
|
||||
let isLast = this.isLast(document, position);
|
||||
const addValue = !location.previousNode || !location.previousNode.columnOffset;
|
||||
const isLast = this.isLast(document, position);
|
||||
collectPromise = this.jsonContribution.collectPropertySuggestions(fileName, location, currentWord, addValue, isLast, collector);
|
||||
} else {
|
||||
if (location.path.length === 0) {
|
||||
@@ -146,8 +146,8 @@ export class JSONCompletionItemProvider implements CompletionItemProvider {
|
||||
}
|
||||
|
||||
private getCurrentWord(document: TextDocument, position: Position) {
|
||||
var i = position.character - 1;
|
||||
var text = document.lineAt(position.line).text;
|
||||
let i = position.character - 1;
|
||||
const text = document.lineAt(position.line).text;
|
||||
while (i >= 0 && ' \t\n\r\v":{[,'.indexOf(text.charAt(i)) === -1) {
|
||||
i--;
|
||||
}
|
||||
@@ -155,7 +155,7 @@ export class JSONCompletionItemProvider implements CompletionItemProvider {
|
||||
}
|
||||
|
||||
private isLast(document: TextDocument, position: Position): boolean {
|
||||
let scanner = createScanner(document.getText(), true);
|
||||
const scanner = createScanner(document.getText(), true);
|
||||
scanner.setPosition(document.offsetAt(position));
|
||||
let nextToken = scanner.scan();
|
||||
if (nextToken === SyntaxKind.StringLiteral && scanner.getTokenError() === ScanError.UnexpectedEndOfString) {
|
||||
|
||||
@@ -13,7 +13,7 @@ import { textToMarkedString } from './markedTextUtil';
|
||||
import * as nls from 'vscode-nls';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
let LIMIT = 40;
|
||||
const LIMIT = 40;
|
||||
|
||||
export class PackageJSONContribution implements IJSONContribution {
|
||||
|
||||
@@ -31,8 +31,8 @@ export class PackageJSONContribution implements IJSONContribution {
|
||||
public constructor(private xhr: XHRRequest) {
|
||||
}
|
||||
|
||||
public collectDefaultSuggestions(fileName: string, result: ISuggestionsCollector): Thenable<any> {
|
||||
let defaultValue = {
|
||||
public collectDefaultSuggestions(_fileName: string, result: ISuggestionsCollector): Thenable<any> {
|
||||
const defaultValue = {
|
||||
'name': '${1:name}',
|
||||
'description': '${2:description}',
|
||||
'authors': '${3:author}',
|
||||
@@ -40,7 +40,7 @@ export class PackageJSONContribution implements IJSONContribution {
|
||||
'main': '${5:pathToMain}',
|
||||
'dependencies': {}
|
||||
};
|
||||
let proposal = new CompletionItem(localize('json.package.default', 'Default package.json'));
|
||||
const proposal = new CompletionItem(localize('json.package.default', 'Default package.json'));
|
||||
proposal.kind = CompletionItemKind.Module;
|
||||
proposal.insertText = new SnippetString(JSON.stringify(defaultValue, null, '\t'));
|
||||
result.add(proposal);
|
||||
@@ -48,7 +48,7 @@ export class PackageJSONContribution implements IJSONContribution {
|
||||
}
|
||||
|
||||
public collectPropertySuggestions(
|
||||
resource: string,
|
||||
_resource: string,
|
||||
location: Location,
|
||||
currentWord: string,
|
||||
addValue: boolean,
|
||||
@@ -65,21 +65,21 @@ export class PackageJSONContribution implements IJSONContribution {
|
||||
}).then((success) => {
|
||||
if (success.status === 200) {
|
||||
try {
|
||||
let obj = JSON.parse(success.responseText);
|
||||
const obj = JSON.parse(success.responseText);
|
||||
if (obj && Array.isArray(obj.rows)) {
|
||||
let results = <{ key: string[]; }[]>obj.rows;
|
||||
const results = <{ key: string[]; }[]>obj.rows;
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
let keys = results[i].key;
|
||||
const keys = results[i].key;
|
||||
if (Array.isArray(keys) && keys.length > 0) {
|
||||
let name = keys[0];
|
||||
let insertText = new SnippetString().appendText(JSON.stringify(name));
|
||||
const name = keys[0];
|
||||
const insertText = new SnippetString().appendText(JSON.stringify(name));
|
||||
if (addValue) {
|
||||
insertText.appendText(': "').appendTabstop().appendText('"');
|
||||
if (!isLast) {
|
||||
insertText.appendText(',');
|
||||
}
|
||||
}
|
||||
let proposal = new CompletionItem(name);
|
||||
const proposal = new CompletionItem(name);
|
||||
proposal.kind = CompletionItemKind.Property;
|
||||
proposal.insertText = insertText;
|
||||
proposal.filterText = JSON.stringify(name);
|
||||
@@ -98,20 +98,21 @@ export class PackageJSONContribution implements IJSONContribution {
|
||||
collector.error(localize('json.npm.error.repoaccess', 'Request to the NPM repository failed: {0}', success.responseText));
|
||||
return 0;
|
||||
}
|
||||
return undefined;
|
||||
}, (error) => {
|
||||
collector.error(localize('json.npm.error.repoaccess', 'Request to the NPM repository failed: {0}', error.responseText));
|
||||
return 0;
|
||||
});
|
||||
} else {
|
||||
this.mostDependedOn.forEach((name) => {
|
||||
let insertText = new SnippetString().appendText(JSON.stringify(name));
|
||||
const insertText = new SnippetString().appendText(JSON.stringify(name));
|
||||
if (addValue) {
|
||||
insertText.appendText(': "').appendTabstop().appendText('"');
|
||||
if (!isLast) {
|
||||
insertText.appendText(',');
|
||||
}
|
||||
}
|
||||
let proposal = new CompletionItem(name);
|
||||
const proposal = new CompletionItem(name);
|
||||
proposal.kind = CompletionItemKind.Property;
|
||||
proposal.insertText = insertText;
|
||||
proposal.filterText = JSON.stringify(name);
|
||||
@@ -126,20 +127,20 @@ export class PackageJSONContribution implements IJSONContribution {
|
||||
}
|
||||
|
||||
public collectValueSuggestions(
|
||||
fileName: string,
|
||||
_fileName: string,
|
||||
location: Location,
|
||||
result: ISuggestionsCollector
|
||||
): Thenable<any> | null {
|
||||
if ((location.matches(['dependencies', '*']) || location.matches(['devDependencies', '*']) || location.matches(['optionalDependencies', '*']) || location.matches(['peerDependencies', '*']))) {
|
||||
let currentKey = location.path[location.path.length - 1];
|
||||
const currentKey = location.path[location.path.length - 1];
|
||||
if (typeof currentKey === 'string') {
|
||||
let queryUrl = 'http://registry.npmjs.org/' + encodeURIComponent(currentKey).replace('%40', '@');
|
||||
const queryUrl = 'http://registry.npmjs.org/' + encodeURIComponent(currentKey).replace('%40', '@');
|
||||
return this.xhr({
|
||||
url: queryUrl
|
||||
}).then((success) => {
|
||||
try {
|
||||
let obj = JSON.parse(success.responseText);
|
||||
let latest = obj && obj['dist-tags'] && obj['dist-tags']['latest'];
|
||||
const obj = JSON.parse(success.responseText);
|
||||
const latest = obj && obj['dist-tags'] && obj['dist-tags']['latest'];
|
||||
if (latest) {
|
||||
let name = JSON.stringify(latest);
|
||||
let proposal = new CompletionItem(name);
|
||||
@@ -166,7 +167,7 @@ export class PackageJSONContribution implements IJSONContribution {
|
||||
// ignore
|
||||
}
|
||||
return 0;
|
||||
}, (error) => {
|
||||
}, () => {
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
@@ -186,24 +187,24 @@ export class PackageJSONContribution implements IJSONContribution {
|
||||
}
|
||||
return null;
|
||||
});
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private getInfo(pack: string): Thenable<string[]> {
|
||||
|
||||
let queryUrl = 'http://registry.npmjs.org/' + encodeURIComponent(pack).replace('%40', '@');
|
||||
const queryUrl = 'http://registry.npmjs.org/' + encodeURIComponent(pack).replace('%40', '@');
|
||||
return this.xhr({
|
||||
url: queryUrl
|
||||
}).then((success) => {
|
||||
try {
|
||||
let obj = JSON.parse(success.responseText);
|
||||
const obj = JSON.parse(success.responseText);
|
||||
if (obj) {
|
||||
let result: string[] = [];
|
||||
const result: string[] = [];
|
||||
if (obj.description) {
|
||||
result.push(obj.description);
|
||||
}
|
||||
let latest = obj && obj['dist-tags'] && obj['dist-tags']['latest'];
|
||||
const latest = obj && obj['dist-tags'] && obj['dist-tags']['latest'];
|
||||
if (latest) {
|
||||
result.push(localize('json.npm.version.hover', 'Latest version: {0}', latest));
|
||||
}
|
||||
@@ -213,14 +214,14 @@ export class PackageJSONContribution implements IJSONContribution {
|
||||
// ignore
|
||||
}
|
||||
return [];
|
||||
}, (error) => {
|
||||
}, () => {
|
||||
return [];
|
||||
});
|
||||
}
|
||||
|
||||
public getInfoContribution(fileName: string, location: Location): Thenable<MarkedString[] | null> | null {
|
||||
public getInfoContribution(_fileName: string, location: Location): Thenable<MarkedString[] | null> | null {
|
||||
if ((location.matches(['dependencies', '*']) || location.matches(['devDependencies', '*']) || location.matches(['optionalDependencies', '*']) || location.matches(['peerDependencies', '*']))) {
|
||||
let pack = location.path[location.path.length - 1];
|
||||
const pack = location.path[location.path.length - 1];
|
||||
if (typeof pack === 'string') {
|
||||
return this.getInfo(pack).then(infos => {
|
||||
if (infos.length) {
|
||||
|
||||
@@ -16,12 +16,12 @@ export function activate(context: ExtensionContext): any {
|
||||
nls.config({ locale: env.language });
|
||||
|
||||
configureHttpRequest();
|
||||
workspace.onDidChangeConfiguration(e => configureHttpRequest());
|
||||
workspace.onDidChangeConfiguration(() => configureHttpRequest());
|
||||
|
||||
context.subscriptions.push(addJSONProviders(httpRequest.xhr));
|
||||
}
|
||||
|
||||
function configureHttpRequest() {
|
||||
let httpSettings = workspace.getConfiguration('http');
|
||||
const httpSettings = workspace.getConfiguration('http');
|
||||
httpRequest.configure(httpSettings.get<string>('proxy', ''), httpSettings.get<boolean>('proxyStrictSSL', true));
|
||||
}
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
"lib": [
|
||||
"es2015"
|
||||
],
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"strict": true
|
||||
},
|
||||
"include": [
|
||||
|
||||
@@ -50,6 +50,7 @@ interface Settings {
|
||||
};
|
||||
}
|
||||
|
||||
// @ts-ignore unused type
|
||||
interface JSONSettings {
|
||||
schemas: JSONSchemaSettings[];
|
||||
}
|
||||
@@ -260,8 +261,8 @@ function getSettings(): Settings {
|
||||
folderPath = folderPath + '/';
|
||||
}
|
||||
collectSchemaSettings(folderSchemas, folderUri.fsPath, folderPath + '*');
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
"outDir": "./out",
|
||||
"noUnusedLocals": true,
|
||||
"lib": [
|
||||
"es5", "es2015.promise"
|
||||
]
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"sourceMap": true,
|
||||
"sourceRoot": "../src",
|
||||
"outDir": "./out",
|
||||
"noUnusedLocals": true,
|
||||
"lib": [
|
||||
"es5", "es2015.promise"
|
||||
]
|
||||
|
||||
@@ -13,7 +13,7 @@ export default class MergeConflictCodeLensProvider implements vscode.CodeLensPro
|
||||
private config: interfaces.IExtensionConfiguration;
|
||||
private tracker: interfaces.IDocumentMergeConflictTracker;
|
||||
|
||||
constructor(private context: vscode.ExtensionContext, trackerService: interfaces.IDocumentMergeConflictTrackerService) {
|
||||
constructor(trackerService: interfaces.IDocumentMergeConflictTrackerService) {
|
||||
this.tracker = trackerService.createTracker('codelens');
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ export default class MergeConflictCodeLensProvider implements vscode.CodeLensPro
|
||||
}
|
||||
}
|
||||
|
||||
async provideCodeLenses(document: vscode.TextDocument, token: vscode.CancellationToken): Promise<vscode.CodeLens[] | null> {
|
||||
async provideCodeLenses(document: vscode.TextDocument, _token: vscode.CancellationToken): Promise<vscode.CodeLens[] | null> {
|
||||
|
||||
if (!this.config || !this.config.enableCodeLens) {
|
||||
return null;
|
||||
|
||||
@@ -24,7 +24,7 @@ export default class CommandHandler implements vscode.Disposable {
|
||||
private disposables: vscode.Disposable[] = [];
|
||||
private tracker: interfaces.IDocumentMergeConflictTracker;
|
||||
|
||||
constructor(private context: vscode.ExtensionContext, trackerService: interfaces.IDocumentMergeConflictTrackerService) {
|
||||
constructor(trackerService: interfaces.IDocumentMergeConflictTrackerService) {
|
||||
this.tracker = trackerService.createTracker('commands');
|
||||
}
|
||||
|
||||
@@ -62,19 +62,19 @@ export default class CommandHandler implements vscode.Disposable {
|
||||
return this.accept(interfaces.CommitType.Both, editor, ...args);
|
||||
}
|
||||
|
||||
acceptAllCurrent(editor: vscode.TextEditor, ...args: any[]): Promise<void> {
|
||||
acceptAllCurrent(editor: vscode.TextEditor): Promise<void> {
|
||||
return this.acceptAll(interfaces.CommitType.Current, editor);
|
||||
}
|
||||
|
||||
acceptAllIncoming(editor: vscode.TextEditor, ...args: any[]): Promise<void> {
|
||||
acceptAllIncoming(editor: vscode.TextEditor): Promise<void> {
|
||||
return this.acceptAll(interfaces.CommitType.Incoming, editor);
|
||||
}
|
||||
|
||||
acceptAllBoth(editor: vscode.TextEditor, ...args: any[]): Promise<void> {
|
||||
acceptAllBoth(editor: vscode.TextEditor): Promise<void> {
|
||||
return this.acceptAll(interfaces.CommitType.Both, editor);
|
||||
}
|
||||
|
||||
async compare(editor: vscode.TextEditor, conflict: interfaces.IDocumentMergeConflict | null, ...args: any[]) {
|
||||
async compare(editor: vscode.TextEditor, conflict: interfaces.IDocumentMergeConflict | null) {
|
||||
const fileName = path.basename(editor.document.uri.fsPath);
|
||||
|
||||
// No conflict, command executed from command palette
|
||||
@@ -102,15 +102,15 @@ export default class CommandHandler implements vscode.Disposable {
|
||||
vscode.commands.executeCommand('vscode.diff', leftUri, rightUri, title);
|
||||
}
|
||||
|
||||
navigateNext(editor: vscode.TextEditor, ...args: any[]): Promise<void> {
|
||||
navigateNext(editor: vscode.TextEditor): Promise<void> {
|
||||
return this.navigate(editor, NavigationDirection.Forwards);
|
||||
}
|
||||
|
||||
navigatePrevious(editor: vscode.TextEditor, ...args: any[]): Promise<void> {
|
||||
navigatePrevious(editor: vscode.TextEditor): Promise<void> {
|
||||
return this.navigate(editor, NavigationDirection.Backwards);
|
||||
}
|
||||
|
||||
async acceptSelection(editor: vscode.TextEditor, ...args: any[]): Promise<void> {
|
||||
async acceptSelection(editor: vscode.TextEditor): Promise<void> {
|
||||
let conflict = await this.findConflictContainingSelection(editor);
|
||||
|
||||
if (!conflict) {
|
||||
|
||||
@@ -4,21 +4,11 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
import * as vscode from 'vscode';
|
||||
import * as interfaces from './interfaces';
|
||||
|
||||
export default class MergeConflictContentProvider implements vscode.TextDocumentContentProvider, vscode.Disposable {
|
||||
|
||||
static scheme = 'merge-conflict.conflict-diff';
|
||||
|
||||
constructor(private context: vscode.ExtensionContext) {
|
||||
}
|
||||
|
||||
begin(config: interfaces.IExtensionConfiguration) {
|
||||
this.context.subscriptions.push(
|
||||
vscode.workspace.registerTextDocumentContentProvider(MergeConflictContentProvider.scheme, this)
|
||||
);
|
||||
}
|
||||
|
||||
dispose() {
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ export class DocumentMergeConflict implements interfaces.IDocumentMergeConflict
|
||||
public commonAncestors: interfaces.IMergeRegion[];
|
||||
public splitter: vscode.Range;
|
||||
|
||||
constructor(document: vscode.TextDocument, descriptor: interfaces.IDocumentMergeConflictDescriptor) {
|
||||
constructor(descriptor: interfaces.IDocumentMergeConflictDescriptor) {
|
||||
this.range = descriptor.range;
|
||||
this.current = descriptor.current;
|
||||
this.incoming = descriptor.incoming;
|
||||
@@ -27,7 +27,7 @@ export class DocumentMergeConflict implements interfaces.IDocumentMergeConflict
|
||||
|
||||
this.applyEdit(type, editor, edit);
|
||||
return Promise.resolve(true);
|
||||
};
|
||||
}
|
||||
|
||||
return editor.edit((edit) => this.applyEdit(type, editor, edit));
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ export default class DocumentMergeConflictTracker implements vscode.Disposable,
|
||||
this.cache.clear();
|
||||
}
|
||||
|
||||
private getConflictsOrEmpty(document: vscode.TextDocument, origins: string[]): interfaces.IDocumentMergeConflict[] {
|
||||
private getConflictsOrEmpty(document: vscode.TextDocument, _origins: string[]): interfaces.IDocumentMergeConflict[] {
|
||||
const containsConflict = MergeConflictParser.containsConflict(document);
|
||||
|
||||
if (!containsConflict) {
|
||||
|
||||
@@ -81,7 +81,7 @@ export class MergeConflictParser {
|
||||
|
||||
return conflictDescriptors
|
||||
.filter(Boolean)
|
||||
.map(descriptor => new DocumentMergeConflict(document, descriptor));
|
||||
.map(descriptor => new DocumentMergeConflict(descriptor));
|
||||
}
|
||||
|
||||
private static scanItemTolMergeConflictDescriptor(document: vscode.TextDocument, scanned: IScanMergedConflict): interfaces.IDocumentMergeConflictDescriptor | null {
|
||||
|
||||
@@ -26,9 +26,9 @@ export default class ServiceWrapper implements vscode.Disposable {
|
||||
|
||||
this.services.push(
|
||||
documentTracker,
|
||||
new CommandHandler(this.context, documentTracker),
|
||||
new CodeLensProvider(this.context, documentTracker),
|
||||
new ContentProvider(this.context),
|
||||
new CommandHandler(documentTracker),
|
||||
new CodeLensProvider(documentTracker),
|
||||
new ContentProvider(),
|
||||
new Decorator(this.context, documentTracker),
|
||||
);
|
||||
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
],
|
||||
"module": "commonjs",
|
||||
"outDir": "./out",
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"strict": true,
|
||||
"experimentalDecorators": true
|
||||
},
|
||||
|
||||
@@ -12,7 +12,7 @@ export default class PHPCompletionItemProvider implements CompletionItemProvider
|
||||
|
||||
public triggerCharacters = ['.', ':', '$'];
|
||||
|
||||
public provideCompletionItems(document: TextDocument, position: Position, token: CancellationToken): Promise<CompletionItem[]> {
|
||||
public provideCompletionItems(document: TextDocument, position: Position, _token: CancellationToken): Promise<CompletionItem[]> {
|
||||
let result: CompletionItem[] = [];
|
||||
|
||||
let shouldProvideCompletionItems = workspace.getConfiguration('php').get<boolean>('suggest.basic', true);
|
||||
@@ -27,7 +27,7 @@ export default class PHPCompletionItemProvider implements CompletionItemProvider
|
||||
}
|
||||
|
||||
var added: any = {};
|
||||
var createNewProposal = function (kind: CompletionItemKind, name: string, entry: phpGlobals.IEntry): CompletionItem {
|
||||
var createNewProposal = function (kind: CompletionItemKind, name: string, entry: phpGlobals.IEntry | null): CompletionItem {
|
||||
var proposal: CompletionItem = new CompletionItem(name);
|
||||
proposal.kind = kind;
|
||||
if (entry) {
|
||||
@@ -85,7 +85,7 @@ export default class PHPCompletionItemProvider implements CompletionItemProvider
|
||||
var text = document.getText();
|
||||
if (prefix[0] === '$') {
|
||||
var variableMatch = /\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)/g;
|
||||
var match: RegExpExecArray = null;
|
||||
var match: RegExpExecArray | null = null;
|
||||
while (match = variableMatch.exec(text)) {
|
||||
var word = match[0];
|
||||
if (!added[word]) {
|
||||
@@ -95,7 +95,7 @@ export default class PHPCompletionItemProvider implements CompletionItemProvider
|
||||
}
|
||||
}
|
||||
var functionMatch = /function\s+([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\s*\(/g;
|
||||
var match: RegExpExecArray = null;
|
||||
var match: RegExpExecArray | null = null;
|
||||
while (match = functionMatch.exec(text)) {
|
||||
var word = match[1];
|
||||
if (!added[word]) {
|
||||
|
||||
@@ -11,15 +11,15 @@ import { textToMarkedString } from './utils/markedTextUtil';
|
||||
|
||||
export default class PHPHoverProvider implements HoverProvider {
|
||||
|
||||
public provideHover(document: TextDocument, position: Position, token: CancellationToken): Hover {
|
||||
public provideHover(document: TextDocument, position: Position, _token: CancellationToken): Hover | undefined {
|
||||
let enable = workspace.getConfiguration('php').get<boolean>('suggest.basic', true);
|
||||
if (!enable) {
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let wordRange = document.getWordRangeAtPosition(position);
|
||||
if (!wordRange) {
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let name = document.getText(wordRange);
|
||||
@@ -30,5 +30,7 @@ export default class PHPHoverProvider implements HoverProvider {
|
||||
let contents: MarkedString[] = [textToMarkedString(entry.description), { language: 'php', value: signature }];
|
||||
return new Hover(contents, wordRange);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ class BackwardIterator {
|
||||
|
||||
export default class PHPSignatureHelpProvider implements SignatureHelpProvider {
|
||||
|
||||
public provideSignatureHelp(document: TextDocument, position: Position, token: CancellationToken): Promise<SignatureHelp> {
|
||||
public provideSignatureHelp(document: TextDocument, position: Position, _token: CancellationToken): Promise<SignatureHelp> | null {
|
||||
let enable = workspace.getConfiguration('php').get<boolean>('suggest.basic', true);
|
||||
if (!enable) {
|
||||
return null;
|
||||
@@ -95,7 +95,7 @@ export default class PHPSignatureHelpProvider implements SignatureHelpProvider {
|
||||
let signatureInfo = new SignatureInformation(ident + paramsString, entry.description);
|
||||
|
||||
var re = /\w*\s+\&?\$[\w_\.]+|void/g;
|
||||
var match: RegExpExecArray = null;
|
||||
var match: RegExpExecArray | null = null;
|
||||
while ((match = re.exec(paramsString)) !== null) {
|
||||
signatureInfo.parameters.push({ label: match[0], documentation: '' });
|
||||
}
|
||||
|
||||
@@ -29,9 +29,9 @@ export interface ITask<T> {
|
||||
*/
|
||||
export class Throttler<T> {
|
||||
|
||||
private activePromise: Promise<T>;
|
||||
private queuedPromise: Promise<T>;
|
||||
private queuedPromiseFactory: ITask<Promise<T>>;
|
||||
private activePromise: Promise<T> | null;
|
||||
private queuedPromise: Promise<T> | null;
|
||||
private queuedPromiseFactory: ITask<Promise<T>> | null;
|
||||
|
||||
constructor() {
|
||||
this.activePromise = null;
|
||||
@@ -47,26 +47,26 @@ export class Throttler<T> {
|
||||
var onComplete = () => {
|
||||
this.queuedPromise = null;
|
||||
|
||||
var result = this.queue(this.queuedPromiseFactory);
|
||||
var result = this.queue(this.queuedPromiseFactory!);
|
||||
this.queuedPromiseFactory = null;
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
this.queuedPromise = new Promise<T>((resolve, reject) => {
|
||||
this.activePromise.then(onComplete, onComplete).then(resolve);
|
||||
this.queuedPromise = new Promise<T>((resolve) => {
|
||||
this.activePromise!.then(onComplete, onComplete).then(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
return new Promise<T>((resolve, reject) => {
|
||||
this.queuedPromise.then(resolve, reject);
|
||||
this.queuedPromise!.then(resolve, reject);
|
||||
});
|
||||
}
|
||||
|
||||
this.activePromise = promiseFactory();
|
||||
|
||||
return new Promise<T>((resolve, reject) => {
|
||||
this.activePromise.then((result: T) => {
|
||||
this.activePromise!.then((result: T) => {
|
||||
this.activePromise = null;
|
||||
resolve(result);
|
||||
}, (err: any) => {
|
||||
@@ -103,10 +103,10 @@ export class Throttler<T> {
|
||||
export class Delayer<T> {
|
||||
|
||||
public defaultDelay: number;
|
||||
private timeout: NodeJS.Timer;
|
||||
private completionPromise: Promise<T>;
|
||||
private onResolve: (value: T | Thenable<T>) => void;
|
||||
private task: ITask<T>;
|
||||
private timeout: NodeJS.Timer | null;
|
||||
private completionPromise: Promise<T> | null;
|
||||
private onResolve: ((value: T | Thenable<T> | undefined) => void) | null;
|
||||
private task: ITask<T> | null;
|
||||
|
||||
constructor(defaultDelay: number) {
|
||||
this.defaultDelay = defaultDelay;
|
||||
@@ -121,13 +121,13 @@ export class Delayer<T> {
|
||||
this.cancelTimeout();
|
||||
|
||||
if (!this.completionPromise) {
|
||||
this.completionPromise = new Promise<T>((resolve, reject) => {
|
||||
this.completionPromise = new Promise<T>((resolve) => {
|
||||
this.onResolve = resolve;
|
||||
}).then(() => {
|
||||
this.completionPromise = null;
|
||||
this.onResolve = null;
|
||||
|
||||
var result = this.task();
|
||||
var result = this.task!();
|
||||
this.task = null;
|
||||
|
||||
return result;
|
||||
@@ -136,7 +136,7 @@ export class Delayer<T> {
|
||||
|
||||
this.timeout = setTimeout(() => {
|
||||
this.timeout = null;
|
||||
this.onResolve(null);
|
||||
this.onResolve!(undefined);
|
||||
}, delay);
|
||||
|
||||
return this.completionPromise;
|
||||
|
||||
@@ -16,7 +16,7 @@ let localize = nls.loadMessageBundle();
|
||||
|
||||
export class LineDecoder {
|
||||
private stringDecoder: NodeStringDecoder;
|
||||
private remaining: string;
|
||||
private remaining: string | null;
|
||||
|
||||
constructor(encoding: string = 'utf8') {
|
||||
this.stringDecoder = new StringDecoder(encoding);
|
||||
@@ -55,7 +55,7 @@ export class LineDecoder {
|
||||
return result;
|
||||
}
|
||||
|
||||
public end(): string {
|
||||
public end(): string | null {
|
||||
return this.remaining;
|
||||
}
|
||||
}
|
||||
@@ -88,17 +88,17 @@ export default class PHPValidationProvider {
|
||||
private static FileArgs: string[] = ['-l', '-n', '-d', 'display_errors=On', '-d', 'log_errors=Off', '-f'];
|
||||
|
||||
private validationEnabled: boolean;
|
||||
private executableIsUserDefined: boolean;
|
||||
private executable: string;
|
||||
private executableIsUserDefined: boolean | undefined;
|
||||
private executable: string | undefined;
|
||||
private trigger: RunTrigger;
|
||||
private pauseValidation: boolean;
|
||||
|
||||
private documentListener: vscode.Disposable;
|
||||
private documentListener: vscode.Disposable | null;
|
||||
private diagnosticCollection: vscode.DiagnosticCollection;
|
||||
private delayers: { [key: string]: ThrottledDelayer<void> };
|
||||
|
||||
constructor(private workspaceStore: vscode.Memento) {
|
||||
this.executable = null;
|
||||
this.executable = undefined;
|
||||
this.validationEnabled = true;
|
||||
this.trigger = RunTrigger.onSave;
|
||||
this.pauseValidation = false;
|
||||
@@ -145,7 +145,7 @@ export default class PHPValidationProvider {
|
||||
}
|
||||
this.trigger = RunTrigger.from(section.get<string>('validate.run', RunTrigger.strings.onSave));
|
||||
}
|
||||
if (this.executableIsUserDefined !== true && this.workspaceStore.get<string>(CheckedExecutablePath, undefined) !== void 0) {
|
||||
if (this.executableIsUserDefined !== true && this.workspaceStore.get<string | undefined>(CheckedExecutablePath, undefined) !== void 0) {
|
||||
vscode.commands.executeCommand('setContext', 'php.untrustValidationExecutableContext', true);
|
||||
}
|
||||
this.delayers = Object.create(null);
|
||||
@@ -195,7 +195,7 @@ export default class PHPValidationProvider {
|
||||
};
|
||||
|
||||
if (this.executableIsUserDefined !== void 0 && !this.executableIsUserDefined) {
|
||||
let checkedExecutablePath = this.workspaceStore.get<string>(CheckedExecutablePath, undefined);
|
||||
let checkedExecutablePath = this.workspaceStore.get<string | undefined>(CheckedExecutablePath, undefined);
|
||||
if (!checkedExecutablePath || checkedExecutablePath !== this.executable) {
|
||||
vscode.window.showInformationMessage<MessageItem>(
|
||||
localize('php.useExecutablePath', 'Do you allow {0} (defined as a workspace setting) to be executed to lint PHP files?', this.executable),
|
||||
@@ -224,7 +224,7 @@ export default class PHPValidationProvider {
|
||||
}
|
||||
|
||||
private doValidate(textDocument: vscode.TextDocument): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
return new Promise<void>((resolve) => {
|
||||
let executable = this.executable || 'php';
|
||||
let decoder = new LineDecoder();
|
||||
let diagnostics: vscode.Diagnostic[] = [];
|
||||
@@ -286,7 +286,7 @@ export default class PHPValidationProvider {
|
||||
}
|
||||
|
||||
private showError(error: any, executable: string): void {
|
||||
let message: string = null;
|
||||
let message: string | null = null;
|
||||
if (error.code === 'ENOENT') {
|
||||
if (this.executable) {
|
||||
message = localize('wrongExecutable', 'Cannot validate since {0} is not a valid php executable. Use the setting \'php.validate.executablePath\' to configure the PHP executable.', executable);
|
||||
@@ -296,6 +296,8 @@ export default class PHPValidationProvider {
|
||||
} else {
|
||||
message = error.message ? error.message : localize('unknownReason', 'Failed to run php using path: {0}. Reason is unknown.', executable);
|
||||
}
|
||||
vscode.window.showInformationMessage(message);
|
||||
if (message) {
|
||||
vscode.window.showInformationMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,12 @@
|
||||
"es2015"
|
||||
],
|
||||
"module": "commonjs",
|
||||
"outDir": "./out"
|
||||
"outDir": "./out",
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"strict": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
"es2015"
|
||||
],
|
||||
"module": "commonjs",
|
||||
"outDir": "./out"
|
||||
"outDir": "./out",
|
||||
"strict": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
|
||||
@@ -530,7 +530,7 @@
|
||||
},
|
||||
{
|
||||
"language": "typescriptreact",
|
||||
"path": "./snippets/typescriptreact.json"
|
||||
"path": "./snippets/typescript.json"
|
||||
}
|
||||
],
|
||||
"jsonValidation": [
|
||||
|
||||
@@ -1,278 +0,0 @@
|
||||
{
|
||||
"Constructor": {
|
||||
"prefix": "ctor",
|
||||
"body": [
|
||||
"/**",
|
||||
" *",
|
||||
" */",
|
||||
"constructor() {",
|
||||
"\tsuper();",
|
||||
"\t$0",
|
||||
"}"
|
||||
],
|
||||
"description": "Constructor"
|
||||
},
|
||||
"Class Definition": {
|
||||
"prefix": "class",
|
||||
"body": [
|
||||
"class ${1:name} {",
|
||||
"\tconstructor(${2:parameters}) {",
|
||||
"\t\t$0",
|
||||
"\t}",
|
||||
"}"
|
||||
],
|
||||
"description": "Class Definition"
|
||||
},
|
||||
"Public Method Definition": {
|
||||
"prefix": "public method",
|
||||
"body": [
|
||||
"/**",
|
||||
" * ${1:name}",
|
||||
" */",
|
||||
"public ${1:name}() {",
|
||||
"\t$0",
|
||||
"}"
|
||||
],
|
||||
"description": "Public Method Definition"
|
||||
},
|
||||
"Private Method Definition": {
|
||||
"prefix": "private method",
|
||||
"body": [
|
||||
"private ${1:name}() {",
|
||||
"\t$0",
|
||||
"}"
|
||||
],
|
||||
"description": "Private Method Definition"
|
||||
},
|
||||
"Import external module.": {
|
||||
"prefix": "import statement",
|
||||
"body": [
|
||||
"import { $0 } from \"${1:module}\";"
|
||||
],
|
||||
"description": "Import external module."
|
||||
},
|
||||
"Property getter": {
|
||||
"prefix": "get",
|
||||
"body": [
|
||||
"",
|
||||
"public get ${1:value}() : ${2:string} {",
|
||||
"\t${3:return $0}",
|
||||
"}",
|
||||
""
|
||||
],
|
||||
"description": "Property getter"
|
||||
},
|
||||
"Log to the console": {
|
||||
"prefix": "log",
|
||||
"body": [
|
||||
"console.log($1);",
|
||||
"$0"
|
||||
],
|
||||
"description": "Log to the console"
|
||||
},
|
||||
"Define a full property": {
|
||||
"prefix": "prop",
|
||||
"body": [
|
||||
"",
|
||||
"private _${1:value} : ${2:string};",
|
||||
"public get ${1:value}() : ${2:string} {",
|
||||
"\treturn this._${1:value};",
|
||||
"}",
|
||||
"public set ${1:value}(v : ${2:string}) {",
|
||||
"\tthis._${1:value} = v;",
|
||||
"}",
|
||||
""
|
||||
],
|
||||
"description": "Define a full property"
|
||||
},
|
||||
"Triple-slash reference": {
|
||||
"prefix": "ref",
|
||||
"body": [
|
||||
"/// <reference path=\"$1\" />",
|
||||
"$0"
|
||||
],
|
||||
"description": "Triple-slash reference"
|
||||
},
|
||||
"Return false": {
|
||||
"prefix": "ret0",
|
||||
"body": [
|
||||
"return false;$0"
|
||||
],
|
||||
"description": "Return false"
|
||||
},
|
||||
"Return true": {
|
||||
"prefix": "ret1",
|
||||
"body": [
|
||||
"return true;$0"
|
||||
],
|
||||
"description": "Return true"
|
||||
},
|
||||
"Return statement": {
|
||||
"prefix": "ret",
|
||||
"body": [
|
||||
"return $1;$0"
|
||||
],
|
||||
"description": "Return statement"
|
||||
},
|
||||
"Property setter": {
|
||||
"prefix": "set",
|
||||
"body": [
|
||||
"",
|
||||
"public set ${1:value}(v : ${2:string}) {",
|
||||
"\tthis.$3 = v;",
|
||||
"}",
|
||||
""
|
||||
],
|
||||
"description": "Property setter"
|
||||
},
|
||||
"Throw Exception": {
|
||||
"prefix": "throw",
|
||||
"body": [
|
||||
"throw \"$1\";",
|
||||
"$0"
|
||||
],
|
||||
"description": "Throw Exception"
|
||||
},
|
||||
"For Loop": {
|
||||
"prefix": "for",
|
||||
"body": [
|
||||
"for (let ${1:index} = 0; ${1:index} < ${2:array}.length; ${1:index}++) {",
|
||||
"\tconst ${3:element} = ${2:array}[${1:index}];",
|
||||
"\t$0",
|
||||
"}"
|
||||
],
|
||||
"description": "For Loop"
|
||||
},
|
||||
"For-Each Loop using =>": {
|
||||
"prefix": "foreach =>",
|
||||
"body": [
|
||||
"${1:array}.forEach(${2:element} => {",
|
||||
"\t$0",
|
||||
"});"
|
||||
],
|
||||
"description": "For-Each Loop using =>"
|
||||
},
|
||||
"For-In Loop": {
|
||||
"prefix": "forin",
|
||||
"body": [
|
||||
"for (const ${1:key} in ${2:object}) {",
|
||||
"\tif (${2:object}.hasOwnProperty(${1:key})) {",
|
||||
"\t\tconst ${3:element} = ${2:object}[${1:key}];",
|
||||
"\t\t$0",
|
||||
"\t}",
|
||||
"}"
|
||||
],
|
||||
"description": "For-In Loop"
|
||||
},
|
||||
"For-Of Loop": {
|
||||
"prefix": "forof",
|
||||
"body": [
|
||||
"for (const ${1:iterator} of ${2:object}) {",
|
||||
"\t$0",
|
||||
"}"
|
||||
],
|
||||
"description": "For-Of Loop"
|
||||
},
|
||||
"Function Statement": {
|
||||
"prefix": "function",
|
||||
"body": [
|
||||
"function ${1:name}(${2:params}:${3:type}) {",
|
||||
"\t$0",
|
||||
"}"
|
||||
],
|
||||
"description": "Function Statement"
|
||||
},
|
||||
"If Statement": {
|
||||
"prefix": "if",
|
||||
"body": [
|
||||
"if (${1:condition}) {",
|
||||
"\t$0",
|
||||
"}"
|
||||
],
|
||||
"description": "If Statement"
|
||||
},
|
||||
"If-Else Statement": {
|
||||
"prefix": "ifelse",
|
||||
"body": [
|
||||
"if (${1:condition}) {",
|
||||
"\t$0",
|
||||
"} else {",
|
||||
"\t",
|
||||
"}"
|
||||
],
|
||||
"description": "If-Else Statement"
|
||||
},
|
||||
"New Statement": {
|
||||
"prefix": "new",
|
||||
"body": [
|
||||
"const ${1:name} = new ${2:type}(${3:arguments});$0"
|
||||
],
|
||||
"description": "New Statement"
|
||||
},
|
||||
"Switch Statement": {
|
||||
"prefix": "switch",
|
||||
"body": [
|
||||
"switch (${1:key}) {",
|
||||
"\tcase ${2:value}:",
|
||||
"\t\t$0",
|
||||
"\t\tbreak;",
|
||||
"",
|
||||
"\tdefault:",
|
||||
"\t\tbreak;",
|
||||
"}"
|
||||
],
|
||||
"description": "Switch Statement"
|
||||
},
|
||||
"While Statement": {
|
||||
"prefix": "while",
|
||||
"body": [
|
||||
"while (${1:condition}) {",
|
||||
"\t$0",
|
||||
"}"
|
||||
],
|
||||
"description": "While Statement"
|
||||
},
|
||||
"Do-While Statement": {
|
||||
"prefix": "dowhile",
|
||||
"body": [
|
||||
"do {",
|
||||
"\t$0",
|
||||
"} while (${1:condition});"
|
||||
],
|
||||
"description": "Do-While Statement"
|
||||
},
|
||||
"Try-Catch Statement": {
|
||||
"prefix": "trycatch",
|
||||
"body": [
|
||||
"try {",
|
||||
"\t$0",
|
||||
"} catch (${1:error}) {",
|
||||
"\t",
|
||||
"}"
|
||||
],
|
||||
"description": "Try-Catch Statement"
|
||||
},
|
||||
"Set Timeout Function": {
|
||||
"prefix": "settimeout",
|
||||
"body": [
|
||||
"setTimeout(() => {",
|
||||
"\t$0",
|
||||
"}, ${1:timeout});"
|
||||
],
|
||||
"description": "Set Timeout Function"
|
||||
},
|
||||
"Region Start": {
|
||||
"prefix": "#region",
|
||||
"body": [
|
||||
"//#region $0"
|
||||
],
|
||||
"description": "Folding Region Start"
|
||||
},
|
||||
"Region End": {
|
||||
"prefix": "#endregion",
|
||||
"body": [
|
||||
"//#endregion"
|
||||
],
|
||||
"description": "Folding Region End"
|
||||
}
|
||||
}
|
||||
@@ -3,38 +3,50 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { CodeActionProvider, TextDocument, Range, CancellationToken, CodeActionContext, Command, commands } from 'vscode';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
import * as Proto from '../protocol';
|
||||
import { ITypeScriptServiceClient } from '../typescriptService';
|
||||
import { vsRangeToTsFileRange } from '../utils/convert';
|
||||
import FormattingConfigurationManager from './formattingConfigurationManager';
|
||||
import { applyCodeAction } from '../utils/codeAction';
|
||||
import { CommandManager, Command } from '../utils/commandManager';
|
||||
|
||||
interface NumberSet {
|
||||
[key: number]: boolean;
|
||||
}
|
||||
|
||||
export default class TypeScriptCodeActionProvider implements CodeActionProvider {
|
||||
private commandId: string;
|
||||
class ApplyCodeActionCommand implements Command {
|
||||
|
||||
public static readonly ID: string = '_typescript.applyCodeAction';
|
||||
public readonly id: string = ApplyCodeActionCommand.ID;
|
||||
|
||||
constructor(
|
||||
private readonly client: ITypeScriptServiceClient
|
||||
) { }
|
||||
|
||||
execute(action: Proto.CodeAction, file: string): void {
|
||||
applyCodeAction(this.client, action, file);
|
||||
}
|
||||
}
|
||||
|
||||
export default class TypeScriptCodeActionProvider implements vscode.CodeActionProvider {
|
||||
private _supportedCodeActions?: Thenable<NumberSet>;
|
||||
|
||||
constructor(
|
||||
private readonly client: ITypeScriptServiceClient,
|
||||
private readonly formattingConfigurationManager: FormattingConfigurationManager,
|
||||
mode: string
|
||||
commandManager: CommandManager
|
||||
) {
|
||||
this.commandId = `_typescript.applyCodeAction.${mode}`;
|
||||
commands.registerCommand(this.commandId, this.onCodeAction, this);
|
||||
commandManager.register(new ApplyCodeActionCommand(this.client));
|
||||
}
|
||||
|
||||
public async provideCodeActions(
|
||||
document: TextDocument,
|
||||
range: Range,
|
||||
context: CodeActionContext,
|
||||
token: CancellationToken
|
||||
): Promise<Command[]> {
|
||||
document: vscode.TextDocument,
|
||||
range: vscode.Range,
|
||||
context: vscode.CodeActionContext,
|
||||
token: vscode.CancellationToken
|
||||
): Promise<vscode.Command[]> {
|
||||
if (!this.client.apiVersion.has213Features()) {
|
||||
return [];
|
||||
}
|
||||
@@ -73,22 +85,18 @@ export default class TypeScriptCodeActionProvider implements CodeActionProvider
|
||||
return this._supportedCodeActions;
|
||||
}
|
||||
|
||||
private async getSupportedActionsForContext(context: CodeActionContext): Promise<Set<number>> {
|
||||
private async getSupportedActionsForContext(context: vscode.CodeActionContext): Promise<Set<number>> {
|
||||
const supportedActions = await this.supportedCodeActions;
|
||||
return new Set(context.diagnostics
|
||||
.map(diagnostic => +diagnostic.code)
|
||||
.filter(code => supportedActions[code]));
|
||||
}
|
||||
|
||||
private getCommandForAction(action: Proto.CodeAction, file: string): Command {
|
||||
private getCommandForAction(action: Proto.CodeAction, file: string): vscode.Command {
|
||||
return {
|
||||
title: action.description,
|
||||
command: this.commandId,
|
||||
command: ApplyCodeActionCommand.ID,
|
||||
arguments: [action, file]
|
||||
};
|
||||
}
|
||||
|
||||
private onCodeAction(action: Proto.CodeAction, file: string): Promise<boolean> {
|
||||
return applyCodeAction(this.client, action, file);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { CompletionItem, TextDocument, Position, CompletionItemKind, CompletionItemProvider, CancellationToken, TextEdit, Range, SnippetString, workspace, ProviderResult, CompletionContext, commands, Uri, MarkdownString } from 'vscode';
|
||||
import { CompletionItem, TextDocument, Position, CompletionItemKind, CompletionItemProvider, CancellationToken, TextEdit, Range, SnippetString, workspace, ProviderResult, CompletionContext, Uri, MarkdownString } from 'vscode';
|
||||
|
||||
import { ITypeScriptServiceClient } from '../typescriptService';
|
||||
import TypingsStatus from '../utils/typingsStatus';
|
||||
@@ -16,6 +16,7 @@ import { tsTextSpanToVsRange, vsPositionToTsFileLocation } from '../utils/conver
|
||||
import * as nls from 'vscode-nls';
|
||||
import { applyCodeAction } from '../utils/codeAction';
|
||||
import * as languageModeIds from '../utils/languageModeIds';
|
||||
import { CommandManager, Command } from '../utils/commandManager';
|
||||
|
||||
let localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -125,6 +126,24 @@ class MyCompletionItem extends CompletionItem {
|
||||
}
|
||||
}
|
||||
|
||||
class ApplyCompletionCodeActionCommand implements Command {
|
||||
public static readonly ID = '_typescript.applyCompletionCodeAction';
|
||||
public readonly id = ApplyCompletionCodeActionCommand.ID;
|
||||
|
||||
public constructor(
|
||||
private readonly client: ITypeScriptServiceClient
|
||||
) { }
|
||||
|
||||
public async execute(file: string, codeActions: CodeAction[]): Promise<boolean> {
|
||||
for (const action of codeActions) {
|
||||
if (!(await applyCodeAction(this.client, action, file))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
interface Configuration {
|
||||
useCodeSnippetsOnMethodSuggest: boolean;
|
||||
nameSuggestions: boolean;
|
||||
@@ -141,15 +160,12 @@ namespace Configuration {
|
||||
}
|
||||
|
||||
export default class TypeScriptCompletionItemProvider implements CompletionItemProvider {
|
||||
private readonly commandId: string;
|
||||
|
||||
constructor(
|
||||
private client: ITypeScriptServiceClient,
|
||||
mode: string,
|
||||
private typingsStatus: TypingsStatus
|
||||
private readonly typingsStatus: TypingsStatus,
|
||||
commandManager: CommandManager
|
||||
) {
|
||||
this.commandId = `_typescript.applyCompletionCodeAction.${mode}`;
|
||||
commands.registerCommand(this.commandId, this.applyCompletionCodeAction, this);
|
||||
commandManager.register(new ApplyCompletionCodeActionCommand(this.client));
|
||||
}
|
||||
|
||||
public async provideCompletionItems(
|
||||
@@ -311,7 +327,7 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP
|
||||
if (detail.codeActions && detail.codeActions.length) {
|
||||
item.command = {
|
||||
title: '',
|
||||
command: this.commandId,
|
||||
command: ApplyCompletionCodeActionCommand.ID,
|
||||
arguments: [filepath, detail.codeActions]
|
||||
};
|
||||
}
|
||||
@@ -378,16 +394,6 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP
|
||||
return new SnippetString(codeSnippet);
|
||||
}
|
||||
|
||||
private async applyCompletionCodeAction(file: string, codeActions: CodeAction[]): Promise<boolean> {
|
||||
for (const action of codeActions) {
|
||||
if (!(await applyCodeAction(this.client, action, file))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private getConfiguration(resource: Uri): Configuration {
|
||||
// Use shared setting for js and ts
|
||||
const typeScriptConfig = workspace.getConfiguration('typescript', resource);
|
||||
|
||||
@@ -10,6 +10,7 @@ import { DocCommandTemplateResponse } from '../protocol';
|
||||
|
||||
import * as nls from 'vscode-nls';
|
||||
import { vsPositionToTsFileLocation } from '../utils/convert';
|
||||
import { Command, CommandManager } from '../utils/commandManager';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
const configurationNamespace = 'jsDocCompletion';
|
||||
@@ -45,11 +46,14 @@ class JsDocCompletionItem extends CompletionItem {
|
||||
}
|
||||
}
|
||||
|
||||
export class JsDocCompletionProvider implements CompletionItemProvider {
|
||||
export default class JsDocCompletionProvider implements CompletionItemProvider {
|
||||
|
||||
constructor(
|
||||
private client: ITypeScriptServiceClient,
|
||||
) { }
|
||||
commandManager: CommandManager
|
||||
) {
|
||||
commandManager.register(new TryCompleteJsDocCommand(client));
|
||||
}
|
||||
|
||||
public provideCompletionItems(
|
||||
document: TextDocument,
|
||||
@@ -77,19 +81,20 @@ export class JsDocCompletionProvider implements CompletionItemProvider {
|
||||
}
|
||||
}
|
||||
|
||||
export class TryCompleteJsDocCommand {
|
||||
static COMMAND_NAME = '_typeScript.tryCompleteJsDoc';
|
||||
class TryCompleteJsDocCommand implements Command {
|
||||
public static readonly COMMAND_NAME = '_typeScript.tryCompleteJsDoc';
|
||||
public readonly id = TryCompleteJsDocCommand.COMMAND_NAME;
|
||||
|
||||
constructor(
|
||||
private lazyClient: () => ITypeScriptServiceClient
|
||||
private readonly client: ITypeScriptServiceClient
|
||||
) { }
|
||||
|
||||
/**
|
||||
* Try to insert a jsdoc comment, using a template provide by typescript
|
||||
* if possible, otherwise falling back to a default comment format.
|
||||
*/
|
||||
public async tryCompleteJsDoc(resource: Uri, start: Position, shouldGetJSDocFromTSServer: boolean): Promise<boolean> {
|
||||
const file = this.lazyClient().normalizePath(resource);
|
||||
public async execute(resource: Uri, start: Position, shouldGetJSDocFromTSServer: boolean): Promise<boolean> {
|
||||
const file = this.client.normalizePath(resource);
|
||||
if (!file) {
|
||||
return false;
|
||||
}
|
||||
@@ -113,7 +118,7 @@ export class TryCompleteJsDocCommand {
|
||||
private tryInsertJsDocFromTemplate(editor: TextEditor, file: string, position: Position): Promise<boolean> {
|
||||
const args = vsPositionToTsFileLocation(file, position);
|
||||
return Promise.race([
|
||||
this.lazyClient().execute('docCommentTemplate', args),
|
||||
this.client.execute('docCommentTemplate', args),
|
||||
new Promise<DocCommandTemplateResponse>((_, reject) => setTimeout(reject, 250))
|
||||
]).then((res: DocCommandTemplateResponse) => {
|
||||
if (!res || !res.body) {
|
||||
|
||||
@@ -5,35 +5,113 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import { CodeActionProvider, TextDocument, Range, CancellationToken, CodeActionContext, Command, commands, workspace, WorkspaceEdit, window, QuickPickItem, Selection } from 'vscode';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
import * as Proto from '../protocol';
|
||||
import { ITypeScriptServiceClient } from '../typescriptService';
|
||||
import { tsTextSpanToVsRange, vsRangeToTsFileRange, tsLocationToVsPosition } from '../utils/convert';
|
||||
import FormattingOptionsManager from './formattingConfigurationManager';
|
||||
import { CommandManager, Command } from '../utils/commandManager';
|
||||
|
||||
export default class TypeScriptRefactorProvider implements CodeActionProvider {
|
||||
private doRefactorCommandId: string;
|
||||
private selectRefactorCommandId: string;
|
||||
class ApplyRefactoringCommand implements Command {
|
||||
public static readonly ID = '_typescript.applyRefactoring';
|
||||
public readonly id = ApplyRefactoringCommand.ID;
|
||||
|
||||
constructor(
|
||||
private readonly client: ITypeScriptServiceClient,
|
||||
private formattingOptionsManager: FormattingOptionsManager,
|
||||
mode: string
|
||||
) {
|
||||
this.doRefactorCommandId = `_typescript.applyRefactoring.${mode}`;
|
||||
this.selectRefactorCommandId = `_typescript.selectRefactoring.${mode}`;
|
||||
private formattingOptionsManager: FormattingOptionsManager
|
||||
) { }
|
||||
|
||||
commands.registerCommand(this.doRefactorCommandId, this.doRefactoring, this);
|
||||
commands.registerCommand(this.selectRefactorCommandId, this.selectRefactoring, this);
|
||||
public async execute(
|
||||
document: vscode.TextDocument,
|
||||
file: string,
|
||||
refactor: string,
|
||||
action: string,
|
||||
range: vscode.Range
|
||||
): Promise<boolean> {
|
||||
await this.formattingOptionsManager.ensureFormatOptionsForDocument(document, undefined);
|
||||
|
||||
const args: Proto.GetEditsForRefactorRequestArgs = {
|
||||
...vsRangeToTsFileRange(file, range),
|
||||
refactor,
|
||||
action
|
||||
};
|
||||
|
||||
const response = await this.client.execute('getEditsForRefactor', args);
|
||||
if (!response || !response.body || !response.body.edits.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const edit = this.toWorkspaceEdit(response.body.edits);
|
||||
if (!(await vscode.workspace.applyEdit(edit))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const renameLocation = response.body.renameLocation;
|
||||
if (renameLocation) {
|
||||
if (vscode.window.activeTextEditor && vscode.window.activeTextEditor.document.uri.fsPath === file) {
|
||||
const pos = tsLocationToVsPosition(renameLocation);
|
||||
vscode.window.activeTextEditor.selection = new vscode.Selection(pos, pos);
|
||||
await vscode.commands.executeCommand('editor.action.rename');
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private toWorkspaceEdit(edits: Proto.FileCodeEdits[]): vscode.WorkspaceEdit {
|
||||
const workspaceEdit = new vscode.WorkspaceEdit();
|
||||
for (const edit of edits) {
|
||||
for (const textChange of edit.textChanges) {
|
||||
workspaceEdit.replace(this.client.asUrl(edit.fileName),
|
||||
tsTextSpanToVsRange(textChange),
|
||||
textChange.newText);
|
||||
}
|
||||
}
|
||||
return workspaceEdit;
|
||||
}
|
||||
}
|
||||
|
||||
class SelectRefactorCommand implements Command {
|
||||
public static readonly ID = '_typescript.selectRefactoring';
|
||||
public readonly id = SelectRefactorCommand.ID;
|
||||
|
||||
constructor(
|
||||
private readonly doRefactoring: ApplyRefactoringCommand
|
||||
) { }
|
||||
|
||||
public async execute(
|
||||
document: vscode.TextDocument,
|
||||
file: string,
|
||||
info: Proto.ApplicableRefactorInfo,
|
||||
range: vscode.Range
|
||||
): Promise<boolean> {
|
||||
const selected = await vscode.window.showQuickPick(info.actions.map((action): vscode.QuickPickItem => ({
|
||||
label: action.name,
|
||||
description: action.description
|
||||
})));
|
||||
if (!selected) {
|
||||
return false;
|
||||
}
|
||||
return this.doRefactoring.execute(document, file, info.name, selected.label, range);
|
||||
}
|
||||
}
|
||||
|
||||
export default class TypeScriptRefactorProvider implements vscode.CodeActionProvider {
|
||||
constructor(
|
||||
private readonly client: ITypeScriptServiceClient,
|
||||
formattingOptionsManager: FormattingOptionsManager,
|
||||
commandManager: CommandManager
|
||||
) {
|
||||
const doRefactoringCommand = commandManager.register(new ApplyRefactoringCommand(this.client, formattingOptionsManager));
|
||||
commandManager.register(new SelectRefactorCommand(doRefactoringCommand));
|
||||
}
|
||||
|
||||
public async provideCodeActions(
|
||||
document: TextDocument,
|
||||
range: Range,
|
||||
_context: CodeActionContext,
|
||||
token: CancellationToken
|
||||
): Promise<Command[]> {
|
||||
document: vscode.TextDocument,
|
||||
range: vscode.Range,
|
||||
_context: vscode.CodeActionContext,
|
||||
token: vscode.CancellationToken
|
||||
): Promise<vscode.Command[]> {
|
||||
if (!this.client.apiVersion.has240Features()) {
|
||||
return [];
|
||||
}
|
||||
@@ -50,19 +128,19 @@ export default class TypeScriptRefactorProvider implements CodeActionProvider {
|
||||
return [];
|
||||
}
|
||||
|
||||
const actions: Command[] = [];
|
||||
const actions: vscode.Command[] = [];
|
||||
for (const info of response.body) {
|
||||
if (info.inlineable === false) {
|
||||
actions.push({
|
||||
title: info.description,
|
||||
command: this.selectRefactorCommandId,
|
||||
command: SelectRefactorCommand.ID,
|
||||
arguments: [document, file, info, range]
|
||||
});
|
||||
} else {
|
||||
for (const action of info.actions) {
|
||||
actions.push({
|
||||
title: action.description,
|
||||
command: this.doRefactorCommandId,
|
||||
command: ApplyRefactoringCommand.ID,
|
||||
arguments: [document, file, info.name, action.name, range]
|
||||
});
|
||||
}
|
||||
@@ -73,57 +151,4 @@ export default class TypeScriptRefactorProvider implements CodeActionProvider {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
private toWorkspaceEdit(edits: Proto.FileCodeEdits[]): WorkspaceEdit {
|
||||
const workspaceEdit = new WorkspaceEdit();
|
||||
for (const edit of edits) {
|
||||
for (const textChange of edit.textChanges) {
|
||||
workspaceEdit.replace(this.client.asUrl(edit.fileName),
|
||||
tsTextSpanToVsRange(textChange),
|
||||
textChange.newText);
|
||||
}
|
||||
}
|
||||
return workspaceEdit;
|
||||
}
|
||||
|
||||
private async selectRefactoring(document: TextDocument, file: string, info: Proto.ApplicableRefactorInfo, range: Range): Promise<boolean> {
|
||||
const selected = await window.showQuickPick(info.actions.map((action): QuickPickItem => ({
|
||||
label: action.name,
|
||||
description: action.description
|
||||
})));
|
||||
if (!selected) {
|
||||
return false;
|
||||
}
|
||||
return this.doRefactoring(document, file, info.name, selected.label, range);
|
||||
}
|
||||
|
||||
private async doRefactoring(document: TextDocument, file: string, refactor: string, action: string, range: Range): Promise<boolean> {
|
||||
await this.formattingOptionsManager.ensureFormatOptionsForDocument(document, undefined);
|
||||
|
||||
const args: Proto.GetEditsForRefactorRequestArgs = {
|
||||
...vsRangeToTsFileRange(file, range),
|
||||
refactor,
|
||||
action
|
||||
};
|
||||
|
||||
const response = await this.client.execute('getEditsForRefactor', args);
|
||||
if (!response || !response.body || !response.body.edits.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const edit = this.toWorkspaceEdit(response.body.edits);
|
||||
if (!(await workspace.applyEdit(edit))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const renameLocation = response.body.renameLocation;
|
||||
if (renameLocation) {
|
||||
if (window.activeTextEditor && window.activeTextEditor.document.uri.fsPath === file) {
|
||||
const pos = tsLocationToVsPosition(renameLocation);
|
||||
window.activeTextEditor.selection = new Selection(pos, pos);
|
||||
await commands.executeCommand('editor.action.rename');
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,8 @@ function getSymbolKind(item: Proto.NavtoItem): SymbolKind {
|
||||
export default class TypeScriptWorkspaceSymbolProvider implements WorkspaceSymbolProvider {
|
||||
public constructor(
|
||||
private client: ITypeScriptServiceClient,
|
||||
private modeId: string) { }
|
||||
private modeIds: string[]
|
||||
) { }
|
||||
|
||||
public async provideWorkspaceSymbols(search: string, token: CancellationToken): Promise<SymbolInformation[]> {
|
||||
// typescript wants to have a resource even when asking
|
||||
@@ -34,14 +35,14 @@ export default class TypeScriptWorkspaceSymbolProvider implements WorkspaceSymbo
|
||||
const editor = window.activeTextEditor;
|
||||
if (editor) {
|
||||
const document = editor.document;
|
||||
if (document && document.languageId === this.modeId) {
|
||||
if (document && this.modeIds.indexOf(document.languageId) >= 0) {
|
||||
uri = document.uri;
|
||||
}
|
||||
}
|
||||
if (!uri) {
|
||||
const documents = workspace.textDocuments;
|
||||
for (const document of documents) {
|
||||
if (document.languageId === this.modeId) {
|
||||
if (this.modeIds.indexOf(document.languageId) >= 0) {
|
||||
uri = document.uri;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import TypeScriptServiceClient from './typescriptServiceClient';
|
||||
import { ITypeScriptServiceClientHost } from './typescriptService';
|
||||
|
||||
import BufferSyncSupport from './features/bufferSyncSupport';
|
||||
import { JsDocCompletionProvider, TryCompleteJsDocCommand } from './features/jsDocCompletionProvider';
|
||||
import TypeScriptTaskProviderManager from './features/taskProvider';
|
||||
|
||||
import * as ProjectStatus from './utils/projectStatus';
|
||||
@@ -36,6 +35,7 @@ import { openOrCreateConfigFile, isImplicitProjectConfigFile } from './utils/tsc
|
||||
import { tsLocationToVsPosition } from './utils/convert';
|
||||
import FormattingConfigurationManager from './features/formattingConfigurationManager';
|
||||
import * as languageModeIds from './utils/languageModeIds';
|
||||
import { CommandManager, Command } from './utils/commandManager';
|
||||
|
||||
interface LanguageDescription {
|
||||
id: string;
|
||||
@@ -45,16 +45,6 @@ interface LanguageDescription {
|
||||
isExternal?: boolean;
|
||||
}
|
||||
|
||||
enum ProjectConfigAction {
|
||||
None,
|
||||
CreateConfig,
|
||||
LearnMore
|
||||
}
|
||||
|
||||
interface ProjectConfigMessageItem extends MessageItem {
|
||||
id: ProjectConfigAction;
|
||||
}
|
||||
|
||||
const standardLanguageDescriptions: LanguageDescription[] = [
|
||||
{
|
||||
id: 'typescript',
|
||||
@@ -69,14 +59,107 @@ const standardLanguageDescriptions: LanguageDescription[] = [
|
||||
}
|
||||
];
|
||||
|
||||
class ReloadTypeScriptProjectsCommand implements Command {
|
||||
public readonly id = 'typescript.reloadProjects';
|
||||
|
||||
public constructor(
|
||||
private readonly lazyClientHost: () => TypeScriptServiceClientHost
|
||||
) { }
|
||||
|
||||
public execute() {
|
||||
this.lazyClientHost().reloadProjects();
|
||||
}
|
||||
}
|
||||
|
||||
class ReloadJavaScriptProjectsCommand implements Command {
|
||||
public readonly id = 'javascript.reloadProjects';
|
||||
|
||||
public constructor(
|
||||
private readonly lazyClientHost: () => TypeScriptServiceClientHost
|
||||
) { }
|
||||
|
||||
public execute() {
|
||||
this.lazyClientHost().reloadProjects();
|
||||
}
|
||||
}
|
||||
|
||||
class SelectTypeScriptVersionCommand implements Command {
|
||||
public readonly id = 'typescript.selectTypeScriptVersion';
|
||||
|
||||
public constructor(
|
||||
private readonly lazyClientHost: () => TypeScriptServiceClientHost
|
||||
) { }
|
||||
|
||||
public execute() {
|
||||
this.lazyClientHost().serviceClient.onVersionStatusClicked();
|
||||
}
|
||||
}
|
||||
|
||||
class OpenTsServerLogCommand implements Command {
|
||||
public readonly id = 'typescript.openTsServerLog';
|
||||
|
||||
public constructor(
|
||||
private readonly lazyClientHost: () => TypeScriptServiceClientHost
|
||||
) { }
|
||||
|
||||
public execute() {
|
||||
this.lazyClientHost().serviceClient.openTsServerLogFile();
|
||||
}
|
||||
}
|
||||
|
||||
class RestartTsServerCommand implements Command {
|
||||
public readonly id = 'typescript.restartTsServer';
|
||||
|
||||
public constructor(
|
||||
private readonly lazyClientHost: () => TypeScriptServiceClientHost
|
||||
) { }
|
||||
|
||||
public execute() {
|
||||
this.lazyClientHost().serviceClient.restartTsServer();
|
||||
}
|
||||
}
|
||||
|
||||
class TypeScriptGoToProjectConfigCommand implements Command {
|
||||
public readonly id = 'typescript.goToProjectConfig';
|
||||
|
||||
public constructor(
|
||||
private readonly lazyClientHost: () => TypeScriptServiceClientHost,
|
||||
) { }
|
||||
|
||||
public execute() {
|
||||
const editor = window.activeTextEditor;
|
||||
if (editor) {
|
||||
this.lazyClientHost().goToProjectConfig(true, editor.document.uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class JavaScriptGoToProjectConfigCommand implements Command {
|
||||
public readonly id = 'javascript.goToProjectConfig';
|
||||
|
||||
public constructor(
|
||||
private readonly lazyClientHost: () => TypeScriptServiceClientHost,
|
||||
) { }
|
||||
|
||||
public execute() {
|
||||
const editor = window.activeTextEditor;
|
||||
if (editor) {
|
||||
this.lazyClientHost().goToProjectConfig(false, editor.document.uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function activate(context: ExtensionContext): void {
|
||||
const plugins = getContributedTypeScriptServerPlugins();
|
||||
|
||||
const commandManager = new CommandManager();
|
||||
context.subscriptions.push(commandManager);
|
||||
|
||||
const lazyClientHost = (() => {
|
||||
let clientHost: TypeScriptServiceClientHost | undefined;
|
||||
return () => {
|
||||
if (!clientHost) {
|
||||
clientHost = new TypeScriptServiceClientHost(standardLanguageDescriptions, context.workspaceState, plugins);
|
||||
clientHost = new TypeScriptServiceClientHost(standardLanguageDescriptions, context.workspaceState, plugins, commandManager);
|
||||
context.subscriptions.push(clientHost);
|
||||
|
||||
const host = clientHost;
|
||||
@@ -92,42 +175,16 @@ export function activate(context: ExtensionContext): void {
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
context.subscriptions.push(commands.registerCommand('typescript.reloadProjects', () => {
|
||||
lazyClientHost().reloadProjects();
|
||||
}));
|
||||
|
||||
context.subscriptions.push(commands.registerCommand('javascript.reloadProjects', () => {
|
||||
lazyClientHost().reloadProjects();
|
||||
}));
|
||||
|
||||
context.subscriptions.push(commands.registerCommand('typescript.selectTypeScriptVersion', () => {
|
||||
lazyClientHost().serviceClient.onVersionStatusClicked();
|
||||
}));
|
||||
|
||||
context.subscriptions.push(commands.registerCommand('typescript.openTsServerLog', () => {
|
||||
lazyClientHost().serviceClient.openTsServerLogFile();
|
||||
}));
|
||||
|
||||
context.subscriptions.push(commands.registerCommand('typescript.restartTsServer', () => {
|
||||
lazyClientHost().serviceClient.restartTsServer();
|
||||
}));
|
||||
commandManager.register(new ReloadTypeScriptProjectsCommand(lazyClientHost));
|
||||
commandManager.register(new ReloadJavaScriptProjectsCommand(lazyClientHost));
|
||||
commandManager.register(new SelectTypeScriptVersionCommand(lazyClientHost));
|
||||
commandManager.register(new OpenTsServerLogCommand(lazyClientHost));
|
||||
commandManager.register(new RestartTsServerCommand(lazyClientHost));
|
||||
commandManager.register(new TypeScriptGoToProjectConfigCommand(lazyClientHost));
|
||||
commandManager.register(new JavaScriptGoToProjectConfigCommand(lazyClientHost));
|
||||
|
||||
context.subscriptions.push(new TypeScriptTaskProviderManager(() => lazyClientHost().serviceClient));
|
||||
|
||||
const goToProjectConfig = (isTypeScript: boolean) => {
|
||||
const editor = window.activeTextEditor;
|
||||
if (editor) {
|
||||
lazyClientHost().goToProjectConfig(isTypeScript, editor.document.uri);
|
||||
}
|
||||
};
|
||||
context.subscriptions.push(commands.registerCommand('typescript.goToProjectConfig', goToProjectConfig.bind(null, true)));
|
||||
context.subscriptions.push(commands.registerCommand('javascript.goToProjectConfig', goToProjectConfig.bind(null, false)));
|
||||
|
||||
const jsDocCompletionCommand = new TryCompleteJsDocCommand(() => lazyClientHost().serviceClient);
|
||||
context.subscriptions.push(commands.registerCommand(TryCompleteJsDocCommand.COMMAND_NAME, jsDocCompletionCommand.tryCompleteJsDoc, jsDocCompletionCommand));
|
||||
|
||||
|
||||
const EMPTY_ELEMENTS: string[] = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'];
|
||||
|
||||
context.subscriptions.push(languages.setLanguageConfiguration('jsx-tags', {
|
||||
@@ -154,7 +211,7 @@ export function activate(context: ExtensionContext): void {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
const openListener = workspace.onDidOpenTextDocument(didOpenTextDocument);
|
||||
for (let textDocument of workspace.textDocuments) {
|
||||
if (didOpenTextDocument(textDocument)) {
|
||||
@@ -187,7 +244,8 @@ class LanguageProvider {
|
||||
|
||||
constructor(
|
||||
private readonly client: TypeScriptServiceClient,
|
||||
private readonly description: LanguageDescription
|
||||
private readonly description: LanguageDescription,
|
||||
private readonly commandManager: CommandManager
|
||||
) {
|
||||
this.formattingOptionsManager = new FormattingConfigurationManager(client);
|
||||
this.bufferSyncSupport = new BufferSyncSupport(client, description.modeIds, {
|
||||
@@ -238,8 +296,9 @@ class LanguageProvider {
|
||||
const selector = this.description.modeIds;
|
||||
const config = workspace.getConfiguration(this.id);
|
||||
|
||||
const completionItemProvider = new (await import('./features/completionItemProvider')).default(client, this.description.id, this.typingsStatus);
|
||||
this.disposables.push(languages.registerCompletionItemProvider(selector, completionItemProvider, '.', '"', '\'', '/', '@'));
|
||||
this.disposables.push(languages.registerCompletionItemProvider(selector,
|
||||
new (await import('./features/completionItemProvider')).default(client, this.typingsStatus, this.commandManager),
|
||||
'.', '"', '\'', '/', '@'));
|
||||
|
||||
this.disposables.push(languages.registerCompletionItemProvider(selector, new (await import('./features/directiveCommentCompletionProvider')).default(client), '@'));
|
||||
|
||||
@@ -253,7 +312,7 @@ class LanguageProvider {
|
||||
this.disposables.push(formattingProviderManager);
|
||||
this.toUpdateOnConfigurationChanged.push(formattingProviderManager);
|
||||
|
||||
this.disposables.push(languages.registerCompletionItemProvider(selector, new JsDocCompletionProvider(client), '*'));
|
||||
this.disposables.push(languages.registerCompletionItemProvider(selector, new (await import('./features/jsDocCompletionProvider')).default(client, this.commandManager), '*'));
|
||||
this.disposables.push(languages.registerHoverProvider(selector, new (await import('./features/hoverProvider')).default(client)));
|
||||
this.disposables.push(languages.registerDefinitionProvider(selector, new (await import('./features/definitionProvider')).default(client)));
|
||||
this.disposables.push(languages.registerDocumentHighlightProvider(selector, new (await import('./features/documentHighlightProvider')).default(client)));
|
||||
@@ -261,24 +320,24 @@ class LanguageProvider {
|
||||
this.disposables.push(languages.registerDocumentSymbolProvider(selector, new (await import('./features/documentSymbolProvider')).default(client)));
|
||||
this.disposables.push(languages.registerSignatureHelpProvider(selector, new (await import('./features/signatureHelpProvider')).default(client), '(', ','));
|
||||
this.disposables.push(languages.registerRenameProvider(selector, new (await import('./features/renameProvider')).default(client)));
|
||||
this.disposables.push(languages.registerCodeActionsProvider(selector, new (await import('./features/codeActionProvider')).default(client, this.formattingOptionsManager, this.description.id)));
|
||||
this.disposables.push(languages.registerCodeActionsProvider(selector, new (await import('./features/refactorProvider')).default(client, this.formattingOptionsManager, this.description.id)));
|
||||
this.disposables.push(languages.registerCodeActionsProvider(selector, new (await import('./features/codeActionProvider')).default(client, this.formattingOptionsManager, this.commandManager)));
|
||||
this.disposables.push(languages.registerCodeActionsProvider(selector, new (await import('./features/refactorProvider')).default(client, this.formattingOptionsManager, this.commandManager)));
|
||||
this.registerVersionDependentProviders();
|
||||
|
||||
for (const modeId of this.description.modeIds) {
|
||||
this.disposables.push(languages.registerWorkspaceSymbolProvider(new (await import('./features/workspaceSymbolProvider')).default(client, modeId)));
|
||||
const referenceCodeLensProvider = new (await import('./features/referencesCodeLensProvider')).default(client, this.description.id);
|
||||
referenceCodeLensProvider.updateConfiguration();
|
||||
this.toUpdateOnConfigurationChanged.push(referenceCodeLensProvider);
|
||||
this.disposables.push(languages.registerCodeLensProvider(selector, referenceCodeLensProvider));
|
||||
|
||||
const referenceCodeLensProvider = new (await import('./features/referencesCodeLensProvider')).default(client, modeId);
|
||||
referenceCodeLensProvider.updateConfiguration();
|
||||
this.toUpdateOnConfigurationChanged.push(referenceCodeLensProvider);
|
||||
this.disposables.push(languages.registerCodeLensProvider(selector, referenceCodeLensProvider));
|
||||
const implementationCodeLensProvider = new (await import('./features/implementationsCodeLensProvider')).default(client, this.description.id);
|
||||
implementationCodeLensProvider.updateConfiguration();
|
||||
this.toUpdateOnConfigurationChanged.push(implementationCodeLensProvider);
|
||||
this.disposables.push(languages.registerCodeLensProvider(selector, implementationCodeLensProvider));
|
||||
|
||||
const implementationCodeLensProvider = new (await import('./features/implementationsCodeLensProvider')).default(client, modeId);
|
||||
implementationCodeLensProvider.updateConfiguration();
|
||||
this.toUpdateOnConfigurationChanged.push(implementationCodeLensProvider);
|
||||
this.disposables.push(languages.registerCodeLensProvider(selector, implementationCodeLensProvider));
|
||||
this.disposables.push(languages.registerWorkspaceSymbolProvider(new (await import('./features/workspaceSymbolProvider')).default(client, this.description.modeIds)));
|
||||
|
||||
if (!this.description.isExternal) {
|
||||
if (!this.description.isExternal) {
|
||||
for (const modeId of this.description.modeIds) {
|
||||
this.disposables.push(languages.setLanguageConfiguration(modeId, {
|
||||
indentationRules: {
|
||||
// ^(.*\*/)?\s*\}.*$
|
||||
@@ -442,7 +501,8 @@ class TypeScriptServiceClientHost implements ITypeScriptServiceClientHost {
|
||||
constructor(
|
||||
descriptions: LanguageDescription[],
|
||||
workspaceState: Memento,
|
||||
plugins: TypeScriptServerPlugin[]
|
||||
plugins: TypeScriptServerPlugin[],
|
||||
private commandManager: CommandManager
|
||||
) {
|
||||
const handleProjectCreateOrDelete = () => {
|
||||
this.client.execute('reloadProjects', null, false);
|
||||
@@ -467,7 +527,7 @@ class TypeScriptServiceClientHost implements ITypeScriptServiceClientHost {
|
||||
|
||||
this.languagePerId = new Map();
|
||||
for (const description of descriptions) {
|
||||
const manager = new LanguageProvider(this.client, description);
|
||||
const manager = new LanguageProvider(this.client, description, this.commandManager);
|
||||
this.languages.push(manager);
|
||||
this.disposables.push(manager);
|
||||
this.languagePerId.set(description.id, manager);
|
||||
@@ -491,7 +551,7 @@ class TypeScriptServiceClientHost implements ITypeScriptServiceClientHost {
|
||||
diagnosticSource: 'ts-plugins',
|
||||
isExternal: true
|
||||
};
|
||||
const manager = new LanguageProvider(this.client, description);
|
||||
const manager = new LanguageProvider(this.client, description, this.commandManager);
|
||||
this.languages.push(manager);
|
||||
this.disposables.push(manager);
|
||||
this.languagePerId.set(description.id, manager);
|
||||
@@ -566,6 +626,16 @@ class TypeScriptServiceClientHost implements ITypeScriptServiceClientHost {
|
||||
return;
|
||||
}
|
||||
|
||||
enum ProjectConfigAction {
|
||||
None,
|
||||
CreateConfig,
|
||||
LearnMore
|
||||
}
|
||||
|
||||
interface ProjectConfigMessageItem extends MessageItem {
|
||||
id: ProjectConfigAction;
|
||||
}
|
||||
|
||||
const selected = await window.showInformationMessage<ProjectConfigMessageItem>(
|
||||
(isTypeScriptProject
|
||||
? localize('typescript.noTypeScriptProjectConfig', 'File is not part of a TypeScript project')
|
||||
|
||||
@@ -375,6 +375,7 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
|
||||
this.isRestarting = false;
|
||||
});
|
||||
|
||||
// tslint:disable-next-line:no-unused-expression
|
||||
new Reader<Proto.Response>(
|
||||
childProcess.stdout,
|
||||
(msg) => { this.dispatchMessage(msg); },
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export interface Command {
|
||||
readonly id: string;
|
||||
|
||||
execute(...args: any[]): void;
|
||||
}
|
||||
|
||||
export class CommandManager {
|
||||
private readonly commands = new Map<string, vscode.Disposable>();
|
||||
|
||||
public dispose() {
|
||||
for (const registration of this.commands.values()) {
|
||||
registration.dispose();
|
||||
}
|
||||
this.commands.clear();
|
||||
}
|
||||
|
||||
private registerCommand(id: string, impl: (...args: any[]) => void, thisArg?: any) {
|
||||
if (this.commands.has(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.commands.set(id, vscode.commands.registerCommand(id, impl, thisArg));
|
||||
}
|
||||
|
||||
public register<T extends Command>(command: T): T {
|
||||
this.registerCommand(command.id, command.execute, command);
|
||||
return command;
|
||||
}
|
||||
}
|
||||
@@ -36,22 +36,22 @@ function getEmptyConfig(
|
||||
}`);
|
||||
}
|
||||
|
||||
export function openOrCreateConfigFile(
|
||||
export async function openOrCreateConfigFile(
|
||||
isTypeScriptProject: boolean,
|
||||
rootPath: string,
|
||||
config: TypeScriptServiceConfiguration
|
||||
): Thenable<vscode.TextEditor | null> {
|
||||
): Promise<vscode.TextEditor | null> {
|
||||
const configFile = vscode.Uri.file(path.join(rootPath, isTypeScriptProject ? 'tsconfig.json' : 'jsconfig.json'));
|
||||
const col = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.viewColumn : undefined;
|
||||
return vscode.workspace.openTextDocument(configFile)
|
||||
.then(doc => {
|
||||
return vscode.window.showTextDocument(doc, col);
|
||||
}, async () => {
|
||||
const doc = await vscode.workspace.openTextDocument(configFile.with({ scheme: 'untitled' }));
|
||||
const editor = await vscode.window.showTextDocument(doc, col);
|
||||
if (editor.document.getText().length === 0) {
|
||||
await editor.insertSnippet(getEmptyConfig(isTypeScriptProject, config));
|
||||
}
|
||||
return editor;
|
||||
});
|
||||
try {
|
||||
const doc = await vscode.workspace.openTextDocument(configFile);
|
||||
return vscode.window.showTextDocument(doc, col);
|
||||
} catch {
|
||||
const doc = await vscode.workspace.openTextDocument(configFile.with({ scheme: 'untitled' }));
|
||||
const editor = await vscode.window.showTextDocument(doc, col);
|
||||
if (editor.document.getText().length === 0) {
|
||||
await editor.insertSnippet(getEmptyConfig(isTypeScriptProject, config));
|
||||
}
|
||||
return editor;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import 'mocha';
|
||||
import * as assert from 'assert';
|
||||
import { join } from 'path';
|
||||
import { commands, workspace, window, Uri, ViewColumn, Range, Position } from 'vscode';
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'mocha';
|
||||
import * as assert from 'assert';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
|
||||
@@ -78,12 +78,12 @@ suite('languages namespace tests', () => {
|
||||
});
|
||||
|
||||
return workspace.openTextDocument(uri).then(doc => {
|
||||
return commands.executeCommand('vscode.executeCompletionItemProvider', uri, new Position(1, 0));
|
||||
}).then((result: CompletionList) => {
|
||||
return commands.executeCommand<CompletionList>('vscode.executeCompletionItemProvider', uri, new Position(1, 0));
|
||||
}).then((result: CompletionList | undefined) => {
|
||||
r1.dispose();
|
||||
assert.ok(ran);
|
||||
console.log(result.items);
|
||||
assert.equal(result.items[0].label, 'foo');
|
||||
console.log(result!.items);
|
||||
assert.equal(result!.items[0].label, 'foo');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,5 +4,4 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/// <reference path="../../../../src/vs/vscode.d.ts" />
|
||||
/// <reference types='@types/mocha'/>
|
||||
/// <reference types='@types/node'/>
|
||||
|
||||
@@ -350,7 +350,7 @@ suite('window namespace tests', () => {
|
||||
});
|
||||
|
||||
test('showWorkspaceFolderPick', function () {
|
||||
const p = (<any>window).showWorkspaceFolderPick(undefined);
|
||||
const p = window.showWorkspaceFolderPick(undefined);
|
||||
|
||||
return commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem').then(() => {
|
||||
return p.then(workspace => {
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
"module": "commonjs",
|
||||
"target": "ES5",
|
||||
"outDir": "out",
|
||||
"noUnusedLocals": true,
|
||||
"lib": [
|
||||
"es2015"
|
||||
],
|
||||
"sourceMap": true,
|
||||
"strictNullChecks": true
|
||||
"strict": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import 'mocha';
|
||||
import * as assert from 'assert';
|
||||
import { commands, Uri } from 'vscode';
|
||||
import { join, basename, normalize, dirname } from 'path';
|
||||
|
||||
@@ -3,5 +3,4 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/// <reference types='@types/mocha'/>
|
||||
/// <reference types='@types/node'/>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"module": "commonjs",
|
||||
"target": "ES5",
|
||||
"outDir": "out",
|
||||
"noUnusedLocals": true,
|
||||
"lib": [
|
||||
"es2015"
|
||||
],
|
||||
|
||||
Generated
+1
-1
@@ -591,7 +591,7 @@
|
||||
"xterm": {
|
||||
"version": "2.9.1",
|
||||
"from": "Tyriar/xterm.js#vscode-release/1.19",
|
||||
"resolved": "git+https://github.com/Tyriar/xterm.js.git#004d47b7255f0d5eea4093e6a336a2da3157bc8d"
|
||||
"resolved": "git+https://github.com/Tyriar/xterm.js.git#d242c552cb5c88125ac257ccaebed7fe336d9266"
|
||||
},
|
||||
"yauzl": {
|
||||
"version": "2.8.0",
|
||||
|
||||
+2
-2
@@ -85,7 +85,7 @@
|
||||
"gulp-shell": "^0.5.2",
|
||||
"gulp-sourcemaps": "^1.11.0",
|
||||
"gulp-tsb": "2.0.4",
|
||||
"gulp-tslint": "^7.0.1",
|
||||
"gulp-tslint": "^8.1.2",
|
||||
"gulp-uglify": "^3.0.0",
|
||||
"gulp-util": "^3.0.6",
|
||||
"gulp-vinyl-zip": "^1.2.2",
|
||||
@@ -107,7 +107,7 @@
|
||||
"rimraf": "^2.2.8",
|
||||
"sinon": "^1.17.2",
|
||||
"source-map": "^0.4.4",
|
||||
"tslint": "^4.3.1",
|
||||
"tslint": "^5.8.0",
|
||||
"typescript": "2.6.1",
|
||||
"typescript-formatter": "4.0.1",
|
||||
"uglify-es": "^3.0.18",
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
"experimentalDecorators": true,
|
||||
"declaration": true,
|
||||
"noImplicitReturns": true,
|
||||
"noUnusedLocals": true,
|
||||
"noImplicitThis": true,
|
||||
"baseUrl": ".",
|
||||
"typeRoots": [
|
||||
"typings"
|
||||
|
||||
@@ -559,9 +559,9 @@ export class Builder implements IDisposable {
|
||||
/**
|
||||
* Registers listener on event types on the current element.
|
||||
*/
|
||||
public on(type: string, fn: (e: Event, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder;
|
||||
public on(typeArray: string[], fn: (e: Event, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder;
|
||||
public on(arg1: any, fn: (e: Event, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder {
|
||||
public on<E extends Event = Event>(type: string, fn: (e: E, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder;
|
||||
public on<E extends Event = Event>(typeArray: string[], fn: (e: E, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder;
|
||||
public on<E extends Event = Event>(arg1: any, fn: (e: E, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder {
|
||||
|
||||
// Event Type Array
|
||||
if (types.isArray(arg1)) {
|
||||
@@ -575,7 +575,7 @@ export class Builder implements IDisposable {
|
||||
let type = arg1;
|
||||
|
||||
// Add Listener
|
||||
let unbind: IDisposable = DOM.addDisposableListener(this.currentElement, type, (e: Event) => {
|
||||
let unbind: IDisposable = DOM.addDisposableListener(this.currentElement, type, (e) => {
|
||||
fn(e, this, unbind); // Pass in Builder as Second Argument
|
||||
}, useCapture || false);
|
||||
|
||||
@@ -641,9 +641,9 @@ export class Builder implements IDisposable {
|
||||
* Registers listener on event types on the current element and removes
|
||||
* them after first invocation.
|
||||
*/
|
||||
public once(type: string, fn: (e: Event, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder;
|
||||
public once(typesArray: string[], fn: (e: Event, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder;
|
||||
public once(arg1: any, fn: (e: Event, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder {
|
||||
public once<E extends Event = Event>(type: string, fn: (e: E, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder;
|
||||
public once<E extends Event = Event>(typesArray: string[], fn: (e: E, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder;
|
||||
public once<E extends Event = Event>(arg1: any, fn: (e: E, builder: Builder, unbind: IDisposable) => void, listenerToUnbindContainer?: IDisposable[], useCapture?: boolean): Builder {
|
||||
|
||||
// Event Type Array
|
||||
if (types.isArray(arg1)) {
|
||||
@@ -657,7 +657,7 @@ export class Builder implements IDisposable {
|
||||
let type = arg1;
|
||||
|
||||
// Add Listener
|
||||
let unbind: IDisposable = DOM.addDisposableListener(this.currentElement, type, (e: Event) => {
|
||||
let unbind: IDisposable = DOM.addDisposableListener(this.currentElement, type, (e) => {
|
||||
fn(e, this, unbind); // Pass in Builder as Second Argument
|
||||
unbind.dispose();
|
||||
}, useCapture || false);
|
||||
|
||||
@@ -413,18 +413,18 @@ class AnimationFrameQueueItem implements IDisposable {
|
||||
/**
|
||||
* Add a throttled listener. `handler` is fired at most every 16ms or with the next animation frame (if browser supports it).
|
||||
*/
|
||||
export interface IEventMerger<R> {
|
||||
(lastEvent: R, currentEvent: Event): R;
|
||||
export interface IEventMerger<R, E> {
|
||||
(lastEvent: R, currentEvent: E): R;
|
||||
}
|
||||
|
||||
const MINIMUM_TIME_MS = 16;
|
||||
const DEFAULT_EVENT_MERGER: IEventMerger<Event> = function (lastEvent: Event, currentEvent: Event) {
|
||||
const DEFAULT_EVENT_MERGER: IEventMerger<Event, Event> = function (lastEvent: Event, currentEvent: Event) {
|
||||
return currentEvent;
|
||||
};
|
||||
|
||||
class TimeoutThrottledDomListener<R> extends Disposable {
|
||||
class TimeoutThrottledDomListener<R, E extends Event> extends Disposable {
|
||||
|
||||
constructor(node: any, type: string, handler: (event: R) => void, eventMerger: IEventMerger<R> = <any>DEFAULT_EVENT_MERGER, minimumTimeMs: number = MINIMUM_TIME_MS) {
|
||||
constructor(node: any, type: string, handler: (event: R) => void, eventMerger: IEventMerger<R, E> = <any>DEFAULT_EVENT_MERGER, minimumTimeMs: number = MINIMUM_TIME_MS) {
|
||||
super();
|
||||
|
||||
let lastEvent: R = null;
|
||||
@@ -452,8 +452,8 @@ class TimeoutThrottledDomListener<R> extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
export function addDisposableThrottledListener<R>(node: any, type: string, handler: (event: R) => void, eventMerger?: IEventMerger<R>, minimumTimeMs?: number): IDisposable {
|
||||
return new TimeoutThrottledDomListener<R>(node, type, handler, eventMerger, minimumTimeMs);
|
||||
export function addDisposableThrottledListener<R, E extends Event = Event>(node: any, type: string, handler: (event: R) => void, eventMerger?: IEventMerger<R, E>, minimumTimeMs?: number): IDisposable {
|
||||
return new TimeoutThrottledDomListener<R, E>(node, type, handler, eventMerger, minimumTimeMs);
|
||||
}
|
||||
|
||||
export function getComputedStyle(el: HTMLElement): CSSStyleDeclaration {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user