Merge branch 'master' into refactor_findallrefs

This commit is contained in:
Andy Hanson 2017-03-17 08:04:04 -07:00
commit ec558b8080
485 changed files with 17272 additions and 3009 deletions

View File

@ -391,7 +391,7 @@ gulp.task(builtLocalCompiler, false, [servicesFile], () => {
.pipe(localCompilerProject())
.pipe(prependCopyright())
.pipe(sourcemaps.write("."))
.pipe(gulp.dest("."));
.pipe(gulp.dest("src/compiler"));
});
gulp.task(servicesFile, false, ["lib", "generate-diagnostics"], () => {
@ -417,13 +417,13 @@ gulp.task(servicesFile, false, ["lib", "generate-diagnostics"], () => {
file.path = nodeDefinitionsFile;
return content + "\r\nexport = ts;";
}))
.pipe(gulp.dest(".")),
.pipe(gulp.dest("src/services")),
completedDts.pipe(clone())
.pipe(insert.transform((content, file) => {
file.path = nodeStandaloneDefinitionsFile;
return content.replace(/declare (namespace|module) ts/g, 'declare module "typescript"');
}))
]).pipe(gulp.dest("."));
]).pipe(gulp.dest("src/services"));
});
// cancellationToken.js
@ -449,7 +449,7 @@ gulp.task(typingsInstallerJs, false, [servicesFile], () => {
.pipe(cancellationTokenProject())
.pipe(prependCopyright())
.pipe(sourcemaps.write("."))
.pipe(gulp.dest("."));
.pipe(gulp.dest("src/server/typingsInstaller"));
});
const serverFile = path.join(builtLocalDirectory, "tsserver.js");
@ -462,7 +462,7 @@ gulp.task(serverFile, false, [servicesFile, typingsInstallerJs, cancellationToke
.pipe(serverProject())
.pipe(prependCopyright())
.pipe(sourcemaps.write("."))
.pipe(gulp.dest("."));
.pipe(gulp.dest("src/server"));
});
const tsserverLibraryFile = path.join(builtLocalDirectory, "tsserverlibrary.js");
@ -478,12 +478,12 @@ gulp.task(tsserverLibraryFile, false, [servicesFile], (done) => {
return merge2([
js.pipe(prependCopyright())
.pipe(sourcemaps.write("."))
.pipe(gulp.dest(".")),
.pipe(gulp.dest("src/server")),
dts.pipe(prependCopyright(/*outputCopyright*/true))
.pipe(insert.transform((content) => {
return content + "\r\nexport = ts;\r\nexport as namespace ts;";
}))
.pipe(gulp.dest("."))
.pipe(gulp.dest("src/server"))
]);
});
@ -557,7 +557,7 @@ gulp.task(run, false, [servicesFile], () => {
.pipe(sourcemaps.init())
.pipe(testProject())
.pipe(sourcemaps.write(".", { includeContent: false, sourceRoot: "../../" }))
.pipe(gulp.dest("."));
.pipe(gulp.dest("src/harness"));
});
const internalTests = "internal/";
@ -779,7 +779,7 @@ gulp.task("browserify", "Runs browserify on run.js to produce a file suitable fo
});
}))
.pipe(sourcemaps.write(".", { includeContent: false }))
.pipe(gulp.dest("."));
.pipe(gulp.dest("src/harness"));
});
@ -961,7 +961,7 @@ gulp.task("update-sublime", "Updates the sublime plugin's tsserver", ["local", s
});
gulp.task("build-rules", "Compiles tslint rules to js", () => {
const settings: tsc.Settings = getCompilerSettings({ module: "commonjs" }, /*useBuiltCompiler*/ false);
const settings: tsc.Settings = getCompilerSettings({ module: "commonjs", "lib": ["es6"] }, /*useBuiltCompiler*/ false);
const dest = path.join(builtLocalDirectory, "tslint");
return gulp.src("scripts/tslint/**/*.ts")
.pipe(newer({

View File

@ -11,11 +11,7 @@ var ts = require("./lib/typescript");
// Variables
var compilerDirectory = "src/compiler/";
var servicesDirectory = "src/services/";
var serverDirectory = "src/server/";
var typingsInstallerDirectory = "src/server/typingsInstaller";
var cancellationTokenDirectory = "src/server/cancellationToken";
var watchGuardDirectory = "src/server/watchGuard";
var harnessDirectory = "src/harness/";
var libraryDirectory = "src/lib/";
var scriptsDirectory = "scripts/";
@ -131,6 +127,7 @@ var harnessSources = harnessCoreSources.concat([
"matchFiles.ts",
"initializeTSConfig.ts",
"printer.ts",
"textChanges.ts",
"transform.ts",
"customTransforms.ts",
].map(function (f) {
@ -328,8 +325,14 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts
if (opts.stripInternal) {
options += " --stripInternal";
}
options += " --target es5 --lib es5,scripthost --noUnusedLocals --noUnusedParameters";
options += " --target es5";
if (opts.lib) {
options += " --lib " + opts.lib
}
else {
options += " --lib es5"
}
options += " --noUnusedLocals --noUnusedParameters";
var cmd = host + " " + compilerPath + " " + options + " ";
cmd = cmd + sources.join(" ");
@ -416,7 +419,7 @@ compileFile(buildProtocolJs,
[buildProtocolTs],
[],
/*useBuiltCompiler*/ false,
{noOutFile: true});
{ noOutFile: true, lib: "es6" });
file(buildProtocolDts, [buildProtocolTs, buildProtocolJs, typescriptServicesDts], function() {
@ -578,16 +581,16 @@ compileFile(
file(typescriptServicesDts, [servicesFile]);
var cancellationTokenFile = path.join(builtLocalDirectory, "cancellationToken.js");
compileFile(cancellationTokenFile, cancellationTokenSources, [builtLocalDirectory].concat(cancellationTokenSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { outDir: builtLocalDirectory, noOutFile: true });
compileFile(cancellationTokenFile, cancellationTokenSources, [builtLocalDirectory].concat(cancellationTokenSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], outDir: builtLocalDirectory, noOutFile: true, lib: "es6" });
var typingsInstallerFile = path.join(builtLocalDirectory, "typingsInstaller.js");
compileFile(typingsInstallerFile, typingsInstallerSources, [builtLocalDirectory].concat(typingsInstallerSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { outDir: builtLocalDirectory, noOutFile: false });
compileFile(typingsInstallerFile, typingsInstallerSources, [builtLocalDirectory].concat(typingsInstallerSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], outDir: builtLocalDirectory, noOutFile: false, lib: "es6" });
var watchGuardFile = path.join(builtLocalDirectory, "watchGuard.js");
compileFile(watchGuardFile, watchGuardSources, [builtLocalDirectory].concat(watchGuardSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { outDir: builtLocalDirectory, noOutFile: false });
compileFile(watchGuardFile, watchGuardSources, [builtLocalDirectory].concat(watchGuardSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], outDir: builtLocalDirectory, noOutFile: false, lib: "es6" });
var serverFile = path.join(builtLocalDirectory, "tsserver.js");
compileFile(serverFile, serverSources, [builtLocalDirectory, copyright, cancellationTokenFile, typingsInstallerFile, watchGuardFile].concat(serverSources).concat(servicesSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], preserveConstEnums: true });
compileFile(serverFile, serverSources, [builtLocalDirectory, copyright, cancellationTokenFile, typingsInstallerFile, watchGuardFile].concat(serverSources).concat(servicesSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], preserveConstEnums: true, lib: "es6" });
var tsserverLibraryFile = path.join(builtLocalDirectory, "tsserverlibrary.js");
var tsserverLibraryDefinitionFile = path.join(builtLocalDirectory, "tsserverlibrary.d.ts");
compileFile(
@ -711,7 +714,7 @@ compileFile(
/*prereqs*/[builtLocalDirectory, tscFile].concat(libraryTargets).concat(servicesSources).concat(harnessSources),
/*prefixes*/[],
/*useBuiltCompiler:*/ true,
/*opts*/ { inlineSourceMap: true, types: ["node", "mocha", "chai"] });
/*opts*/ { inlineSourceMap: true, types: ["node", "mocha", "chai"], lib: "es6" });
var internalTests = "internal/";
@ -1098,7 +1101,8 @@ var tslintRules = [
"noInOperatorRule",
"noIncrementDecrementRule",
"objectLiteralSurroundingSpaceRule",
"noTypeAssertionWhitespaceRule"
"noTypeAssertionWhitespaceRule",
"noBomRule"
];
var tslintRulesFiles = tslintRules.map(function (p) {
return path.join(tslintRuleDir, p + ".ts");
@ -1110,7 +1114,7 @@ desc("Compiles tslint rules to js");
task("build-rules", ["build-rules-start"].concat(tslintRulesOutFiles).concat(["build-rules-end"]));
tslintRulesFiles.forEach(function (ruleFile, i) {
compileFile(tslintRulesOutFiles[i], [ruleFile], [ruleFile], [], /*useBuiltCompiler*/ false,
{ noOutFile: true, generateDeclarations: false, outDir: path.join(builtLocalDirectory, "tslint") });
{ noOutFile: true, generateDeclarations: false, outDir: path.join(builtLocalDirectory, "tslint"), lib: "es6" });
});
desc("Emit the start of the build-rules fold");

View File

@ -39,8 +39,8 @@ with any additional questions or comments.
## Documentation
* [Quick tutorial](http://www.typescriptlang.org/Tutorial)
* [Programming handbook](http://www.typescriptlang.org/Handbook)
* [Quick tutorial](http://www.typescriptlang.org/docs/tutorial.html)
* [Programming handbook](http://www.typescriptlang.org/docs/handbook/basic-types.html)
* [Language specification](https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md)
* [Homepage](http://www.typescriptlang.org/)
@ -95,4 +95,4 @@ node built/local/tsc.js hello.ts
## Roadmap
For details on our planned features and future direction please refer to our [roadmap](https://github.com/Microsoft/TypeScript/wiki/Roadmap).
For details on our planned features and future direction please refer to our [roadmap](https://github.com/Microsoft/TypeScript/wiki/Roadmap).

View File

@ -2,7 +2,7 @@
<!-- QUESTIONS: This is not a general support forum! Ask Qs at http://stackoverflow.com/questions/tagged/typescript -->
<!-- SUGGESTIONS: See https://github.com/Microsoft/TypeScript-wiki/blob/master/Writing-Good-Design-Proposals.md -->
**TypeScript Version:** 2.1.1 / nightly (2.2.0-dev.201xxxxx)
**TypeScript Version:** 2.2.1 / nightly (2.2.0-dev.201xxxxx)
**Code**

1
lib/protocol.d.ts vendored
View File

@ -1742,6 +1742,7 @@ declare namespace ts.server.protocol {
insertSpaceAfterFunctionKeywordForAnonymousFunctions?: boolean;
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis?: boolean;
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets?: boolean;
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces?: boolean;
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces?: boolean;
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces?: boolean;
insertSpaceBeforeFunctionParenthesis?: boolean;

View File

@ -1,5 +1,6 @@
var tslint = require("tslint");
var fs = require("fs");
var path = require("path");
function getLinterOptions() {
return {
@ -9,7 +10,7 @@ function getLinterOptions() {
};
}
function getLinterConfiguration() {
return require("../tslint.json");
return tslint.Configuration.loadConfigurationFromPath(path.join(__dirname, "../tslint.json"));
}
function lintFileContents(options, configuration, path, contents) {

View File

@ -2,52 +2,62 @@ import * as Lint from "tslint/lib";
import * as ts from "typescript";
export class Rule extends Lint.Rules.AbstractRule {
public static FAILURE_STRING_FACTORY = (name: string, currently: string) => `Tag boolean argument as '${name}' (currently '${currently}')`;
public static FAILURE_STRING_FACTORY(name: string, currently?: string): string {
const current = currently ? ` (currently '${currently}')` : "";
return `Tag boolean argument as '${name}'${current}`;
}
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
// Cheat to get type checker
const program = ts.createProgram([sourceFile.fileName], Lint.createCompilerOptions());
const checker = program.getTypeChecker();
return this.applyWithWalker(new BooleanTriviaWalker(checker, program.getSourceFile(sourceFile.fileName), this.getOptions()));
return this.applyWithFunction(program.getSourceFile(sourceFile.fileName), ctx => walk(ctx, checker));
}
}
class BooleanTriviaWalker extends Lint.RuleWalker {
constructor(private checker: ts.TypeChecker, file: ts.SourceFile, opts: Lint.IOptions) {
super(file, opts);
function walk(ctx: Lint.WalkContext<void>, checker: ts.TypeChecker): void {
ts.forEachChild(ctx.sourceFile, recur);
function recur(node: ts.Node): void {
if (node.kind === ts.SyntaxKind.CallExpression) {
checkCall(node as ts.CallExpression);
}
ts.forEachChild(node, recur);
}
visitCallExpression(node: ts.CallExpression) {
super.visitCallExpression(node);
if (node.arguments && node.arguments.some(arg => arg.kind === ts.SyntaxKind.TrueKeyword || arg.kind === ts.SyntaxKind.FalseKeyword)) {
const targetCallSignature = this.checker.getResolvedSignature(node);
if (!!targetCallSignature) {
const targetParameters = targetCallSignature.getParameters();
const source = this.getSourceFile();
for (let index = 0; index < targetParameters.length; index++) {
const param = targetParameters[index];
const arg = node.arguments[index];
if (!(arg && param)) {
continue;
}
function checkCall(node: ts.CallExpression): void {
if (!node.arguments || !node.arguments.some(arg => arg.kind === ts.SyntaxKind.TrueKeyword || arg.kind === ts.SyntaxKind.FalseKeyword)) {
return;
}
const argType = this.checker.getContextualType(arg);
if (argType && (argType.getFlags() & ts.TypeFlags.Boolean)) {
if (arg.kind !== ts.SyntaxKind.TrueKeyword && arg.kind !== ts.SyntaxKind.FalseKeyword) {
continue;
}
let triviaContent: string;
const ranges = ts.getLeadingCommentRanges(arg.getFullText(), 0);
if (ranges && ranges.length === 1 && ranges[0].kind === ts.SyntaxKind.MultiLineCommentTrivia) {
triviaContent = arg.getFullText().slice(ranges[0].pos + 2, ranges[0].end - 2); // +/-2 to remove /**/
}
const targetCallSignature = checker.getResolvedSignature(node);
if (!targetCallSignature) {
return;
}
const paramName = param.getName();
if (triviaContent !== paramName && triviaContent !== paramName + ":") {
this.addFailure(this.createFailure(arg.getStart(source), arg.getWidth(source), Rule.FAILURE_STRING_FACTORY(param.getName(), triviaContent)));
}
}
const targetParameters = targetCallSignature.getParameters();
for (let index = 0; index < targetParameters.length; index++) {
const param = targetParameters[index];
const arg = node.arguments[index];
if (!(arg && param)) {
continue;
}
const argType = checker.getContextualType(arg);
if (argType && (argType.getFlags() & ts.TypeFlags.Boolean)) {
if (arg.kind !== ts.SyntaxKind.TrueKeyword && arg.kind !== ts.SyntaxKind.FalseKeyword) {
continue;
}
let triviaContent: string | undefined;
const ranges = ts.getLeadingCommentRanges(arg.getFullText(), 0);
if (ranges && ranges.length === 1 && ranges[0].kind === ts.SyntaxKind.MultiLineCommentTrivia) {
triviaContent = arg.getFullText().slice(ranges[0].pos + 2, ranges[0].end - 2); // +/-2 to remove /**/
}
const paramName = param.getName();
if (triviaContent !== paramName && triviaContent !== paramName + ":") {
ctx.addFailureAtNode(arg, Rule.FAILURE_STRING_FACTORY(param.getName(), triviaContent));
}
}
}
}
}
}

View File

@ -9,50 +9,56 @@ export class Rule extends Lint.Rules.AbstractRule {
public static ELSE_FAILURE_STRING = "'else' should not be on the same line as the preceeding block's curly brace";
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(new NextLineWalker(sourceFile, this.getOptions()));
const options = this.getOptions().ruleArguments;
const checkCatch = options.indexOf(OPTION_CATCH) !== -1;
const checkElse = options.indexOf(OPTION_ELSE) !== -1;
return this.applyWithFunction(sourceFile, ctx => walk(ctx, checkCatch, checkElse));
}
}
class NextLineWalker extends Lint.RuleWalker {
public visitIfStatement(node: ts.IfStatement) {
const sourceFile = node.getSourceFile();
const thenStatement = node.thenStatement;
const elseStatement = node.elseStatement;
if (!!elseStatement) {
// find the else keyword
const elseKeyword = getFirstChildOfKind(node, ts.SyntaxKind.ElseKeyword);
if (this.hasOption(OPTION_ELSE) && !!elseKeyword) {
const thenStatementEndLoc = sourceFile.getLineAndCharacterOfPosition(thenStatement.getEnd());
const elseKeywordLoc = sourceFile.getLineAndCharacterOfPosition(elseKeyword.getStart(sourceFile));
if (thenStatementEndLoc.line === elseKeywordLoc.line) {
const failure = this.createFailure(elseKeyword.getStart(sourceFile), elseKeyword.getWidth(sourceFile), Rule.ELSE_FAILURE_STRING);
this.addFailure(failure);
}
}
function walk(ctx: Lint.WalkContext<void>, checkCatch: boolean, checkElse: boolean): void {
const { sourceFile } = ctx;
function recur(node: ts.Node): void {
switch (node.kind) {
case ts.SyntaxKind.IfStatement:
checkIf(node as ts.IfStatement);
break;
case ts.SyntaxKind.TryStatement:
checkTry(node as ts.TryStatement);
break;
}
super.visitIfStatement(node);
ts.forEachChild(node, recur);
}
public visitTryStatement(node: ts.TryStatement) {
const sourceFile = node.getSourceFile();
const catchClause = node.catchClause;
function checkIf(node: ts.IfStatement): void {
const { thenStatement, elseStatement } = node;
if (!elseStatement) {
return;
}
// "visit" try block
const tryBlock = node.tryBlock;
if (this.hasOption(OPTION_CATCH) && !!catchClause) {
const tryClosingBrace = tryBlock.getLastToken(sourceFile);
const catchKeyword = catchClause.getFirstToken(sourceFile);
const tryClosingBraceLoc = sourceFile.getLineAndCharacterOfPosition(tryClosingBrace.getEnd());
const catchKeywordLoc = sourceFile.getLineAndCharacterOfPosition(catchKeyword.getStart(sourceFile));
if (tryClosingBraceLoc.line === catchKeywordLoc.line) {
const failure = this.createFailure(catchKeyword.getStart(sourceFile), catchKeyword.getWidth(sourceFile), Rule.CATCH_FAILURE_STRING);
this.addFailure(failure);
// find the else keyword
const elseKeyword = getFirstChildOfKind(node, ts.SyntaxKind.ElseKeyword);
if (checkElse && !!elseKeyword) {
const thenStatementEndLoc = sourceFile.getLineAndCharacterOfPosition(thenStatement.getEnd());
const elseKeywordLoc = sourceFile.getLineAndCharacterOfPosition(elseKeyword.getStart(sourceFile));
if (thenStatementEndLoc.line === elseKeywordLoc.line) {
ctx.addFailureAtNode(elseKeyword, Rule.ELSE_FAILURE_STRING);
}
}
super.visitTryStatement(node);
}
function checkTry({ tryBlock, catchClause }: ts.TryStatement): void {
if (!checkCatch || !catchClause) {
return;
}
const tryClosingBrace = tryBlock.getLastToken(sourceFile);
const catchKeyword = catchClause.getFirstToken(sourceFile);
const tryClosingBraceLoc = sourceFile.getLineAndCharacterOfPosition(tryClosingBrace.getEnd());
const catchKeywordLoc = sourceFile.getLineAndCharacterOfPosition(catchKeyword.getStart(sourceFile));
if (tryClosingBraceLoc.line === catchKeywordLoc.line) {
ctx.addFailureAtNode(catchKeyword, Rule.CATCH_FAILURE_STRING);
}
}
}

View File

@ -0,0 +1,16 @@
import * as Lint from "tslint/lib";
import * as ts from "typescript";
export class Rule extends Lint.Rules.AbstractRule {
public static FAILURE_STRING = "This file has a BOM.";
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, walk);
}
}
function walk(ctx: Lint.WalkContext<void>): void {
if (ctx.sourceFile.text[0] === "\ufeff") {
ctx.addFailure(0, 1, Rule.FAILURE_STRING);
}
}

View File

@ -1,20 +1,19 @@
import * as Lint from "tslint/lib";
import * as ts from "typescript";
export class Rule extends Lint.Rules.AbstractRule {
public static FAILURE_STRING = "Don't use the 'in' keyword - use 'hasProperty' to check for key presence instead";
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(new InWalker(sourceFile, this.getOptions()));
return this.applyWithFunction(sourceFile, walk);
}
}
class InWalker extends Lint.RuleWalker {
visitNode(node: ts.Node) {
super.visitNode(node);
if (node.kind === ts.SyntaxKind.InKeyword && node.parent && node.parent.kind === ts.SyntaxKind.BinaryExpression) {
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.FAILURE_STRING));
function walk(ctx: Lint.WalkContext<void>): void {
ts.forEachChild(ctx.sourceFile, recur);
function recur(node: ts.Node): void {
if (node.kind === ts.SyntaxKind.InKeyword && node.parent.kind === ts.SyntaxKind.BinaryExpression) {
ctx.addFailureAtNode(node, Rule.FAILURE_STRING);
}
}
}

View File

@ -1,44 +1,55 @@
import * as Lint from "tslint/lib";
import * as ts from "typescript";
export class Rule extends Lint.Rules.AbstractRule {
public static POSTFIX_FAILURE_STRING = "Don't use '++' or '--' postfix operators outside statements or for loops.";
public static PREFIX_FAILURE_STRING = "Don't use '++' or '--' prefix operators.";
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(new IncrementDecrementWalker(sourceFile, this.getOptions()));
return this.applyWithFunction(sourceFile, walk);
}
}
class IncrementDecrementWalker extends Lint.RuleWalker {
function walk(ctx: Lint.WalkContext<void>): void {
ts.forEachChild(ctx.sourceFile, recur);
function recur(node: ts.Node): void {
switch (node.kind) {
case ts.SyntaxKind.PrefixUnaryExpression:
const { operator } = node as ts.PrefixUnaryExpression;
if (operator === ts.SyntaxKind.PlusPlusToken || operator === ts.SyntaxKind.MinusMinusToken) {
check(node as ts.PrefixUnaryExpression);
}
break;
visitPostfixUnaryExpression(node: ts.PostfixUnaryExpression) {
super.visitPostfixUnaryExpression(node);
if (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator == ts.SyntaxKind.MinusMinusToken) {
this.visitIncrementDecrement(node);
case ts.SyntaxKind.PostfixUnaryExpression:
check(node as ts.PostfixUnaryExpression);
break;
}
}
visitPrefixUnaryExpression(node: ts.PrefixUnaryExpression) {
super.visitPrefixUnaryExpression(node);
if (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator == ts.SyntaxKind.MinusMinusToken) {
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.PREFIX_FAILURE_STRING));
function check(node: ts.UnaryExpression): void {
if (!isAllowedLocation(node.parent!)) {
ctx.addFailureAtNode(node, Rule.POSTFIX_FAILURE_STRING);
}
}
visitIncrementDecrement(node: ts.UnaryExpression) {
if (node.parent && (
// Can be a statement
node.parent.kind === ts.SyntaxKind.ExpressionStatement ||
// Can be directly in a for-statement
node.parent.kind === ts.SyntaxKind.ForStatement ||
// Can be in a comma operator in a for statement (`for (let a = 0, b = 10; a < b; a++, b--)`)
node.parent.kind === ts.SyntaxKind.BinaryExpression &&
(<ts.BinaryExpression>node.parent).operatorToken.kind === ts.SyntaxKind.CommaToken &&
node.parent.parent.kind === ts.SyntaxKind.ForStatement)) {
return;
}
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.POSTFIX_FAILURE_STRING));
}
}
function isAllowedLocation(node: ts.Node): boolean {
switch (node.kind) {
// Can be a statement
case ts.SyntaxKind.ExpressionStatement:
return true;
// Can be directly in a for-statement
case ts.SyntaxKind.ForStatement:
return true;
// Can be in a comma operator in a for statement (`for (let a = 0, b = 10; a < b; a++, b--)`)
case ts.SyntaxKind.BinaryExpression:
return (node as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.CommaToken &&
node.parent!.kind === ts.SyntaxKind.ForStatement;
default:
return false;
}
}

View File

@ -1,25 +1,25 @@
import * as Lint from "tslint/lib";
import * as ts from "typescript";
export class Rule extends Lint.Rules.AbstractRule {
public static TRAILING_FAILURE_STRING = "Excess trailing whitespace found around type assertion.";
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(new TypeAssertionWhitespaceWalker(sourceFile, this.getOptions()));
return this.applyWithFunction(sourceFile, walk);
}
}
class TypeAssertionWhitespaceWalker extends Lint.RuleWalker {
public visitNode(node: ts.Node) {
function walk(ctx: Lint.WalkContext<void>): void {
ts.forEachChild(ctx.sourceFile, recur);
function recur(node: ts.Node) {
if (node.kind === ts.SyntaxKind.TypeAssertionExpression) {
const refined = node as ts.TypeAssertion;
const leftSideWhitespaceStart = refined.type.getEnd() + 1;
const rightSideWhitespaceEnd = refined.expression.getStart();
if (leftSideWhitespaceStart !== rightSideWhitespaceEnd) {
this.addFailure(this.createFailure(leftSideWhitespaceStart, rightSideWhitespaceEnd, Rule.TRAILING_FAILURE_STRING));
ctx.addFailure(leftSideWhitespaceStart, rightSideWhitespaceEnd, Rule.TRAILING_FAILURE_STRING);
}
}
super.visitNode(node);
ts.forEachChild(node, recur);
}
}

View File

@ -1,7 +1,6 @@
import * as Lint from "tslint/lib";
import * as ts from "typescript";
export class Rule extends Lint.Rules.AbstractRule {
public static LEADING_FAILURE_STRING = "No leading whitespace found on single-line object literal.";
public static TRAILING_FAILURE_STRING = "No trailing whitespace found on single-line object literal.";
@ -9,34 +8,37 @@ export class Rule extends Lint.Rules.AbstractRule {
public static TRAILING_EXCESS_FAILURE_STRING = "Excess trailing whitespace found on single-line object literal.";
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(new ObjectLiteralSpaceWalker(sourceFile, this.getOptions()));
return this.applyWithFunction(sourceFile, walk);
}
}
class ObjectLiteralSpaceWalker extends Lint.RuleWalker {
public visitNode(node: ts.Node) {
function walk(ctx: Lint.WalkContext<void>): void {
const { sourceFile } = ctx;
ts.forEachChild(sourceFile, recur);
function recur(node: ts.Node): void {
if (node.kind === ts.SyntaxKind.ObjectLiteralExpression) {
const literal = node as ts.ObjectLiteralExpression;
const text = literal.getText();
if (text.match(/^{[^\n]+}$/g)) {
if (text.charAt(1) !== " ") {
const failure = this.createFailure(node.pos, node.getWidth(), Rule.LEADING_FAILURE_STRING);
this.addFailure(failure);
}
if (text.charAt(2) === " ") {
const failure = this.createFailure(node.pos + 2, 1, Rule.LEADING_EXCESS_FAILURE_STRING);
this.addFailure(failure);
}
if (text.charAt(text.length - 2) !== " ") {
const failure = this.createFailure(node.pos, node.getWidth(), Rule.TRAILING_FAILURE_STRING);
this.addFailure(failure);
}
if (text.charAt(text.length - 3) === " ") {
const failure = this.createFailure(node.pos + node.getWidth() - 3, 1, Rule.TRAILING_EXCESS_FAILURE_STRING);
this.addFailure(failure);
}
}
check(node as ts.ObjectLiteralExpression);
}
ts.forEachChild(node, recur);
}
function check(node: ts.ObjectLiteralExpression): void {
const text = node.getText(sourceFile);
if (!text.match(/^{[^\n]+}$/g)) {
return;
}
if (text.charAt(1) !== " ") {
ctx.addFailureAtNode(node, Rule.LEADING_FAILURE_STRING);
}
if (text.charAt(2) === " ") {
ctx.addFailureAt(node.pos + 2, 1, Rule.LEADING_EXCESS_FAILURE_STRING);
}
if (text.charAt(text.length - 2) !== " ") {
ctx.addFailureAtNode(node, Rule.TRAILING_FAILURE_STRING);
}
if (text.charAt(text.length - 3) === " ") {
ctx.addFailureAt(node.pos + node.getWidth() - 3, 1, Rule.TRAILING_EXCESS_FAILURE_STRING);
}
super.visitNode(node);
}
}

View File

@ -1,6 +1,11 @@
{
"compilerOptions": {
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"strictNullChecks": true,
"module": "commonjs",
"outDir": "../../built/local/tslint"
}

View File

@ -1,34 +1,36 @@
import * as Lint from "tslint/lib";
import * as ts from "typescript";
export class Rule extends Lint.Rules.AbstractRule {
public static FAILURE_STRING = "The '|' and '&' operators must be surrounded by single spaces";
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(new TypeOperatorSpacingWalker(sourceFile, this.getOptions()));
return this.applyWithFunction(sourceFile, walk);
}
}
class TypeOperatorSpacingWalker extends Lint.RuleWalker {
public visitNode(node: ts.Node) {
function walk(ctx: Lint.WalkContext<void>): void {
const { sourceFile } = ctx;
ts.forEachChild(sourceFile, recur);
function recur(node: ts.Node): void {
if (node.kind === ts.SyntaxKind.UnionType || node.kind === ts.SyntaxKind.IntersectionType) {
const types = (<ts.UnionOrIntersectionTypeNode>node).types;
let expectedStart = types[0].end + 2; // space, | or &
for (let i = 1; i < types.length; i++) {
const currentType = types[i];
if (expectedStart !== currentType.pos || currentType.getLeadingTriviaWidth() !== 1) {
const sourceFile = currentType.getSourceFile();
const previousTypeEndPos = sourceFile.getLineAndCharacterOfPosition(types[i - 1].end);
const currentTypeStartPos = sourceFile.getLineAndCharacterOfPosition(currentType.pos);
if (previousTypeEndPos.line === currentTypeStartPos.line) {
const failure = this.createFailure(currentType.pos, currentType.getWidth(), Rule.FAILURE_STRING);
this.addFailure(failure);
}
}
expectedStart = currentType.end + 2;
}
check((node as ts.UnionOrIntersectionTypeNode).types);
}
ts.forEachChild(node, recur);
}
function check(types: ts.TypeNode[]): void {
let expectedStart = types[0].end + 2; // space, | or &
for (let i = 1; i < types.length; i++) {
const currentType = types[i];
if (expectedStart !== currentType.pos || currentType.getLeadingTriviaWidth() !== 1) {
const previousTypeEndPos = sourceFile.getLineAndCharacterOfPosition(types[i - 1].end);
const currentTypeStartPos = sourceFile.getLineAndCharacterOfPosition(currentType.pos);
if (previousTypeEndPos.line === currentTypeStartPos.line) {
ctx.addFailureAtNode(currentType, Rule.FAILURE_STRING);
}
}
expectedStart = currentType.end + 2;
}
super.visitNode(node);
}
}

View File

@ -182,7 +182,7 @@ namespace ts {
return bindSourceFile;
function bindInStrictMode(file: SourceFile, opts: CompilerOptions): boolean {
if (opts.alwaysStrict && !isDeclarationFile(file)) {
if ((opts.alwaysStrict === undefined ? opts.strict : opts.alwaysStrict) && !isDeclarationFile(file)) {
// bind in strict mode source files with alwaysStrict option
return true;
}
@ -1903,7 +1903,7 @@ namespace ts {
// Even though in the AST the jsdoc @typedef node belongs to the current node,
// its symbol might be in the same scope with the current node's symbol. Consider:
//
//
// /** @typedef {string | number} MyType */
// function foo();
//
@ -2289,7 +2289,42 @@ namespace ts {
declareSymbol(file.symbol.exports, file.symbol, <PropertyAccessExpression>node.left, SymbolFlags.Property | SymbolFlags.Export, SymbolFlags.None);
}
function isExportsOrModuleExportsOrAlias(node: Node): boolean {
return isExportsIdentifier(node) ||
isModuleExportsPropertyAccessExpression(node) ||
isNameOfExportsOrModuleExportsAliasDeclaration(node);
}
function isNameOfExportsOrModuleExportsAliasDeclaration(node: Node) {
if (node.kind === SyntaxKind.Identifier) {
const symbol = container.locals.get((<Identifier>node).text);
if (symbol && symbol.valueDeclaration && symbol.valueDeclaration.kind === SyntaxKind.VariableDeclaration) {
const declaration = symbol.valueDeclaration as VariableDeclaration;
if (declaration.initializer) {
return isExportsOrModuleExportsOrAliasOrAssignemnt(declaration.initializer);
}
}
}
return false;
}
function isExportsOrModuleExportsOrAliasOrAssignemnt(node: Node): boolean {
return isExportsOrModuleExportsOrAlias(node) ||
(isAssignmentExpression(node, /*excludeCompoundAssignements*/ true) && (isExportsOrModuleExportsOrAliasOrAssignemnt(node.left) || isExportsOrModuleExportsOrAliasOrAssignemnt(node.right)));
}
function bindModuleExportsAssignment(node: BinaryExpression) {
// A common practice in node modules is to set 'export = module.exports = {}', this ensures that 'exports'
// is still pointing to 'module.exports'.
// We do not want to consider this as 'export=' since a module can have only one of these.
// Similarlly we do not want to treat 'module.exports = exports' as an 'export='.
const assignedExpression = getRightMostAssignedExpression(node.right);
if (isEmptyObjectLiteral(assignedExpression) || isExportsOrModuleExportsOrAlias(assignedExpression)) {
// Mark it as a module in case there are no other exports in the file
setCommonJsModuleIndicator(node);
return;
}
// 'module.exports = expr' assignment
setCommonJsModuleIndicator(node);
declareSymbol(file.symbol.exports, file.symbol, node, SymbolFlags.Property | SymbolFlags.Export | SymbolFlags.ValueModule, SymbolFlags.None);
@ -2297,23 +2332,30 @@ namespace ts {
function bindThisPropertyAssignment(node: BinaryExpression) {
Debug.assert(isInJavaScriptFile(node));
// Declare a 'member' if the container is an ES5 class or ES6 constructor
if (container.kind === SyntaxKind.FunctionDeclaration || container.kind === SyntaxKind.FunctionExpression) {
container.symbol.members = container.symbol.members || createMap<Symbol>();
// It's acceptable for multiple 'this' assignments of the same identifier to occur
declareSymbol(container.symbol.members, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
}
else if (container.kind === SyntaxKind.Constructor) {
// this.foo assignment in a JavaScript class
// Bind this property to the containing class
const saveContainer = container;
container = container.parent;
const symbol = bindPropertyOrMethodOrAccessor(node, SymbolFlags.Property, SymbolFlags.None);
if (symbol) {
// constructor-declared symbols can be overwritten by subsequent method declarations
(symbol as Symbol).isReplaceableByMethod = true;
}
container = saveContainer;
const container = getThisContainer(node, /*includeArrowFunctions*/false);
switch (container.kind) {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
// Declare a 'member' if the container is an ES5 class or ES6 constructor
container.symbol.members = container.symbol.members || createMap<Symbol>();
// It's acceptable for multiple 'this' assignments of the same identifier to occur
declareSymbol(container.symbol.members, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
break;
case SyntaxKind.Constructor:
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
// this.foo assignment in a JavaScript class
// Bind this property to the containing class
const containingClass = container.parent;
const symbol = declareSymbol(hasModifier(container, ModifierFlags.Static) ? containingClass.symbol.exports : containingClass.symbol.members, containingClass.symbol, node, SymbolFlags.Property, SymbolFlags.None);
if (symbol) {
// symbols declared through 'this' property assignements can be overwritten by subsequent method declarations
(symbol as Symbol).isReplaceableByMethod = true;
}
break;
}
}
@ -2346,11 +2388,20 @@ namespace ts {
leftSideOfAssignment.parent = node;
target.parent = leftSideOfAssignment;
bindPropertyAssignment(target.text, leftSideOfAssignment, /*isPrototypeProperty*/ false);
if (isNameOfExportsOrModuleExportsAliasDeclaration(target)) {
// This can be an alias for the 'exports' or 'module.exports' names, e.g.
// var util = module.exports;
// util.property = function ...
bindExportsPropertyAssignment(node);
}
else {
bindPropertyAssignment(target.text, leftSideOfAssignment, /*isPrototypeProperty*/ false);
}
}
function bindPropertyAssignment(functionName: string, propertyAccessExpression: PropertyAccessExpression, isPrototypeProperty: boolean) {
let targetSymbol = container.locals.get(functionName);
if (targetSymbol && isDeclarationOfFunctionOrClassExpression(targetSymbol)) {
targetSymbol = (targetSymbol.valueDeclaration as VariableDeclaration).initializer.symbol;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/// <reference path="sys.ts"/>
/// <reference path="sys.ts"/>
/// <reference path="types.ts"/>
/// <reference path="core.ts"/>
/// <reference path="diagnosticInformationMap.generated.ts"/>
@ -467,6 +467,11 @@ namespace ts {
type: "boolean",
description: Diagnostics.Parse_in_strict_mode_and_emit_use_strict_for_each_source_file
},
{
name: "strict",
type: "boolean",
description: Diagnostics.Enable_all_strict_type_checks
},
{
// A list of plugins to load in the language service
name: "plugins",
@ -520,7 +525,7 @@ namespace ts {
export const defaultInitCompilerOptions: CompilerOptions = {
module: ModuleKind.CommonJS,
target: ScriptTarget.ES5,
noImplicitAny: false,
strict: true,
sourceMap: false,
};

View File

@ -1,4 +1,4 @@
/// <reference path="types.ts"/>
/// <reference path="types.ts"/>
/// <reference path="performance.ts" />
namespace ts {
@ -84,7 +84,7 @@ namespace ts {
this.index++;
return { value: this.selector(this.data, this.keys[index]), done: false };
}
return { value: undefined as never, done: true }
return { value: undefined as never, done: true };
}
}
@ -140,7 +140,7 @@ namespace ts {
action(this.data[key], key);
}
}
}
};
}
export function createFileMap<T>(keyMapper?: (key: string) => string): FileMap<T> {

View File

@ -1164,7 +1164,7 @@ namespace ts {
emitTypeParameters(node.typeParameters);
const baseTypeNode = getClassExtendsHeritageClauseElement(node);
if (baseTypeNode) {
node.name
node.name;
emitHeritageClause(node.name, [baseTypeNode], /*isImplementsList*/ false);
}
emitHeritageClause(node.name, getClassImplementsHeritageClauseElements(node), /*isImplementsList*/ true);

View File

@ -2413,10 +2413,6 @@
"category": "Error",
"code": 5012
},
"Unsupported file encoding.": {
"category": "Error",
"code": 5013
},
"Failed to parse file '{0}': {1}.": {
"category": "Error",
"code": 5014
@ -3045,6 +3041,10 @@
"category": "Message",
"code": 6149
},
"Enable all strict type checks.": {
"category": "Message",
"code": 6150
},
"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",
"code": 7005

View File

@ -1,4 +1,4 @@
/// <reference path="checker.ts" />
/// <reference path="checker.ts" />
/// <reference path="transformer.ts" />
/// <reference path="declarationEmitter.ts" />
/// <reference path="sourcemap.ts" />
@ -199,6 +199,8 @@ namespace ts {
onEmitHelpers,
onSetSourceFile,
substituteNode,
onBeforeEmitNodeArray,
onAfterEmitNodeArray
} = handlers;
const newLine = getNewLineCharacter(printerOptions);
@ -631,6 +633,11 @@ namespace ts {
if (isExpression(node)) {
return pipelineEmitExpression(trySubstituteNode(EmitHint.Expression, node));
}
if (isToken(node)) {
writeTokenText(kind);
return;
}
}
function pipelineEmitExpression(node: Node): void {
@ -819,8 +826,8 @@ namespace ts {
writeIfPresent(node.dotDotDotToken, "...");
emit(node.name);
writeIfPresent(node.questionToken, "?");
emitExpressionWithPrefix(" = ", node.initializer);
emitWithPrefix(": ", node.type);
emitExpressionWithPrefix(" = ", node.initializer);
}
function emitDecorator(decorator: Decorator) {
@ -1553,6 +1560,10 @@ namespace ts {
emitSignatureAndBody(node, emitSignatureHead);
}
function emitBlockCallback(_hint: EmitHint, body: Node): void {
emitBlockFunctionBody(<Block>body);
}
function emitSignatureAndBody(node: FunctionLikeDeclaration, emitSignatureHead: (node: SignatureDeclaration) => void) {
const body = node.body;
if (body) {
@ -1564,12 +1575,22 @@ namespace ts {
if (getEmitFlags(node) & EmitFlags.ReuseTempVariableScope) {
emitSignatureHead(node);
emitBlockFunctionBody(body);
if (onEmitNode) {
onEmitNode(EmitHint.Unspecified, body, emitBlockCallback);
}
else {
emitBlockFunctionBody(body);
}
}
else {
pushNameGenerationScope();
emitSignatureHead(node);
emitBlockFunctionBody(body);
if (onEmitNode) {
onEmitNode(EmitHint.Unspecified, body, emitBlockCallback);
}
else {
emitBlockFunctionBody(body);
}
popNameGenerationScope();
}
@ -2200,6 +2221,10 @@ namespace ts {
write(getOpeningBracket(format));
}
if (onBeforeEmitNodeArray) {
onBeforeEmitNodeArray(children);
}
if (isEmpty) {
// Write a line terminator if the parent node was multi-line
if (format & ListFormat.MultiLine) {
@ -2315,6 +2340,10 @@ namespace ts {
}
}
if (onAfterEmitNodeArray) {
onAfterEmitNodeArray(children);
}
if (format & ListFormat.BracketsMask) {
write(getClosingBracket(format));
}

View File

@ -1,4 +1,4 @@
/// <reference path="core.ts"/>
/// <reference path="core.ts"/>
/// <reference path="utilities.ts"/>
namespace ts {
@ -1099,6 +1099,10 @@ namespace ts {
: node;
}
export function createKeywordTypeNode(kind: KeywordTypeNode["kind"]): KeywordTypeNode {
return <KeywordTypeNode>createSynthesizedNode(kind);
}
export function createFunctionDeclaration(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) {
const node = <FunctionDeclaration>createSynthesizedNode(SyntaxKind.FunctionDeclaration);
node.decorators = asNodeArray(decorators);

View File

@ -675,7 +675,7 @@ namespace ts {
}
export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations {
return nodeModuleNameResolverWorker(moduleName, containingFile, compilerOptions, host, cache, /* jsOnly*/ false);
return nodeModuleNameResolverWorker(moduleName, containingFile, compilerOptions, host, cache, /*jsOnly*/ false);
}
/* @internal */
@ -962,7 +962,7 @@ namespace ts {
const result = cache && cache.get(containingDirectory);
if (result) {
if (traceEnabled) {
trace(host, Diagnostics.Resolution_for_module_0_was_found_in_cache, moduleName)
trace(host, Diagnostics.Resolution_for_module_0_was_found_in_cache, moduleName);
}
return { value: result.resolvedModule && { path: result.resolvedModule.resolvedFileName, extension: result.resolvedModule.extension } };
}

View File

@ -87,9 +87,6 @@ namespace ts {
return sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
}
// returned by CScript sys environment
const unsupportedFileEncodingErrorCode = -2147024809;
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile {
let text: string;
try {
@ -100,9 +97,7 @@ namespace ts {
}
catch (e) {
if (onError) {
onError(e.number === unsupportedFileEncodingErrorCode
? createCompilerDiagnostic(Diagnostics.Unsupported_file_encoding).messageText
: e.message);
onError(e.message);
}
text = "";
}
@ -290,6 +285,11 @@ namespace ts {
return resolutions;
}
interface DiagnosticCache {
perFile?: FileMap<Diagnostic[]>;
allDiagnostics?: Diagnostic[];
}
export function createProgram(rootNames: string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program): Program {
let program: Program;
let files: SourceFile[] = [];
@ -298,6 +298,9 @@ namespace ts {
let noDiagnosticsTypeChecker: TypeChecker;
let classifiableNames: Map<string>;
let cachedSemanticDiagnosticsForFile: DiagnosticCache = {};
let cachedDeclarationDiagnosticsForFile: DiagnosticCache = {};
let resolvedTypeReferenceDirectives = createMap<ResolvedTypeReferenceDirective>();
let fileProcessingDiagnostics = createDiagnosticCollection();
@ -899,6 +902,10 @@ namespace ts {
}
function getSemanticDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
return getAndCacheDiagnostics(sourceFile, cancellationToken, cachedSemanticDiagnosticsForFile, getSemanticDiagnosticsForFileNoCache);
}
function getSemanticDiagnosticsForFileNoCache(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
return runWithCancellationToken(() => {
const typeChecker = getDiagnosticsProducingTypeChecker();
@ -1094,7 +1101,11 @@ namespace ts {
});
}
function getDeclarationDiagnosticsWorker(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
function getDeclarationDiagnosticsWorker(sourceFile: SourceFile | undefined, cancellationToken: CancellationToken): Diagnostic[] {
return getAndCacheDiagnostics(sourceFile, cancellationToken, cachedDeclarationDiagnosticsForFile, getDeclarationDiagnosticsForFileNoCache);
}
function getDeclarationDiagnosticsForFileNoCache(sourceFile: SourceFile| undefined, cancellationToken: CancellationToken) {
return runWithCancellationToken(() => {
const resolver = getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile, cancellationToken);
// Don't actually write any files since we're just getting diagnostics.
@ -1102,6 +1113,32 @@ namespace ts {
});
}
function getAndCacheDiagnostics(
sourceFile: SourceFile | undefined,
cancellationToken: CancellationToken,
cache: DiagnosticCache,
getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken) => Diagnostic[]) {
const cachedResult = sourceFile
? cache.perFile && cache.perFile.get(sourceFile.path)
: cache.allDiagnostics;
if (cachedResult) {
return cachedResult;
}
const result = getDiagnostics(sourceFile, cancellationToken) || emptyArray;
if (sourceFile) {
if (!cache.perFile) {
cache.perFile = createFileMap<Diagnostic[]>();
}
cache.perFile.set(sourceFile.path, result);
}
else {
cache.allDiagnostics = result;
}
return result;
}
function getDeclarationDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
return isDeclarationFile(sourceFile) ? [] : getDeclarationDiagnosticsWorker(sourceFile, cancellationToken);
}
@ -1630,7 +1667,7 @@ namespace ts {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "lib", "noLib"));
}
if (options.noImplicitUseStrict && options.alwaysStrict) {
if (options.noImplicitUseStrict && (options.alwaysStrict === undefined ? options.strict : options.alwaysStrict)) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noImplicitUseStrict", "alwaysStrict"));
}

View File

@ -333,7 +333,7 @@ namespace ts {
}
/* @internal */
export function getLineStarts(sourceFile: SourceFile): number[] {
export function getLineStarts(sourceFile: SourceFileLike): number[] {
return sourceFile.lineMap || (sourceFile.lineMap = computeLineStarts(sourceFile.text));
}

View File

@ -1,4 +1,4 @@
/// <reference path="core.ts"/>
/// <reference path="core.ts"/>
declare function setTimeout(handler: (...args: any[]) => void, timeout: number): any;
declare function clearTimeout(handle: any): void;
@ -74,13 +74,6 @@ namespace ts {
return parseInt(version.substring(1, dot));
}
declare class Enumerator {
public atEnd(): boolean;
public moveNext(): boolean;
public item(): any;
constructor(o: any);
}
declare var ChakraHost: {
args: string[];
currentDirectory: string;
@ -104,152 +97,6 @@ namespace ts {
};
export let sys: System = (function() {
function getWScriptSystem(): System {
const fso = new ActiveXObject("Scripting.FileSystemObject");
const shell = new ActiveXObject("WScript.Shell");
const fileStream = new ActiveXObject("ADODB.Stream");
fileStream.Type = 2 /*text*/;
const binaryStream = new ActiveXObject("ADODB.Stream");
binaryStream.Type = 1 /*binary*/;
const args: string[] = [];
for (let i = 0; i < WScript.Arguments.length; i++) {
args[i] = WScript.Arguments.Item(i);
}
function readFile(fileName: string, encoding?: string): string {
if (!fso.FileExists(fileName)) {
return undefined;
}
fileStream.Open();
try {
if (encoding) {
fileStream.Charset = encoding;
fileStream.LoadFromFile(fileName);
}
else {
// Load file and read the first two bytes into a string with no interpretation
fileStream.Charset = "x-ansi";
fileStream.LoadFromFile(fileName);
const bom = fileStream.ReadText(2) || "";
// Position must be at 0 before encoding can be changed
fileStream.Position = 0;
// [0xFF,0xFE] and [0xFE,0xFF] mean utf-16 (little or big endian), otherwise default to utf-8
fileStream.Charset = bom.length >= 2 && (bom.charCodeAt(0) === 0xFF && bom.charCodeAt(1) === 0xFE || bom.charCodeAt(0) === 0xFE && bom.charCodeAt(1) === 0xFF) ? "unicode" : "utf-8";
}
// ReadText method always strips byte order mark from resulting string
return fileStream.ReadText();
}
catch (e) {
throw e;
}
finally {
fileStream.Close();
}
}
function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void {
fileStream.Open();
binaryStream.Open();
try {
// Write characters in UTF-8 encoding
fileStream.Charset = "utf-8";
fileStream.WriteText(data);
// If we don't want the BOM, then skip it by setting the starting location to 3 (size of BOM).
// If not, start from position 0, as the BOM will be added automatically when charset==utf8.
if (writeByteOrderMark) {
fileStream.Position = 0;
}
else {
fileStream.Position = 3;
}
fileStream.CopyTo(binaryStream);
binaryStream.SaveToFile(fileName, 2 /*overwrite*/);
}
finally {
binaryStream.Close();
fileStream.Close();
}
}
function getNames(collection: any): string[] {
const result: string[] = [];
for (const e = new Enumerator(collection); !e.atEnd(); e.moveNext()) {
result.push(e.item().Name);
}
return result.sort();
}
function getDirectories(path: string): string[] {
const folder = fso.GetFolder(path);
return getNames(folder.subfolders);
}
function getAccessibleFileSystemEntries(path: string): FileSystemEntries {
try {
const folder = fso.GetFolder(path || ".");
const files = getNames(folder.files);
const directories = getNames(folder.subfolders);
return { files, directories };
}
catch (e) {
return { files: [], directories: [] };
}
}
function readDirectory(path: string, extensions?: string[], excludes?: string[], includes?: string[]): string[] {
return matchFiles(path, extensions, excludes, includes, /*useCaseSensitiveFileNames*/ false, shell.CurrentDirectory, getAccessibleFileSystemEntries);
}
const wscriptSystem: System = {
args,
newLine: "\r\n",
useCaseSensitiveFileNames: false,
write(s: string): void {
WScript.StdOut.Write(s);
},
readFile,
writeFile,
resolvePath(path: string): string {
return fso.GetAbsolutePathName(path);
},
fileExists(path: string): boolean {
return fso.FileExists(path);
},
directoryExists(path: string) {
return fso.FolderExists(path);
},
createDirectory(directoryName: string) {
if (!wscriptSystem.directoryExists(directoryName)) {
fso.CreateFolder(directoryName);
}
},
getExecutingFilePath() {
return WScript.ScriptFullName;
},
getCurrentDirectory() {
return shell.CurrentDirectory;
},
getDirectories,
getEnvironmentVariable(name: string) {
return new ActiveXObject("WScript.Shell").ExpandEnvironmentStrings(`%${name}%`);
},
readDirectory,
exit(exitCode?: number): void {
try {
WScript.Quit(exitCode);
}
catch (e) {
}
}
};
return wscriptSystem;
}
function getNodeSystem(): System {
const _fs = require("fs");
const _path = require("path");
@ -646,9 +493,6 @@ namespace ts {
if (typeof ChakraHost !== "undefined") {
sys = getChakraSystem();
}
else if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") {
sys = getWScriptSystem();
}
else if (typeof process !== "undefined" && process.nextTick && !process.browser && typeof require !== "undefined") {
// process and process.nextTick checks if current environment is node-like
// process.browser check excludes webpack and browserify

View File

@ -1,4 +1,4 @@
/// <reference path="visitor.ts" />
/// <reference path="visitor.ts" />
/// <reference path="transformers/ts.ts" />
/// <reference path="transformers/jsx.ts" />
/// <reference path="transformers/esnext.ts" />
@ -121,13 +121,13 @@ namespace ts {
enableEmitNotification,
isSubstitutionEnabled,
isEmitNotificationEnabled,
get onSubstituteNode() { return onSubstituteNode },
get onSubstituteNode() { return onSubstituteNode; },
set onSubstituteNode(value) {
Debug.assert(state < TransformationState.Initialized, "Cannot modify transformation hooks after initialization has completed.");
Debug.assert(value !== undefined, "Value must not be 'undefined'");
onSubstituteNode = value;
},
get onEmitNode() { return onEmitNode },
get onEmitNode() { return onEmitNode; },
set onEmitNode(value) {
Debug.assert(state < TransformationState.Initialized, "Cannot modify transformation hooks after initialization has completed.");
Debug.assert(value !== undefined, "Value must not be 'undefined'");

View File

@ -43,7 +43,7 @@ namespace ts {
let value: Expression;
if (isDestructuringAssignment(node)) {
value = node.right;
while (isEmptyObjectLiteralOrArrayLiteral(node.left)) {
while (isEmptyArrayLiteral(node.left) || isEmptyObjectLiteral(node.left)) {
if (isDestructuringAssignment(value)) {
location = node = value;
value = node.right;

View File

@ -2690,7 +2690,7 @@ namespace ts {
if (loopOutParameters.length) {
copyOutParameters(loopOutParameters, CopyDirection.ToOutParameter, statements);
}
addRange(statements, lexicalEnvironment)
addRange(statements, lexicalEnvironment);
loopBody = createBlock(statements, /*multiline*/ true);
}

View File

@ -1,4 +1,4 @@
/// <reference path="../factory.ts" />
/// <reference path="../factory.ts" />
/// <reference path="../visitor.ts" />
// Transforms generator functions into a compatible ES5 representation with similar runtime

View File

@ -1,4 +1,4 @@
/// <reference path="../../factory.ts" />
/// <reference path="../../factory.ts" />
/// <reference path="../../visitor.ts" />
/// <reference path="../destructuring.ts" />
@ -55,9 +55,7 @@ namespace ts {
* @param node The SourceFile node.
*/
function transformSourceFile(node: SourceFile) {
if (isDeclarationFile(node)
|| !(isExternalModule(node)
|| compilerOptions.isolatedModules)) {
if (isDeclarationFile(node) || !(isExternalModule(node) || compilerOptions.isolatedModules)) {
return node;
}
@ -74,6 +72,14 @@ namespace ts {
return aggregateTransformFlags(updated);
}
function shouldEmitUnderscoreUnderscoreESModule() {
if (!currentModuleInfo.exportEquals && isExternalModule(currentSourceFile)) {
return true;
}
return false;
}
/**
* Transforms a SourceFile into a CommonJS module.
*
@ -85,7 +91,7 @@ namespace ts {
const statements: Statement[] = [];
const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, sourceElementVisitor);
if (!currentModuleInfo.exportEquals) {
if (shouldEmitUnderscoreUnderscoreESModule()) {
append(statements, createUnderscoreUnderscoreESModule());
}
@ -378,7 +384,7 @@ namespace ts {
const statements: Statement[] = [];
const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, sourceElementVisitor);
if (!currentModuleInfo.exportEquals) {
if (shouldEmitUnderscoreUnderscoreESModule()) {
append(statements, createUnderscoreUnderscoreESModule());
}
@ -1152,7 +1158,7 @@ namespace ts {
createIdentifier("__esModule"),
createLiteral(true)
)
)
);
}
else {
statement = createStatement(

View File

@ -1,4 +1,4 @@
/// <reference path="../../factory.ts" />
/// <reference path="../../factory.ts" />
/// <reference path="../../visitor.ts" />
/// <reference path="../destructuring.ts" />

View File

@ -1,4 +1,4 @@
/// <reference path="../factory.ts" />
/// <reference path="../factory.ts" />
/// <reference path="../visitor.ts" />
/// <reference path="./destructuring.ts" />
@ -472,7 +472,8 @@ namespace ts {
}
function visitSourceFile(node: SourceFile) {
const alwaysStrict = compilerOptions.alwaysStrict && !(isExternalModule(node) && moduleKind === ModuleKind.ES2015);
const alwaysStrict = (compilerOptions.alwaysStrict === undefined ? compilerOptions.strict : compilerOptions.alwaysStrict) &&
!(isExternalModule(node) && moduleKind === ModuleKind.ES2015);
return updateSourceFileNode(
node,
visitLexicalEnvironment(node.statements, sourceElementVisitor, context, /*start*/ 0, alwaysStrict));

View File

@ -1,4 +1,4 @@
/// <reference path="program.ts"/>
/// <reference path="program.ts"/>
/// <reference path="commandLineParser.ts"/>
namespace ts {

View File

@ -1,4 +1,4 @@
namespace ts {
namespace ts {
/**
* Type of objects whose values are all of the same type.
* The `in` and `for-in` operators can *not* be safely used,
@ -519,6 +519,8 @@
/* @internal */ localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes)
/* @internal */ flowNode?: FlowNode; // Associated FlowNode (initialized by binding)
/* @internal */ emitNode?: EmitNode; // Associated EmitNode (initialized by transforms)
/* @internal */ contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution
/* @internal */ contextualMapper?: TypeMapper; // Mapper for contextual type
}
export interface NodeArray<T extends Node> extends Array<T>, TextRange {
@ -621,6 +623,7 @@
export interface TypeParameterDeclaration extends Declaration {
kind: SyntaxKind.TypeParameter;
parent?: DeclarationWithTypeParameters;
name: Identifier;
constraint?: TypeNode;
default?: TypeNode;
@ -648,7 +651,7 @@
export interface VariableDeclaration extends Declaration {
kind: SyntaxKind.VariableDeclaration;
parent?: VariableDeclarationList;
parent?: VariableDeclarationList | CatchClause;
name: BindingName; // Declared variable name
type?: TypeNode; // Optional type annotation
initializer?: Expression; // Optional initializer
@ -656,11 +659,13 @@
export interface VariableDeclarationList extends Node {
kind: SyntaxKind.VariableDeclarationList;
parent?: VariableStatement | ForStatement | ForOfStatement | ForInStatement;
declarations: NodeArray<VariableDeclaration>;
}
export interface ParameterDeclaration extends Declaration {
kind: SyntaxKind.Parameter;
parent?: SignatureDeclaration;
dotDotDotToken?: DotDotDotToken; // Present on rest parameter
name: BindingName; // Declared parameter name
questionToken?: QuestionToken; // Present on optional parameter
@ -670,6 +675,7 @@
export interface BindingElement extends Declaration {
kind: SyntaxKind.BindingElement;
parent?: BindingPattern;
propertyName?: PropertyName; // Binding property name (in object binding pattern)
dotDotDotToken?: DotDotDotToken; // Present on rest element (in object binding pattern)
name: BindingName; // Declared binding element name
@ -751,11 +757,13 @@
export interface ObjectBindingPattern extends Node {
kind: SyntaxKind.ObjectBindingPattern;
parent?: VariableDeclaration | ParameterDeclaration | BindingElement;
elements: NodeArray<BindingElement>;
}
export interface ArrayBindingPattern extends Node {
kind: SyntaxKind.ArrayBindingPattern;
parent?: VariableDeclaration | ParameterDeclaration | BindingElement;
elements: NodeArray<ArrayBindingElement>;
}
@ -957,7 +965,6 @@
export interface Expression extends Node {
_expressionBrand: any;
contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution
}
export interface OmittedExpression extends Expression {
@ -1324,14 +1331,17 @@
export interface TemplateHead extends LiteralLikeNode {
kind: SyntaxKind.TemplateHead;
parent?: TemplateExpression;
}
export interface TemplateMiddle extends LiteralLikeNode {
kind: SyntaxKind.TemplateMiddle;
parent?: TemplateSpan;
}
export interface TemplateTail extends LiteralLikeNode {
kind: SyntaxKind.TemplateTail;
parent?: TemplateSpan;
}
export type TemplateLiteral = TemplateExpression | NoSubstitutionTemplateLiteral;
@ -1346,6 +1356,7 @@
// The template literal must have kind TemplateMiddleLiteral or TemplateTailLiteral.
export interface TemplateSpan extends Node {
kind: SyntaxKind.TemplateSpan;
parent?: TemplateExpression;
expression: Expression;
literal: TemplateMiddle | TemplateTail;
}
@ -1433,6 +1444,7 @@
export interface ExpressionWithTypeArguments extends TypeNode {
kind: SyntaxKind.ExpressionWithTypeArguments;
parent?: HeritageClause;
expression: LeftHandSideExpression;
typeArguments?: NodeArray<TypeNode>;
}
@ -1500,6 +1512,7 @@
/// The opening element of a <Tag>...</Tag> JsxElement
export interface JsxOpeningElement extends Expression {
kind: SyntaxKind.JsxOpeningElement;
parent?: JsxElement;
tagName: JsxTagNameExpression;
attributes: JsxAttributes;
}
@ -1513,6 +1526,7 @@
export interface JsxAttribute extends ObjectLiteralElement {
kind: SyntaxKind.JsxAttribute;
parent?: JsxOpeningLikeElement;
name: Identifier;
/// JSX attribute initializers are optional; <X y /> is sugar for <X y={true} />
initializer?: StringLiteral | JsxExpression;
@ -1520,22 +1534,26 @@
export interface JsxSpreadAttribute extends ObjectLiteralElement {
kind: SyntaxKind.JsxSpreadAttribute;
parent?: JsxOpeningLikeElement;
expression: Expression;
}
export interface JsxClosingElement extends Node {
kind: SyntaxKind.JsxClosingElement;
parent?: JsxElement;
tagName: JsxTagNameExpression;
}
export interface JsxExpression extends Expression {
kind: SyntaxKind.JsxExpression;
parent?: JsxElement | JsxAttributeLike;
dotDotDotToken?: Token<SyntaxKind.DotDotDotToken>;
expression?: Expression;
}
export interface JsxText extends Node {
kind: SyntaxKind.JsxText;
parent?: JsxElement;
}
export type JsxChild = JsxText | JsxExpression | JsxElement | JsxSelfClosingElement;
@ -1677,17 +1695,20 @@
export interface CaseBlock extends Node {
kind: SyntaxKind.CaseBlock;
parent?: SwitchStatement;
clauses: NodeArray<CaseOrDefaultClause>;
}
export interface CaseClause extends Node {
kind: SyntaxKind.CaseClause;
parent?: CaseBlock;
expression: Expression;
statements: NodeArray<Statement>;
}
export interface DefaultClause extends Node {
kind: SyntaxKind.DefaultClause;
parent?: CaseBlock;
statements: NodeArray<Statement>;
}
@ -1713,6 +1734,7 @@
export interface CatchClause extends Node {
kind: SyntaxKind.CatchClause;
parent?: TryStatement;
variableDeclaration: VariableDeclaration;
block: Block;
}
@ -1756,6 +1778,7 @@
export interface HeritageClause extends Node {
kind: SyntaxKind.HeritageClause;
parent?: InterfaceDeclaration | ClassDeclaration | ClassExpression;
token: SyntaxKind;
types?: NodeArray<ExpressionWithTypeArguments>;
}
@ -1769,6 +1792,7 @@
export interface EnumMember extends Declaration {
kind: SyntaxKind.EnumMember;
parent?: EnumDeclaration;
// This does include ComputedPropertyName, but the parser will give an error
// if it parses a ComputedPropertyName in an EnumMember
name: PropertyName;
@ -1787,7 +1811,8 @@
export interface ModuleDeclaration extends DeclarationStatement {
kind: SyntaxKind.ModuleDeclaration;
name: Identifier | StringLiteral;
parent?: ModuleBody | SourceFile;
name: ModuleName;
body?: ModuleBody | JSDocNamespaceDeclaration | Identifier;
}
@ -1807,6 +1832,7 @@
export interface ModuleBlock extends Node, Statement {
kind: SyntaxKind.ModuleBlock;
parent?: ModuleDeclaration;
statements: NodeArray<Statement>;
}
@ -1814,6 +1840,7 @@
export interface ImportEqualsDeclaration extends DeclarationStatement {
kind: SyntaxKind.ImportEqualsDeclaration;
parent?: SourceFile | ModuleBlock;
name: Identifier;
// 'EntityName' for an internal module reference, 'ExternalModuleReference' for an external
@ -1824,6 +1851,7 @@
export interface ExternalModuleReference extends Node {
parent: ImportEqualsDeclaration;
kind: SyntaxKind.ExternalModuleReference;
parent?: ImportEqualsDeclaration;
expression?: Expression;
}
@ -1833,6 +1861,7 @@
// ImportClause information is shown at its declaration below.
export interface ImportDeclaration extends Statement {
kind: SyntaxKind.ImportDeclaration;
parent?: SourceFile | ModuleBlock;
importClause?: ImportClause;
/** If this is not a StringLiteral it will be a grammar error. */
moduleSpecifier: Expression;
@ -1848,12 +1877,14 @@
// import d, { a, b as x } from "mod" => name = d, namedBinding: NamedImports = { elements: [{ name: a }, { name: x, propertyName: b}]}
export interface ImportClause extends Declaration {
kind: SyntaxKind.ImportClause;
parent?: ImportDeclaration;
name?: Identifier; // Default binding
namedBindings?: NamedImportBindings;
}
export interface NamespaceImport extends Declaration {
kind: SyntaxKind.NamespaceImport;
parent?: ImportClause;
name: Identifier;
}
@ -1865,6 +1896,7 @@
export interface ExportDeclaration extends DeclarationStatement {
kind: SyntaxKind.ExportDeclaration;
parent?: SourceFile | ModuleBlock;
exportClause?: NamedExports;
/** If this is not a StringLiteral it will be a grammar error. */
moduleSpecifier?: Expression;
@ -1872,12 +1904,14 @@
export interface NamedImports extends Node {
kind: SyntaxKind.NamedImports;
parent?: ImportClause;
elements: NodeArray<ImportSpecifier>;
}
export interface NamedExports extends Node {
parent: ExportDeclaration;
kind: SyntaxKind.NamedExports;
parent?: ExportDeclaration;
elements: NodeArray<ExportSpecifier>;
}
@ -1885,6 +1919,7 @@
export interface ImportSpecifier extends Declaration {
kind: SyntaxKind.ImportSpecifier;
parent?: NamedImports;
propertyName?: Identifier; // Name preceding "as" keyword (or undefined when "as" is absent)
name: Identifier; // Declared name
}
@ -1892,6 +1927,7 @@
export interface ExportSpecifier extends Declaration {
parent: NamedExports;
kind: SyntaxKind.ExportSpecifier;
parent?: NamedExports;
propertyName?: Identifier; // Name preceding "as" keyword (or undefined when "as" is absent)
name: Identifier; // Declared name
}
@ -1900,6 +1936,7 @@
export interface ExportAssignment extends DeclarationStatement {
kind: SyntaxKind.ExportAssignment;
parent?: SourceFile;
isExportEquals?: boolean;
expression: Expression;
}
@ -2173,6 +2210,16 @@
name: string;
}
/* @internal */
/**
* Subset of properties from SourceFile that are used in multiple utility functions
*/
export interface SourceFileLike {
readonly text: string;
lineMap: number[];
}
// Source files are declarations when they are external modules.
export interface SourceFile extends Declaration {
kind: SyntaxKind.SourceFile;
@ -3208,6 +3255,7 @@
mapper?: TypeMapper; // Type mapper for this inference context
failedTypeParameterIndex?: number; // Index of type parameter for which inference failed
// It is optional because in contextual signature instantiation, nothing fails
useAnyForNoInferences?: boolean; // Use any instead of {} for no inferences
}
/* @internal */
@ -3271,7 +3319,7 @@
}
export interface PluginImport {
name: string
name: string;
}
export type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike<string[]> | PluginImport[];
@ -3282,7 +3330,7 @@
allowSyntheticDefaultImports?: boolean;
allowUnreachableCode?: boolean;
allowUnusedLabels?: boolean;
alwaysStrict?: boolean;
alwaysStrict?: boolean; // Always combine with strict property
baseUrl?: string;
charset?: string;
/* @internal */ configFilePath?: string;
@ -3318,9 +3366,9 @@
noEmitOnError?: boolean;
noErrorTruncation?: boolean;
noFallthroughCasesInSwitch?: boolean;
noImplicitAny?: boolean;
noImplicitAny?: boolean; // Always combine with strict property
noImplicitReturns?: boolean;
noImplicitThis?: boolean;
noImplicitThis?: boolean; // Always combine with strict property
noUnusedLocals?: boolean;
noUnusedParameters?: boolean;
noImplicitUseStrict?: boolean;
@ -3343,7 +3391,8 @@
skipDefaultLibCheck?: boolean;
sourceMap?: boolean;
sourceRoot?: string;
strictNullChecks?: boolean;
strict?: boolean;
strictNullChecks?: boolean; // Always combine with strict property
/* @internal */ stripInternal?: boolean;
suppressExcessPropertyErrors?: boolean;
suppressImplicitAnyIndexErrors?: boolean;
@ -4103,6 +4152,8 @@
/*@internal*/ onEmitSourceMapOfPosition?: (pos: number) => void;
/*@internal*/ onEmitHelpers?: (node: Node, writeLines: (text: string) => void) => void;
/*@internal*/ onSetSourceFile?: (node: SourceFile) => void;
/*@internal*/ onBeforeEmitNodeArray?: (nodes: NodeArray<any>) => void;
/*@internal*/ onAfterEmitNodeArray?: (nodes: NodeArray<any>) => void;
}
export interface PrinterOptions {

View File

@ -1,4 +1,4 @@
/// <reference path="sys.ts" />
/// <reference path="sys.ts" />
/* @internal */
namespace ts {
@ -184,7 +184,7 @@ namespace ts {
return false;
}
export function getStartPositionOfLine(line: number, sourceFile: SourceFile): number {
export function getStartPositionOfLine(line: number, sourceFile: SourceFileLike): number {
Debug.assert(line >= 0);
return getLineStarts(sourceFile)[line];
}
@ -204,7 +204,7 @@ namespace ts {
return value !== undefined;
}
export function getEndLinePosition(line: number, sourceFile: SourceFile): number {
export function getEndLinePosition(line: number, sourceFile: SourceFileLike): number {
Debug.assert(line >= 0);
const lineStarts = getLineStarts(sourceFile);
@ -255,7 +255,11 @@ namespace ts {
return !nodeIsMissing(node);
}
export function getTokenPosOfNode(node: Node, sourceFile?: SourceFile, includeJsDoc?: boolean): number {
export function isToken(n: Node): boolean {
return n.kind >= SyntaxKind.FirstToken && n.kind <= SyntaxKind.LastToken;
}
export function getTokenPosOfNode(node: Node, sourceFile?: SourceFileLike, includeJsDoc?: boolean): number {
// With nodes that have no width (i.e. 'Missing' nodes), we actually *don't*
// want to skip trivia because this will launch us forward to the next token.
if (nodeIsMissing(node)) {
@ -289,7 +293,7 @@ namespace ts {
return node.kind >= SyntaxKind.FirstJSDocTagNode && node.kind <= SyntaxKind.LastJSDocTagNode;
}
export function getNonDecoratorTokenPosOfNode(node: Node, sourceFile?: SourceFile): number {
export function getNonDecoratorTokenPosOfNode(node: Node, sourceFile?: SourceFileLike): number {
if (nodeIsMissing(node) || !node.decorators) {
return getTokenPosOfNode(node, sourceFile);
}
@ -435,8 +439,8 @@ namespace ts {
}
/** Given a symbol for a module, checks that it is either an untyped import or a shorthand ambient module. */
export function isShorthandAmbientModuleSymbol(moduleSymbol: Symbol): boolean {
return isShorthandAmbientModule(moduleSymbol.valueDeclaration);
export function isUntypedOrShorthandAmbientModuleSymbol(moduleSymbol: Symbol): boolean {
return !moduleSymbol.declarations || isShorthandAmbientModule(moduleSymbol.valueDeclaration);
}
function isShorthandAmbientModule(node: Node): boolean {
@ -1425,6 +1429,21 @@ namespace ts {
return false;
}
export function getRightMostAssignedExpression(node: Node) {
while (isAssignmentExpression(node, /*excludeCompoundAssignements*/ true)) {
node = node.right;
}
return node;
}
export function isExportsIdentifier(node: Node) {
return isIdentifier(node) && node.text === "exports";
}
export function isModuleExportsPropertyAccessExpression(node: Node) {
return isPropertyAccessExpression(node) && isIdentifier(node.expression) && node.expression.text === "module" && node.name.text === "exports";
}
/// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property
/// assignments we treat as special in the binder
export function getSpecialPropertyAssignmentKind(expression: Node): SpecialPropertyAssignmentKind {
@ -2476,7 +2495,7 @@ namespace ts {
return indentStrings[1].length;
}
export function createTextWriter(newLine: String): EmitTextWriter {
export function createTextWriter(newLine: string): EmitTextWriter {
let output: string;
let indent: number;
let lineStart: boolean;
@ -3129,6 +3148,15 @@ namespace ts {
return tryGetClassExtendingExpressionWithTypeArguments(node) !== undefined;
}
export function isExpressionWithTypeArgumentsInClassImplementsClause(node: Node): node is ExpressionWithTypeArguments {
return node.kind === SyntaxKind.ExpressionWithTypeArguments
&& isEntityNameExpression((node as ExpressionWithTypeArguments).expression)
&& node.parent
&& (<HeritageClause>node.parent).token === SyntaxKind.ImplementsKeyword
&& node.parent.parent
&& isClassLike(node.parent.parent);
}
export function isEntityNameExpression(node: Expression): node is EntityNameExpression {
return node.kind === SyntaxKind.Identifier ||
node.kind === SyntaxKind.PropertyAccessExpression && isEntityNameExpression((<PropertyAccessExpression>node).expression);
@ -3139,15 +3167,14 @@ namespace ts {
(node.parent.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>node.parent).name === node);
}
export function isEmptyObjectLiteralOrArrayLiteral(expression: Node): boolean {
const kind = expression.kind;
if (kind === SyntaxKind.ObjectLiteralExpression) {
return (<ObjectLiteralExpression>expression).properties.length === 0;
}
if (kind === SyntaxKind.ArrayLiteralExpression) {
return (<ArrayLiteralExpression>expression).elements.length === 0;
}
return false;
export function isEmptyObjectLiteral(expression: Node): boolean {
return expression.kind === SyntaxKind.ObjectLiteralExpression &&
(<ObjectLiteralExpression>expression).properties.length === 0;
}
export function isEmptyArrayLiteral(expression: Node): boolean {
return expression.kind === SyntaxKind.ArrayLiteralExpression &&
(<ArrayLiteralExpression>expression).elements.length === 0;
}
export function getLocalSymbolForExportDefault(symbol: Symbol) {

View File

@ -1,4 +1,4 @@
/// <reference path="checker.ts" />
/// <reference path="checker.ts" />
/// <reference path="factory.ts" />
/// <reference path="utilities.ts" />
@ -154,9 +154,9 @@ namespace ts {
* Starts a new lexical environment and visits a parameter list, suspending the lexical
* environment upon completion.
*/
export function visitParameterList(nodes: NodeArray<ParameterDeclaration>, visitor: Visitor, context: TransformationContext) {
export function visitParameterList(nodes: NodeArray<ParameterDeclaration>, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes) {
context.startLexicalEnvironment();
const updated = visitNodes(nodes, visitor, isParameterDeclaration);
const updated = nodesVisitor(nodes, visitor, isParameterDeclaration);
context.suspendLexicalEnvironment();
return updated;
}
@ -204,9 +204,9 @@ namespace ts {
* @param visitor The callback used to visit each child.
* @param context A lexical environment context for the visitor.
*/
export function visitEachChild<T extends Node>(node: T | undefined, visitor: Visitor, context: TransformationContext): T | undefined;
export function visitEachChild<T extends Node>(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes): T | undefined;
export function visitEachChild(node: Node, visitor: Visitor, context: TransformationContext): Node {
export function visitEachChild(node: Node, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes): Node {
if (node === undefined) {
return undefined;
}
@ -243,8 +243,8 @@ namespace ts {
// Signature elements
case SyntaxKind.Parameter:
return updateParameter(<ParameterDeclaration>node,
visitNodes((<ParameterDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<ParameterDeclaration>node).modifiers, visitor, isModifier),
nodesVisitor((<ParameterDeclaration>node).decorators, visitor, isDecorator),
nodesVisitor((<ParameterDeclaration>node).modifiers, visitor, isModifier),
(<ParameterDeclaration>node).dotDotDotToken,
visitNode((<ParameterDeclaration>node).name, visitor, isBindingName),
visitNode((<ParameterDeclaration>node).type, visitor, isTypeNode),
@ -257,55 +257,55 @@ namespace ts {
// Type member
case SyntaxKind.PropertyDeclaration:
return updateProperty(<PropertyDeclaration>node,
visitNodes((<PropertyDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<PropertyDeclaration>node).modifiers, visitor, isModifier),
nodesVisitor((<PropertyDeclaration>node).decorators, visitor, isDecorator),
nodesVisitor((<PropertyDeclaration>node).modifiers, visitor, isModifier),
visitNode((<PropertyDeclaration>node).name, visitor, isPropertyName),
visitNode((<PropertyDeclaration>node).type, visitor, isTypeNode),
visitNode((<PropertyDeclaration>node).initializer, visitor, isExpression));
case SyntaxKind.MethodDeclaration:
return updateMethod(<MethodDeclaration>node,
visitNodes((<MethodDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<MethodDeclaration>node).modifiers, visitor, isModifier),
nodesVisitor((<MethodDeclaration>node).decorators, visitor, isDecorator),
nodesVisitor((<MethodDeclaration>node).modifiers, visitor, isModifier),
(<MethodDeclaration>node).asteriskToken,
visitNode((<MethodDeclaration>node).name, visitor, isPropertyName),
visitNodes((<MethodDeclaration>node).typeParameters, visitor, isTypeParameter),
visitParameterList((<MethodDeclaration>node).parameters, visitor, context),
nodesVisitor((<MethodDeclaration>node).typeParameters, visitor, isTypeParameter),
visitParameterList((<MethodDeclaration>node).parameters, visitor, context, nodesVisitor),
visitNode((<MethodDeclaration>node).type, visitor, isTypeNode),
visitFunctionBody((<MethodDeclaration>node).body, visitor, context));
case SyntaxKind.Constructor:
return updateConstructor(<ConstructorDeclaration>node,
visitNodes((<ConstructorDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<ConstructorDeclaration>node).modifiers, visitor, isModifier),
visitParameterList((<ConstructorDeclaration>node).parameters, visitor, context),
nodesVisitor((<ConstructorDeclaration>node).decorators, visitor, isDecorator),
nodesVisitor((<ConstructorDeclaration>node).modifiers, visitor, isModifier),
visitParameterList((<ConstructorDeclaration>node).parameters, visitor, context, nodesVisitor),
visitFunctionBody((<ConstructorDeclaration>node).body, visitor, context));
case SyntaxKind.GetAccessor:
return updateGetAccessor(<GetAccessorDeclaration>node,
visitNodes((<GetAccessorDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<GetAccessorDeclaration>node).modifiers, visitor, isModifier),
nodesVisitor((<GetAccessorDeclaration>node).decorators, visitor, isDecorator),
nodesVisitor((<GetAccessorDeclaration>node).modifiers, visitor, isModifier),
visitNode((<GetAccessorDeclaration>node).name, visitor, isPropertyName),
visitParameterList((<GetAccessorDeclaration>node).parameters, visitor, context),
visitParameterList((<GetAccessorDeclaration>node).parameters, visitor, context, nodesVisitor),
visitNode((<GetAccessorDeclaration>node).type, visitor, isTypeNode),
visitFunctionBody((<GetAccessorDeclaration>node).body, visitor, context));
case SyntaxKind.SetAccessor:
return updateSetAccessor(<SetAccessorDeclaration>node,
visitNodes((<SetAccessorDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<SetAccessorDeclaration>node).modifiers, visitor, isModifier),
nodesVisitor((<SetAccessorDeclaration>node).decorators, visitor, isDecorator),
nodesVisitor((<SetAccessorDeclaration>node).modifiers, visitor, isModifier),
visitNode((<SetAccessorDeclaration>node).name, visitor, isPropertyName),
visitParameterList((<SetAccessorDeclaration>node).parameters, visitor, context),
visitParameterList((<SetAccessorDeclaration>node).parameters, visitor, context, nodesVisitor),
visitFunctionBody((<SetAccessorDeclaration>node).body, visitor, context));
// Binding patterns
case SyntaxKind.ObjectBindingPattern:
return updateObjectBindingPattern(<ObjectBindingPattern>node,
visitNodes((<ObjectBindingPattern>node).elements, visitor, isBindingElement));
nodesVisitor((<ObjectBindingPattern>node).elements, visitor, isBindingElement));
case SyntaxKind.ArrayBindingPattern:
return updateArrayBindingPattern(<ArrayBindingPattern>node,
visitNodes((<ArrayBindingPattern>node).elements, visitor, isArrayBindingElement));
nodesVisitor((<ArrayBindingPattern>node).elements, visitor, isArrayBindingElement));
case SyntaxKind.BindingElement:
return updateBindingElement(<BindingElement>node,
@ -317,11 +317,11 @@ namespace ts {
// Expression
case SyntaxKind.ArrayLiteralExpression:
return updateArrayLiteral(<ArrayLiteralExpression>node,
visitNodes((<ArrayLiteralExpression>node).elements, visitor, isExpression));
nodesVisitor((<ArrayLiteralExpression>node).elements, visitor, isExpression));
case SyntaxKind.ObjectLiteralExpression:
return updateObjectLiteral(<ObjectLiteralExpression>node,
visitNodes((<ObjectLiteralExpression>node).properties, visitor, isObjectLiteralElementLike));
nodesVisitor((<ObjectLiteralExpression>node).properties, visitor, isObjectLiteralElementLike));
case SyntaxKind.PropertyAccessExpression:
return updatePropertyAccess(<PropertyAccessExpression>node,
@ -336,14 +336,14 @@ namespace ts {
case SyntaxKind.CallExpression:
return updateCall(<CallExpression>node,
visitNode((<CallExpression>node).expression, visitor, isExpression),
visitNodes((<CallExpression>node).typeArguments, visitor, isTypeNode),
visitNodes((<CallExpression>node).arguments, visitor, isExpression));
nodesVisitor((<CallExpression>node).typeArguments, visitor, isTypeNode),
nodesVisitor((<CallExpression>node).arguments, visitor, isExpression));
case SyntaxKind.NewExpression:
return updateNew(<NewExpression>node,
visitNode((<NewExpression>node).expression, visitor, isExpression),
visitNodes((<NewExpression>node).typeArguments, visitor, isTypeNode),
visitNodes((<NewExpression>node).arguments, visitor, isExpression));
nodesVisitor((<NewExpression>node).typeArguments, visitor, isTypeNode),
nodesVisitor((<NewExpression>node).arguments, visitor, isExpression));
case SyntaxKind.TaggedTemplateExpression:
return updateTaggedTemplate(<TaggedTemplateExpression>node,
@ -361,19 +361,19 @@ namespace ts {
case SyntaxKind.FunctionExpression:
return updateFunctionExpression(<FunctionExpression>node,
visitNodes((<FunctionExpression>node).modifiers, visitor, isModifier),
nodesVisitor((<FunctionExpression>node).modifiers, visitor, isModifier),
(<FunctionExpression>node).asteriskToken,
visitNode((<FunctionExpression>node).name, visitor, isIdentifier),
visitNodes((<FunctionExpression>node).typeParameters, visitor, isTypeParameter),
visitParameterList((<FunctionExpression>node).parameters, visitor, context),
nodesVisitor((<FunctionExpression>node).typeParameters, visitor, isTypeParameter),
visitParameterList((<FunctionExpression>node).parameters, visitor, context, nodesVisitor),
visitNode((<FunctionExpression>node).type, visitor, isTypeNode),
visitFunctionBody((<FunctionExpression>node).body, visitor, context));
case SyntaxKind.ArrowFunction:
return updateArrowFunction(<ArrowFunction>node,
visitNodes((<ArrowFunction>node).modifiers, visitor, isModifier),
visitNodes((<ArrowFunction>node).typeParameters, visitor, isTypeParameter),
visitParameterList((<ArrowFunction>node).parameters, visitor, context),
nodesVisitor((<ArrowFunction>node).modifiers, visitor, isModifier),
nodesVisitor((<ArrowFunction>node).typeParameters, visitor, isTypeParameter),
visitParameterList((<ArrowFunction>node).parameters, visitor, context, nodesVisitor),
visitNode((<ArrowFunction>node).type, visitor, isTypeNode),
visitFunctionBody((<ArrowFunction>node).body, visitor, context));
@ -415,7 +415,7 @@ namespace ts {
case SyntaxKind.TemplateExpression:
return updateTemplateExpression(<TemplateExpression>node,
visitNode((<TemplateExpression>node).head, visitor, isTemplateHead),
visitNodes((<TemplateExpression>node).templateSpans, visitor, isTemplateSpan));
nodesVisitor((<TemplateExpression>node).templateSpans, visitor, isTemplateSpan));
case SyntaxKind.YieldExpression:
return updateYield(<YieldExpression>node,
@ -428,15 +428,15 @@ namespace ts {
case SyntaxKind.ClassExpression:
return updateClassExpression(<ClassExpression>node,
visitNodes((<ClassExpression>node).modifiers, visitor, isModifier),
nodesVisitor((<ClassExpression>node).modifiers, visitor, isModifier),
visitNode((<ClassExpression>node).name, visitor, isIdentifier),
visitNodes((<ClassExpression>node).typeParameters, visitor, isTypeParameter),
visitNodes((<ClassExpression>node).heritageClauses, visitor, isHeritageClause),
visitNodes((<ClassExpression>node).members, visitor, isClassElement));
nodesVisitor((<ClassExpression>node).typeParameters, visitor, isTypeParameter),
nodesVisitor((<ClassExpression>node).heritageClauses, visitor, isHeritageClause),
nodesVisitor((<ClassExpression>node).members, visitor, isClassElement));
case SyntaxKind.ExpressionWithTypeArguments:
return updateExpressionWithTypeArguments(<ExpressionWithTypeArguments>node,
visitNodes((<ExpressionWithTypeArguments>node).typeArguments, visitor, isTypeNode),
nodesVisitor((<ExpressionWithTypeArguments>node).typeArguments, visitor, isTypeNode),
visitNode((<ExpressionWithTypeArguments>node).expression, visitor, isExpression));
case SyntaxKind.AsExpression:
@ -457,11 +457,11 @@ namespace ts {
// Element
case SyntaxKind.Block:
return updateBlock(<Block>node,
visitNodes((<Block>node).statements, visitor, isStatement));
nodesVisitor((<Block>node).statements, visitor, isStatement));
case SyntaxKind.VariableStatement:
return updateVariableStatement(<VariableStatement>node,
visitNodes((<VariableStatement>node).modifiers, visitor, isModifier),
nodesVisitor((<VariableStatement>node).modifiers, visitor, isModifier),
visitNode((<VariableStatement>node).declarationList, visitor, isVariableDeclarationList));
case SyntaxKind.ExpressionStatement:
@ -549,61 +549,61 @@ namespace ts {
case SyntaxKind.VariableDeclarationList:
return updateVariableDeclarationList(<VariableDeclarationList>node,
visitNodes((<VariableDeclarationList>node).declarations, visitor, isVariableDeclaration));
nodesVisitor((<VariableDeclarationList>node).declarations, visitor, isVariableDeclaration));
case SyntaxKind.FunctionDeclaration:
return updateFunctionDeclaration(<FunctionDeclaration>node,
visitNodes((<FunctionDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<FunctionDeclaration>node).modifiers, visitor, isModifier),
nodesVisitor((<FunctionDeclaration>node).decorators, visitor, isDecorator),
nodesVisitor((<FunctionDeclaration>node).modifiers, visitor, isModifier),
(<FunctionDeclaration>node).asteriskToken,
visitNode((<FunctionDeclaration>node).name, visitor, isIdentifier),
visitNodes((<FunctionDeclaration>node).typeParameters, visitor, isTypeParameter),
visitParameterList((<FunctionDeclaration>node).parameters, visitor, context),
nodesVisitor((<FunctionDeclaration>node).typeParameters, visitor, isTypeParameter),
visitParameterList((<FunctionDeclaration>node).parameters, visitor, context, nodesVisitor),
visitNode((<FunctionDeclaration>node).type, visitor, isTypeNode),
visitFunctionBody((<FunctionExpression>node).body, visitor, context));
case SyntaxKind.ClassDeclaration:
return updateClassDeclaration(<ClassDeclaration>node,
visitNodes((<ClassDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<ClassDeclaration>node).modifiers, visitor, isModifier),
nodesVisitor((<ClassDeclaration>node).decorators, visitor, isDecorator),
nodesVisitor((<ClassDeclaration>node).modifiers, visitor, isModifier),
visitNode((<ClassDeclaration>node).name, visitor, isIdentifier),
visitNodes((<ClassDeclaration>node).typeParameters, visitor, isTypeParameter),
visitNodes((<ClassDeclaration>node).heritageClauses, visitor, isHeritageClause),
visitNodes((<ClassDeclaration>node).members, visitor, isClassElement));
nodesVisitor((<ClassDeclaration>node).typeParameters, visitor, isTypeParameter),
nodesVisitor((<ClassDeclaration>node).heritageClauses, visitor, isHeritageClause),
nodesVisitor((<ClassDeclaration>node).members, visitor, isClassElement));
case SyntaxKind.EnumDeclaration:
return updateEnumDeclaration(<EnumDeclaration>node,
visitNodes((<EnumDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<EnumDeclaration>node).modifiers, visitor, isModifier),
nodesVisitor((<EnumDeclaration>node).decorators, visitor, isDecorator),
nodesVisitor((<EnumDeclaration>node).modifiers, visitor, isModifier),
visitNode((<EnumDeclaration>node).name, visitor, isIdentifier),
visitNodes((<EnumDeclaration>node).members, visitor, isEnumMember));
nodesVisitor((<EnumDeclaration>node).members, visitor, isEnumMember));
case SyntaxKind.ModuleDeclaration:
return updateModuleDeclaration(<ModuleDeclaration>node,
visitNodes((<ModuleDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<ModuleDeclaration>node).modifiers, visitor, isModifier),
nodesVisitor((<ModuleDeclaration>node).decorators, visitor, isDecorator),
nodesVisitor((<ModuleDeclaration>node).modifiers, visitor, isModifier),
visitNode((<ModuleDeclaration>node).name, visitor, isIdentifier),
visitNode((<ModuleDeclaration>node).body, visitor, isModuleBody));
case SyntaxKind.ModuleBlock:
return updateModuleBlock(<ModuleBlock>node,
visitNodes((<ModuleBlock>node).statements, visitor, isStatement));
nodesVisitor((<ModuleBlock>node).statements, visitor, isStatement));
case SyntaxKind.CaseBlock:
return updateCaseBlock(<CaseBlock>node,
visitNodes((<CaseBlock>node).clauses, visitor, isCaseOrDefaultClause));
nodesVisitor((<CaseBlock>node).clauses, visitor, isCaseOrDefaultClause));
case SyntaxKind.ImportEqualsDeclaration:
return updateImportEqualsDeclaration(<ImportEqualsDeclaration>node,
visitNodes((<ImportEqualsDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<ImportEqualsDeclaration>node).modifiers, visitor, isModifier),
nodesVisitor((<ImportEqualsDeclaration>node).decorators, visitor, isDecorator),
nodesVisitor((<ImportEqualsDeclaration>node).modifiers, visitor, isModifier),
visitNode((<ImportEqualsDeclaration>node).name, visitor, isIdentifier),
visitNode((<ImportEqualsDeclaration>node).moduleReference, visitor, isModuleReference));
case SyntaxKind.ImportDeclaration:
return updateImportDeclaration(<ImportDeclaration>node,
visitNodes((<ImportDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<ImportDeclaration>node).modifiers, visitor, isModifier),
nodesVisitor((<ImportDeclaration>node).decorators, visitor, isDecorator),
nodesVisitor((<ImportDeclaration>node).modifiers, visitor, isModifier),
visitNode((<ImportDeclaration>node).importClause, visitor, isImportClause),
visitNode((<ImportDeclaration>node).moduleSpecifier, visitor, isExpression));
@ -618,7 +618,7 @@ namespace ts {
case SyntaxKind.NamedImports:
return updateNamedImports(<NamedImports>node,
visitNodes((<NamedImports>node).elements, visitor, isImportSpecifier));
nodesVisitor((<NamedImports>node).elements, visitor, isImportSpecifier));
case SyntaxKind.ImportSpecifier:
return updateImportSpecifier(<ImportSpecifier>node,
@ -627,20 +627,20 @@ namespace ts {
case SyntaxKind.ExportAssignment:
return updateExportAssignment(<ExportAssignment>node,
visitNodes((<ExportAssignment>node).decorators, visitor, isDecorator),
visitNodes((<ExportAssignment>node).modifiers, visitor, isModifier),
nodesVisitor((<ExportAssignment>node).decorators, visitor, isDecorator),
nodesVisitor((<ExportAssignment>node).modifiers, visitor, isModifier),
visitNode((<ExportAssignment>node).expression, visitor, isExpression));
case SyntaxKind.ExportDeclaration:
return updateExportDeclaration(<ExportDeclaration>node,
visitNodes((<ExportDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<ExportDeclaration>node).modifiers, visitor, isModifier),
nodesVisitor((<ExportDeclaration>node).decorators, visitor, isDecorator),
nodesVisitor((<ExportDeclaration>node).modifiers, visitor, isModifier),
visitNode((<ExportDeclaration>node).exportClause, visitor, isNamedExports),
visitNode((<ExportDeclaration>node).moduleSpecifier, visitor, isExpression));
case SyntaxKind.NamedExports:
return updateNamedExports(<NamedExports>node,
visitNodes((<NamedExports>node).elements, visitor, isExportSpecifier));
nodesVisitor((<NamedExports>node).elements, visitor, isExportSpecifier));
case SyntaxKind.ExportSpecifier:
return updateExportSpecifier(<ExportSpecifier>node,
@ -656,12 +656,12 @@ namespace ts {
case SyntaxKind.JsxElement:
return updateJsxElement(<JsxElement>node,
visitNode((<JsxElement>node).openingElement, visitor, isJsxOpeningElement),
visitNodes((<JsxElement>node).children, visitor, isJsxChild),
nodesVisitor((<JsxElement>node).children, visitor, isJsxChild),
visitNode((<JsxElement>node).closingElement, visitor, isJsxClosingElement));
case SyntaxKind.JsxAttributes:
return updateJsxAttributes(<JsxAttributes>node,
visitNodes((<JsxAttributes>node).properties, visitor, isJsxAttributeLike));
nodesVisitor((<JsxAttributes>node).properties, visitor, isJsxAttributeLike));
case SyntaxKind.JsxSelfClosingElement:
return updateJsxSelfClosingElement(<JsxSelfClosingElement>node,
@ -694,15 +694,15 @@ namespace ts {
case SyntaxKind.CaseClause:
return updateCaseClause(<CaseClause>node,
visitNode((<CaseClause>node).expression, visitor, isExpression),
visitNodes((<CaseClause>node).statements, visitor, isStatement));
nodesVisitor((<CaseClause>node).statements, visitor, isStatement));
case SyntaxKind.DefaultClause:
return updateDefaultClause(<DefaultClause>node,
visitNodes((<DefaultClause>node).statements, visitor, isStatement));
nodesVisitor((<DefaultClause>node).statements, visitor, isStatement));
case SyntaxKind.HeritageClause:
return updateHeritageClause(<HeritageClause>node,
visitNodes((<HeritageClause>node).types, visitor, isExpressionWithTypeArguments));
nodesVisitor((<HeritageClause>node).types, visitor, isExpressionWithTypeArguments));
case SyntaxKind.CatchClause:
return updateCatchClause(<CatchClause>node,

View File

@ -1,4 +1,4 @@
//
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -22,6 +22,10 @@
namespace FourSlash {
ts.disableIncrementalParsing = false;
function normalizeNewLines(s: string) {
return s.replace(/\r\n/g, "\n");
}
// Represents a parsed source file with metadata
export interface FourSlashFile {
// The contents of the file (with markers, etc stripped out)
@ -596,7 +600,7 @@ namespace FourSlash {
}
private getGoToDefinition(): ts.DefinitionInfo[] {
return this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition)
return this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition);
}
public verifyGoToType(arg0: any, endMarkerNames?: string | string[]) {
@ -996,9 +1000,13 @@ namespace FourSlash {
}
function rangeToReferenceEntry(r: Range) {
let { isWriteAccess, isDefinition } = (r.marker && r.marker.data) || { isWriteAccess: false, isDefinition: false };
let { isWriteAccess, isDefinition, isInString } = (r.marker && r.marker.data) || { isWriteAccess: false, isDefinition: false, isInString: undefined };
isWriteAccess = !!isWriteAccess; isDefinition = !!isDefinition;
return { fileName: r.fileName, textSpan: { start: r.start, length: r.end - r.start }, isWriteAccess, isDefinition }
const result: any = { fileName: r.fileName, textSpan: { start: r.start, length: r.end - r.start }, isWriteAccess, isDefinition };
if (isInString !== undefined) {
result.isInString = isInString;
}
return result;
}
}
@ -1943,17 +1951,41 @@ namespace FourSlash {
const unsatisfiedRanges: Range[] = [];
const delayedErrors: string[] = [];
for (const range of ranges) {
const length = range.end - range.start;
const matchingImpl = ts.find(implementations, impl =>
range.fileName === impl.fileName && range.start === impl.textSpan.start && length === impl.textSpan.length);
if (matchingImpl) {
if (range.marker && range.marker.data) {
const expected = <{ displayParts?: ts.SymbolDisplayPart[], parts: string[], kind?: string }>range.marker.data;
if (expected.displayParts) {
if (!ts.arrayIsEqualTo(expected.displayParts, matchingImpl.displayParts, displayPartIsEqualTo)) {
delayedErrors.push(`Mismatched display parts: expected ${JSON.stringify(expected.displayParts)}, actual ${JSON.stringify(matchingImpl.displayParts)}`);
}
}
else if (expected.parts) {
const actualParts = matchingImpl.displayParts.map(p => p.text);
if (!ts.arrayIsEqualTo(expected.parts, actualParts)) {
delayedErrors.push(`Mismatched non-tagged display parts: expected ${JSON.stringify(expected.parts)}, actual ${JSON.stringify(actualParts)}`);
}
}
if (expected.kind !== undefined) {
if (expected.kind !== matchingImpl.kind) {
delayedErrors.push(`Mismatched kind: expected ${JSON.stringify(expected.kind)}, actual ${JSON.stringify(matchingImpl.kind)}`);
}
}
}
matchingImpl.matched = true;
}
else {
unsatisfiedRanges.push(range);
}
}
if (delayedErrors.length) {
this.raiseError(delayedErrors.join("\n"));
}
const unmatchedImplementations = implementations.filter(impl => !impl.matched);
if (unmatchedImplementations.length || unsatisfiedRanges.length) {
@ -1978,6 +2010,10 @@ namespace FourSlash {
function implementationsAreEqual(a: ImplementationLocationInformation, b: ImplementationLocationInformation) {
return a.fileName === b.fileName && TestState.textSpansEqual(a.textSpan, b.textSpan);
}
function displayPartIsEqualTo(a: ts.SymbolDisplayPart, b: ts.SymbolDisplayPart): boolean {
return a.kind === b.kind && a.text === b.text;
}
}
public getMarkers(): Marker[] {
@ -2050,8 +2086,7 @@ namespace FourSlash {
public verifyCurrentFileContent(text: string) {
const actual = this.getFileContent(this.activeFile.fileName);
const replaceNewlines = (str: string) => str.replace(/\r\n/g, "\n");
if (replaceNewlines(actual) !== replaceNewlines(text)) {
if (normalizeNewLines(actual) !== normalizeNewLines(text)) {
throw new Error("verifyCurrentFileContent\n" +
"\tExpected: \"" + text + "\"\n" +
"\t Actual: \"" + actual + "\"");
@ -2227,8 +2262,8 @@ namespace FourSlash {
const actualText = this.rangeText(ranges[0]);
const result = includeWhiteSpace
? actualText === expectedText
: this.removeWhitespace(actualText) === this.removeWhitespace(expectedText)
? normalizeNewLines(actualText) === normalizeNewLines(expectedText)
: this.removeWhitespace(actualText) === this.removeWhitespace(expectedText);
if (!result) {
this.raiseError(`Actual text doesn't match expected text. Actual:\n'${actualText}'\nExpected:\n'${expectedText}'`);
@ -2265,7 +2300,7 @@ namespace FourSlash {
start: diagnostic.start,
length: diagnostic.length,
code: diagnostic.code
}
};
});
const dedupedDiagnositcs = ts.deduplicate(diagnosticsForCodeFix, ts.equalOwnProperties);
@ -2277,7 +2312,7 @@ namespace FourSlash {
continue;
}
const newActions = this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.length, [diagnostic.code]);
const newActions = this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.length, [diagnostic.code], this.formatCodeSettings);
if (newActions && newActions.length) {
actions = actions ? actions.concat(newActions) : newActions;
}
@ -2340,22 +2375,23 @@ namespace FourSlash {
if (expected === undefined) {
if (actual) {
this.raiseError(name + " failed - expected no template but got {newText: \"" + actual.newText + "\" caretOffset: " + actual.caretOffset + "}");
this.raiseError(`${name} failed - expected no template but got {newText: "${actual.newText}", caretOffset: ${actual.caretOffset}}`);
}
return;
}
else {
if (actual === undefined) {
this.raiseError(name + " failed - expected the template {newText: \"" + actual.newText + "\" caretOffset: " + actual.caretOffset + "} but got nothing instead");
this.raiseError(`${name} failed - expected the template {newText: "${expected.newText}", caretOffset: "${expected.caretOffset}"} but got nothing instead`);
}
if (actual.newText !== expected.newText) {
this.raiseError(name + " failed - expected insertion:\n" + this.clarifyNewlines(expected.newText) + "\nactual insertion:\n" + this.clarifyNewlines(actual.newText));
this.raiseError(`${name} failed - expected insertion:\n"${this.clarifyNewlines(expected.newText)}"\nactual insertion:\n"${this.clarifyNewlines(actual.newText)}"`);
}
if (actual.caretOffset !== expected.caretOffset) {
this.raiseError(name + " failed - expected caretOffset: " + expected.caretOffset + ",\nactual caretOffset:" + actual.caretOffset);
this.raiseError(`${name} failed - expected caretOffset: ${expected.caretOffset}\nactual caretOffset:${actual.caretOffset}`);
}
}
}

View File

@ -34,17 +34,11 @@ var _chai: typeof chai = require("chai");
var assert: typeof _chai.assert = _chai.assert;
declare var __dirname: string; // Node-specific
var global: NodeJS.Global = <any>Function("return this").call(undefined);
declare namespace NodeJS {
export interface Global {
WScript: typeof WScript;
ActiveXObject: typeof ActiveXObject;
}
}
declare var window: {};
declare var XMLHttpRequest: {
new(): XMLHttpRequest;
}
};
interface XMLHttpRequest {
readonly readyState: number;
readonly responseText: string;
@ -60,14 +54,10 @@ namespace Utils {
export const enum ExecutionEnvironment {
Node,
Browser,
CScript
}
export function getExecutionEnvironment() {
if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") {
return ExecutionEnvironment.CScript;
}
else if (typeof window !== "undefined") {
if (typeof window !== "undefined") {
return ExecutionEnvironment.Browser;
}
else {
@ -93,7 +83,6 @@ namespace Utils {
export function evalFile(fileContents: string, fileName: string, nodeContext?: any) {
const environment = getExecutionEnvironment();
switch (environment) {
case ExecutionEnvironment.CScript:
case ExecutionEnvironment.Browser:
eval(fileContents);
break;
@ -516,83 +505,6 @@ namespace Harness {
export const virtualFileSystemRoot = "/";
namespace IOImpl {
declare class Enumerator {
public atEnd(): boolean;
public moveNext(): boolean;
public item(): any;
constructor(o: any);
}
export namespace CScript {
let fso: any;
if (global.ActiveXObject) {
fso = new global.ActiveXObject("Scripting.FileSystemObject");
}
else {
fso = {};
}
export const args = () => ts.sys.args;
export const getExecutingFilePath = () => ts.sys.getExecutingFilePath();
export const exit = (exitCode: number) => ts.sys.exit(exitCode);
export const resolvePath = (path: string) => ts.sys.resolvePath(path);
export const getCurrentDirectory = () => ts.sys.getCurrentDirectory();
export const newLine = () => harnessNewLine;
export const useCaseSensitiveFileNames = () => ts.sys.useCaseSensitiveFileNames;
export const readFile: typeof IO.readFile = path => ts.sys.readFile(path);
export const writeFile: typeof IO.writeFile = (path, content) => ts.sys.writeFile(path, content);
export const directoryName: typeof IO.directoryName = fso.GetParentFolderName;
export const getDirectories: typeof IO.getDirectories = dir => ts.sys.getDirectories(dir);
export const directoryExists: typeof IO.directoryExists = fso.FolderExists;
export const fileExists: typeof IO.fileExists = fso.FileExists;
export const log: typeof IO.log = global.WScript && global.WScript.StdOut.WriteLine;
export const getEnvironmentVariable: typeof IO.getEnvironmentVariable = name => ts.sys.getEnvironmentVariable(name);
export const readDirectory: typeof IO.readDirectory = (path, extension, exclude, include) => ts.sys.readDirectory(path, extension, exclude, include);
export function createDirectory(path: string) {
if (directoryExists(path)) {
fso.CreateFolder(path);
}
}
export function deleteFile(path: string) {
if (fileExists(path)) {
fso.DeleteFile(path, true); // true: delete read-only files
}
}
export let listFiles: typeof IO.listFiles = (path, spec?, options?) => {
options = options || <{ recursive?: boolean; }>{};
function filesInFolder(folder: any, root: string): string[] {
let paths: string[] = [];
let fc: any;
if (options.recursive) {
fc = new Enumerator(folder.subfolders);
for (; !fc.atEnd(); fc.moveNext()) {
paths = paths.concat(filesInFolder(fc.item(), root + "\\" + fc.item().Name));
}
}
fc = new Enumerator(folder.files);
for (; !fc.atEnd(); fc.moveNext()) {
if (!spec || fc.item().Name.match(spec)) {
paths.push(root + "\\" + fc.item().Name);
}
}
return paths;
}
const folder: any = fso.GetFolder(path);
return filesInFolder(folder, path);
};
}
export namespace Node {
declare const require: any;
let fs: any, pathModule: any;
@ -840,16 +752,16 @@ namespace Harness {
}
}
switch (Utils.getExecutionEnvironment()) {
case Utils.ExecutionEnvironment.CScript:
IO = IOImpl.CScript;
break;
const environment = Utils.getExecutionEnvironment();
switch (environment) {
case Utils.ExecutionEnvironment.Node:
IO = IOImpl.Node;
break;
case Utils.ExecutionEnvironment.Browser:
IO = IOImpl.Network;
break;
default:
throw new Error(`Unknown value '${environment}' for ExecutionEnvironment.`);
}
}
@ -873,7 +785,7 @@ namespace Harness {
/** Aggregate various writes into a single array of lines. Useful for passing to the
* TypeScript compiler to fill with source code or errors.
*/
export class WriterAggregator implements ITextWriter {
export class WriterAggregator {
public lines: string[] = [];
public currentLine = <string>undefined;
@ -1017,7 +929,7 @@ namespace Harness {
}
else {
if (!es6TestLibFileNameSourceFileMap.get(libFileName)) {
es6TestLibFileNameSourceFileMap.set(libFileName, createSourceFileAndAssertInvariants(libFileName, IO.readFile(libFileName), scriptTarget))
es6TestLibFileNameSourceFileMap.set(libFileName, createSourceFileAndAssertInvariants(libFileName, IO.readFile(libFileName), scriptTarget));
}
}
}

View File

@ -779,7 +779,7 @@ namespace Harness.LanguageService {
start: 0
});
return prev;
}
};
return proxy;
}
}),

View File

@ -6,6 +6,10 @@
"declaration": false,
"types": [
"node", "mocha", "chai"
],
"lib": [
"es6",
"scripthost"
]
},
"files": [
@ -121,6 +125,7 @@
"./unittests/projectErrors.ts",
"./unittests/printer.ts",
"./unittests/transform.ts",
"./unittests/customTransforms.ts"
"./unittests/customTransforms.ts",
"./unittests/textChanges.ts"
]
}

View File

@ -1,4 +1,4 @@
/// <reference path="..\harness.ts" />
/// <reference path="..\harness.ts" />
namespace ts {
interface File {

View File

@ -496,7 +496,7 @@ namespace ts.projectSystem {
const emitOutput = host.readFile(path + ".js");
assert.equal(emitOutput, f.content + newLine, "content of emit output should be identical with the input + newline");
}
})
});
it("should emit specified file", () => {
const file1 = {

View File

@ -1,4 +1,4 @@
/// <reference path="..\harness.ts" />
/// <reference path="..\harness.ts" />
/// <reference path="..\..\compiler\commandLineParser.ts" />
namespace ts {

View File

@ -9,7 +9,7 @@ namespace ts {
Harness.Baseline.runBaseline(`printerApi/${prefix}.${name}.js`, () =>
printCallback(createPrinter({ newLine: NewLineKind.CarriageReturnLineFeed, ...options })));
});
}
};
}
describe("printFile", () => {
@ -45,6 +45,9 @@ namespace ts {
// comment9
console.log(1 + 2);
// comment10
function functionWithDefaultArgValue(argument: string = "defaultValue"): void { }
`, ScriptTarget.ES2015);
printsCorrectly("default", {}, printer => printer.printFile(sourceFile));

View File

@ -1,4 +1,4 @@
/// <reference path="..\harness.ts" />
/// <reference path="..\harness.ts" />
/// <reference path="..\..\harness\harnessLanguageService.ts" />
namespace ts {

View File

@ -1,4 +1,4 @@
/// <reference path="..\..\harnessLanguageService.ts" />
/// <reference path="..\..\harnessLanguageService.ts" />
interface ClassificationEntry {
value: any;

View File

@ -1,4 +1,4 @@
/// <reference path="..\..\harnessLanguageService.ts" />
/// <reference path="..\..\harnessLanguageService.ts" />
describe("PreProcessFile:", function () {
function test(sourceText: string, readImportFile: boolean, detectJavaScriptImports: boolean, expectedPreProcess: ts.PreProcessedFileInfo): void {

View File

@ -1,4 +1,4 @@
/// <reference path="..\harness.ts" />
/// <reference path="..\harness.ts" />
const expect: typeof _chai.expect = _chai.expect;

View File

@ -0,0 +1,791 @@
/// <reference path="..\..\compiler\emitter.ts" />
/// <reference path="..\..\services\textChanges.ts" />
/// <reference path="..\harness.ts" />
namespace ts {
describe("textChanges", () => {
function findChild(name: string, n: Node) {
return find(n);
function find(node: Node): Node {
if (isDeclaration(node) && node.name && isIdentifier(node.name) && node.name.text === name) {
return node;
}
else {
return forEachChild(node, find);
}
}
}
const printerOptions = { newLine: NewLineKind.LineFeed };
const newLineCharacter = getNewLineCharacter(printerOptions);
function getRuleProvider(action?: (opts: FormatCodeSettings) => void) {
const options = {
indentSize: 4,
tabSize: 4,
newLineCharacter,
convertTabsToSpaces: true,
indentStyle: ts.IndentStyle.Smart,
insertSpaceAfterConstructor: false,
insertSpaceAfterCommaDelimiter: true,
insertSpaceAfterSemicolonInForStatements: true,
insertSpaceBeforeAndAfterBinaryOperators: true,
insertSpaceAfterKeywordsInControlFlowStatements: true,
insertSpaceAfterFunctionKeywordForAnonymousFunctions: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false,
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false,
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false,
insertSpaceBeforeFunctionParenthesis: false,
placeOpenBraceOnNewLineForFunctions: false,
placeOpenBraceOnNewLineForControlBlocks: false,
};
if (action) {
action(options);
}
const rulesProvider = new formatting.RulesProvider();
rulesProvider.ensureUpToDate(options);
return rulesProvider;
}
// validate that positions that were recovered from the printed text actually match positions that will be created if the same text is parsed.
function verifyPositions({ text, node }: textChanges.NonFormattedText): void {
const nodeList = flattenNodes(node);
const sourceFile = createSourceFile("f.ts", text, ScriptTarget.ES2015);
const parsedNodeList = flattenNodes(sourceFile.statements[0]);
Debug.assert(nodeList.length === parsedNodeList.length);
for (let i = 0; i < nodeList.length; i++) {
const left = nodeList[i];
const right = parsedNodeList[i];
Debug.assert(left.pos === right.pos);
Debug.assert(left.end === right.end);
}
function flattenNodes(n: Node) {
const data: (Node | NodeArray<any>)[] = [];
walk(n);
return data;
function walk(n: Node | Node[]): void {
data.push(<any>n);
return isArray(n) ? forEach(n, walk) : forEachChild(n, walk, walk);
}
}
}
function runSingleFileTest(caption: string, setupFormatOptions: (opts: FormatCodeSettings) => void, text: string, validateNodes: boolean, testBlock: (sourceFile: SourceFile, changeTracker: textChanges.ChangeTracker) => void) {
it(caption, () => {
Harness.Baseline.runBaseline(`textChanges/${caption}.js`, () => {
const sourceFile = createSourceFile("source.ts", text, ScriptTarget.ES2015, /*setParentNodes*/ true);
const rulesProvider = getRuleProvider(setupFormatOptions);
const changeTracker = new textChanges.ChangeTracker(printerOptions.newLine, rulesProvider, validateNodes ? verifyPositions : undefined);
testBlock(sourceFile, changeTracker);
const changes = changeTracker.getChanges();
assert.equal(changes.length, 1);
assert.equal(changes[0].fileName, sourceFile.fileName);
const modified = textChanges.applyChanges(sourceFile.text, changes[0].textChanges);
return `===ORIGINAL===${newLineCharacter}${text}${newLineCharacter}===MODIFIED===${newLineCharacter}${modified}`;
});
});
}
function setNewLineForOpenBraceInFunctions(opts: FormatCodeSettings) {
opts.placeOpenBraceOnNewLineForFunctions = true;
}
{
const text = `
namespace M
{
namespace M2
{
function foo() {
// comment 1
const x = 1;
/**
* comment 2 line 1
* comment 2 line 2
*/
function f() {
return 100;
}
const y = 2; // comment 3
return 1;
}
}
}`;
runSingleFileTest("extractMethodLike", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
const statements = (<Block>(<FunctionDeclaration>findChild("foo", sourceFile)).body).statements.slice(1);
const newFunction = createFunctionDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
/*name*/ "bar",
/*typeParameters*/ undefined,
/*parameters*/ emptyArray,
/*type*/ createKeywordTypeNode(SyntaxKind.AnyKeyword),
/*body */ createBlock(statements)
);
changeTracker.insertNodeBefore(sourceFile, /*before*/findChild("M2", sourceFile), newFunction, { suffix: newLineCharacter });
// replace statements with return statement
const newStatement = createReturn(
createCall(
/*expression*/ newFunction.name,
/*typeArguments*/ undefined,
/*argumentsArray*/ emptyArray
));
changeTracker.replaceNodeRange(sourceFile, statements[0], lastOrUndefined(statements), newStatement, { suffix: newLineCharacter });
});
}
{
const text = `
function foo() {
return 1;
}
function bar() {
return 2;
}
`;
runSingleFileTest("deleteRange1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteRange(sourceFile, { pos: text.indexOf("function foo"), end: text.indexOf("function bar") });
});
}
function findVariableStatementContaining(name: string, sourceFile: SourceFile) {
const varDecl = findChild(name, sourceFile);
assert.equal(varDecl.kind, SyntaxKind.VariableDeclaration);
const varStatement = varDecl.parent.parent;
assert.equal(varStatement.kind, SyntaxKind.VariableStatement);
return varStatement;
}
{
const text = `
var x = 1; // some comment - 1
/**
* comment 2
*/
var y = 2; // comment 3
var z = 3; // comment 4
`;
runSingleFileTest("deleteNode1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNode(sourceFile, findVariableStatementContaining("y", sourceFile));
});
runSingleFileTest("deleteNode2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNode(sourceFile, findVariableStatementContaining("y", sourceFile), { useNonAdjustedStartPosition: true });
});
runSingleFileTest("deleteNode3", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNode(sourceFile, findVariableStatementContaining("y", sourceFile), { useNonAdjustedEndPosition: true });
});
runSingleFileTest("deleteNode4", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNode(sourceFile, findVariableStatementContaining("y", sourceFile), { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: true });
});
runSingleFileTest("deleteNode5", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNode(sourceFile, findVariableStatementContaining("x", sourceFile));
});
}
{
const text = `
// comment 1
var x = 1; // comment 2
// comment 3
var y = 2; // comment 4
var z = 3; // comment 5
// comment 6
var a = 4; // comment 7
`;
runSingleFileTest("deleteNodeRange1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile));
});
runSingleFileTest("deleteNodeRange2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile),
{ useNonAdjustedStartPosition: true });
});
runSingleFileTest("deleteNodeRange3", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile),
{ useNonAdjustedEndPosition: true });
});
runSingleFileTest("deleteNodeRange4", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile),
{ useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: true });
});
}
function createTestVariableDeclaration(name: string) {
return createVariableDeclaration(name, /*type*/ undefined, createObjectLiteral([createPropertyAssignment("p1", createLiteral(1))], /*multiline*/ true));
}
function createTestClass() {
return createClassDeclaration(
/*decorators*/ undefined,
[
createToken(SyntaxKind.PublicKeyword)
],
"class1",
/*typeParameters*/ undefined,
[
createHeritageClause(
SyntaxKind.ImplementsKeyword,
[
createExpressionWithTypeArguments(/*typeArguments*/ undefined, createIdentifier("interface1"))
]
)
],
[
createProperty(
/*decorators*/ undefined,
/*modifiers*/ undefined,
"property1",
/*questionToken*/ undefined,
createKeywordTypeNode(SyntaxKind.BooleanKeyword),
/*initializer*/ undefined
)
]
);
}
{
const text = `
// comment 1
var x = 1; // comment 2
// comment 3
var y = 2; // comment 4
var z = 3; // comment 5
// comment 6
var a = 4; // comment 7`;
runSingleFileTest("replaceRange", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.replaceRange(sourceFile, { pos: text.indexOf("var y"), end: text.indexOf("var a") }, createTestClass(), { suffix: newLineCharacter });
});
runSingleFileTest("replaceRangeWithForcedIndentation", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.replaceRange(sourceFile, { pos: text.indexOf("var y"), end: text.indexOf("var a") }, createTestClass(), { suffix: newLineCharacter, indentation: 8, delta: 0 });
});
runSingleFileTest("replaceRangeNoLineBreakBefore", setNewLineForOpenBraceInFunctions, `const x = 1, y = "2";`, /*validateNodes*/ false, (sourceFile, changeTracker) => {
const newNode = createTestVariableDeclaration("z1");
changeTracker.replaceRange(sourceFile, { pos: sourceFile.text.indexOf("y"), end: sourceFile.text.indexOf(";") }, newNode);
});
}
{
const text = `
namespace A {
const x = 1, y = "2";
}
`;
runSingleFileTest("replaceNode1NoLineBreakBefore", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
const newNode = createTestVariableDeclaration("z1");
changeTracker.replaceNode(sourceFile, findChild("y", sourceFile), newNode);
});
}
{
const text = `
// comment 1
var x = 1; // comment 2
// comment 3
var y = 2; // comment 4
var z = 3; // comment 5
// comment 6
var a = 4; // comment 7`;
runSingleFileTest("replaceNode1", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { suffix: newLineCharacter });
});
runSingleFileTest("replaceNode2", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { useNonAdjustedStartPosition: true, suffix: newLineCharacter, prefix: newLineCharacter });
});
runSingleFileTest("replaceNode3", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { useNonAdjustedEndPosition: true, suffix: newLineCharacter });
});
runSingleFileTest("replaceNode4", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: true });
});
runSingleFileTest("replaceNode5", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.replaceNode(sourceFile, findVariableStatementContaining("x", sourceFile), createTestClass(), { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: true });
});
}
{
const text = `
// comment 1
var x = 1; // comment 2
// comment 3
var y = 2; // comment 4
var z = 3; // comment 5
// comment 6
var a = 4; // comment 7`;
runSingleFileTest("replaceNodeRange1", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { suffix: newLineCharacter });
});
runSingleFileTest("replaceNodeRange2", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { useNonAdjustedStartPosition: true, suffix: newLineCharacter, prefix: newLineCharacter });
});
runSingleFileTest("replaceNodeRange3", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { useNonAdjustedEndPosition: true, suffix: newLineCharacter });
});
runSingleFileTest("replaceNodeRange4", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: true });
});
}
{
const text = `
// comment 1
var x = 1; // comment 2
// comment 3
var y; // comment 4
var z = 3; // comment 5
// comment 6
var a = 4; // comment 7`;
runSingleFileTest("insertNodeAt1", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.insertNodeAt(sourceFile, text.indexOf("var y"), createTestClass(), { suffix: newLineCharacter });
});
runSingleFileTest("insertNodeAt2", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeAt(sourceFile, text.indexOf("; // comment 4"), createTestVariableDeclaration("z1"));
});
}
{
const text = `
namespace M {
// comment 1
var x = 1; // comment 2
// comment 3
var y; // comment 4
var z = 3; // comment 5
// comment 6
var a = 4; // comment 7
}`;
runSingleFileTest("insertNodeBefore1", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.insertNodeBefore(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { suffix: newLineCharacter });
});
runSingleFileTest("insertNodeBefore2", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.insertNodeBefore(sourceFile, findChild("M", sourceFile), createTestClass(), { suffix: newLineCharacter });
});
runSingleFileTest("insertNodeAfter1", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.insertNodeAfter(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { suffix: newLineCharacter });
});
runSingleFileTest("insertNodeAfter2", setNewLineForOpenBraceInFunctions, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
changeTracker.insertNodeAfter(sourceFile, findChild("M", sourceFile), createTestClass(), { prefix: newLineCharacter });
});
}
{
function findOpenBraceForConstructor(sourceFile: SourceFile) {
const classDecl = <ClassDeclaration>sourceFile.statements[0];
const constructorDecl = forEach(classDecl.members, m => m.kind === SyntaxKind.Constructor && (<ConstructorDeclaration>m).body && <ConstructorDeclaration>m);
return constructorDecl.body.getFirstToken();
}
function createTestSuperCall() {
const superCall = createCall(
createSuper(),
/*typeArguments*/ undefined,
/*argumentsArray*/ emptyArray
);
return createStatement(superCall);
}
const text1 = `
class A {
constructor() {
}
}
`;
runSingleFileTest("insertNodeAfter3", noop, text1, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeAfter(sourceFile, findOpenBraceForConstructor(sourceFile), createTestSuperCall(), { suffix: newLineCharacter });
});
const text2 = `
class A {
constructor() {
var x = 1;
}
}
`;
runSingleFileTest("insertNodeAfter4", noop, text2, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeAfter(sourceFile, findVariableStatementContaining("x", sourceFile), createTestSuperCall(), { suffix: newLineCharacter });
});
const text3 = `
class A {
constructor() {
}
}
`;
runSingleFileTest("insertNodeAfter3-block with newline", noop, text3, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeAfter(sourceFile, findOpenBraceForConstructor(sourceFile), createTestSuperCall(), { suffix: newLineCharacter });
});
}
{
const text = `var a = 1, b = 2, c = 3;`;
runSingleFileTest("deleteNodeInList1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeInList(sourceFile, findChild("a", sourceFile));
});
runSingleFileTest("deleteNodeInList2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeInList(sourceFile, findChild("b", sourceFile));
});
runSingleFileTest("deleteNodeInList3", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeInList(sourceFile, findChild("c", sourceFile));
});
}
{
const text = `var a = 1,b = 2,c = 3;`;
runSingleFileTest("deleteNodeInList1_1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeInList(sourceFile, findChild("a", sourceFile));
});
runSingleFileTest("deleteNodeInList2_1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeInList(sourceFile, findChild("b", sourceFile));
});
runSingleFileTest("deleteNodeInList3_1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeInList(sourceFile, findChild("c", sourceFile));
});
}
{
const text = `
namespace M {
var a = 1,
b = 2,
c = 3;
}`;
runSingleFileTest("deleteNodeInList4", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeInList(sourceFile, findChild("a", sourceFile));
});
runSingleFileTest("deleteNodeInList5", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeInList(sourceFile, findChild("b", sourceFile));
});
runSingleFileTest("deleteNodeInList6", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeInList(sourceFile, findChild("c", sourceFile));
});
}
{
const text = `
namespace M {
var a = 1, // comment 1
// comment 2
b = 2, // comment 3
// comment 4
c = 3; // comment 5
}`;
runSingleFileTest("deleteNodeInList4_1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeInList(sourceFile, findChild("a", sourceFile));
});
runSingleFileTest("deleteNodeInList5_1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeInList(sourceFile, findChild("b", sourceFile));
});
runSingleFileTest("deleteNodeInList6_1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeInList(sourceFile, findChild("c", sourceFile));
});
}
{
const text = `
function foo(a: number, b: string, c = true) {
return 1;
}`;
runSingleFileTest("deleteNodeInList7", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeInList(sourceFile, findChild("a", sourceFile));
});
runSingleFileTest("deleteNodeInList8", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeInList(sourceFile, findChild("b", sourceFile));
});
runSingleFileTest("deleteNodeInList9", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeInList(sourceFile, findChild("c", sourceFile));
});
}
{
const text = `
function foo(a: number,b: string,c = true) {
return 1;
}`;
runSingleFileTest("deleteNodeInList10", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeInList(sourceFile, findChild("a", sourceFile));
});
runSingleFileTest("deleteNodeInList11", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeInList(sourceFile, findChild("b", sourceFile));
});
runSingleFileTest("deleteNodeInList12", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeInList(sourceFile, findChild("c", sourceFile));
});
}
{
const text = `
function foo(
a: number,
b: string,
c = true) {
return 1;
}`;
runSingleFileTest("deleteNodeInList13", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeInList(sourceFile, findChild("a", sourceFile));
});
runSingleFileTest("deleteNodeInList14", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeInList(sourceFile, findChild("b", sourceFile));
});
runSingleFileTest("deleteNodeInList15", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNodeInList(sourceFile, findChild("c", sourceFile));
});
}
{
const text = `
const x = 1, y = 2;`;
runSingleFileTest("insertNodeInListAfter1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
});
runSingleFileTest("insertNodeInListAfter2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
});
}
{
const text = `
const /*x*/ x = 1, /*y*/ y = 2;`;
runSingleFileTest("insertNodeInListAfter3", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
});
runSingleFileTest("insertNodeInListAfter4", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
});
}
{
const text = `
const x = 1;`;
runSingleFileTest("insertNodeInListAfter5", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
});
}
{
const text = `
const x = 1,
y = 2;`;
runSingleFileTest("insertNodeInListAfter6", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
});
runSingleFileTest("insertNodeInListAfter7", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
});
}
{
const text = `
const /*x*/ x = 1,
/*y*/ y = 2;`;
runSingleFileTest("insertNodeInListAfter8", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
});
runSingleFileTest("insertNodeInListAfter9", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1)));
});
}
{
const text = `
import {
x
} from "bar"`;
runSingleFileTest("insertNodeInListAfter10", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(createIdentifier("b"), createIdentifier("a")));
})
}
{
const text = `
import {
x // this is x
} from "bar"`;
runSingleFileTest("insertNodeInListAfter11", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(createIdentifier("b"), createIdentifier("a")));
})
}
{
const text = `
import {
x
} from "bar"`;
runSingleFileTest("insertNodeInListAfter12", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a")));
})
}
{
const text = `
import {
x // this is x
} from "bar"`;
runSingleFileTest("insertNodeInListAfter13", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a")));
})
}
{
const text = `
import {
x0,
x
} from "bar"`;
runSingleFileTest("insertNodeInListAfter14", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(createIdentifier("b"), createIdentifier("a")));
})
}
{
const text = `
import {
x0,
x // this is x
} from "bar"`;
runSingleFileTest("insertNodeInListAfter15", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(createIdentifier("b"), createIdentifier("a")));
})
}
{
const text = `
import {
x0,
x
} from "bar"`;
runSingleFileTest("insertNodeInListAfter16", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a")));
})
}
{
const text = `
import {
x0,
x // this is x
} from "bar"`;
runSingleFileTest("insertNodeInListAfter17", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a")));
})
}
{
const text = `
import {
x0, x
} from "bar"`;
runSingleFileTest("insertNodeInListAfter18", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createImportSpecifier(undefined, createIdentifier("a")));
})
}
{
const text = `
class A {
x;
}`;
runSingleFileTest("insertNodeAfterMultipleNodes", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
let newNodes = [];
for (let i = 0; i < 11 /*error doesn't occur with fewer nodes*/; ++i) {
newNodes.push(
createProperty(undefined, undefined, i + "", undefined, undefined, undefined));
}
const insertAfter = findChild("x", sourceFile);
for (const newNode of newNodes) {
changeTracker.insertNodeAfter(sourceFile, insertAfter, newNode, { suffix: newLineCharacter });
}
});
}
{
const text = `
class A {
x
}
`;
runSingleFileTest("insertNodeAfterInClass1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), createProperty(undefined, undefined, "a", undefined, createKeywordTypeNode(SyntaxKind.BooleanKeyword), undefined), { suffix: newLineCharacter });
});
}
{
const text = `
class A {
x;
}
`;
runSingleFileTest("insertNodeAfterInClass2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), createProperty(undefined, undefined, "a", undefined, createKeywordTypeNode(SyntaxKind.BooleanKeyword), undefined), { suffix: newLineCharacter });
});
}
{
const text = `
class A {
x;
y = 1;
}
`;
runSingleFileTest("deleteNodeAfterInClass1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNode(sourceFile, findChild("x", sourceFile));
});
}
{
const text = `
class A {
x
y = 1;
}
`;
runSingleFileTest("deleteNodeAfterInClass2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.deleteNode(sourceFile, findChild("x", sourceFile));
});
}
{
const text = `
class A {
x = foo
}
`
runSingleFileTest("insertNodeInClassAfterNodeWithoutSeparator1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
const newNode = createProperty(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createComputedPropertyName(createLiteral(1)),
/*questionToken*/ undefined,
createKeywordTypeNode(SyntaxKind.AnyKeyword),
/*initializer*/ undefined);
changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode, { suffix: newLineCharacter });
});
}
{
const text = `
class A {
x() {
}
}
`
runSingleFileTest("insertNodeInClassAfterNodeWithoutSeparator2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
const newNode = createProperty(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createComputedPropertyName(createLiteral(1)),
/*questionToken*/ undefined,
createKeywordTypeNode(SyntaxKind.AnyKeyword),
/*initializer*/ undefined);
changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode, { suffix: newLineCharacter });
});
}
{
const text = `
interface A {
x
}
`
runSingleFileTest("insertNodeInInterfaceAfterNodeWithoutSeparator1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
const newNode = createProperty(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createComputedPropertyName(createLiteral(1)),
/*questionToken*/ undefined,
createKeywordTypeNode(SyntaxKind.AnyKeyword),
/*initializer*/ undefined);
changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode, { suffix: newLineCharacter });
});
}
{
const text = `
interface A {
x()
}
`
runSingleFileTest("insertNodeInInterfaceAfterNodeWithoutSeparator2", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
const newNode = createProperty(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createComputedPropertyName(createLiteral(1)),
/*questionToken*/ undefined,
createKeywordTypeNode(SyntaxKind.AnyKeyword),
/*initializer*/ undefined);
changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode, { suffix: newLineCharacter });
});
}
{
const text = `
let x = foo
`
runSingleFileTest("insertNodeInStatementListAfterNodeWithoutSeparator1", noop, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
const newNode = createStatement(createParen(createLiteral(1)));
changeTracker.insertNodeAfter(sourceFile, findVariableStatementContaining("x", sourceFile), newNode, { suffix: newLineCharacter });
});
}
});
}

View File

@ -65,6 +65,6 @@ namespace ts.textStorage {
ts1.getLineInfo(0);
assert.isTrue(ts1.hasScriptVersionCache(), "have script version cache - 2");
})
});
});
}

View File

@ -1,4 +1,4 @@
/// <reference path="..\harness.ts" />
/// <reference path="..\harness.ts" />
/// <reference path="../../server/typingsInstaller/typingsInstaller.ts" />
namespace ts.projectSystem {
@ -628,7 +628,7 @@ namespace ts.projectSystem {
checkProjectActualFiles(service.configuredProjects[0], []);
checkProjectActualFiles(service.inferredProjects[0], [f1.path]);
})
});
it("create configured project without file list", () => {
const configFile: FileOrFolder = {
@ -1181,7 +1181,7 @@ namespace ts.projectSystem {
const host = createServerHost([f1, f2, libFile]);
const service = createProjectService(host);
service.openExternalProject({ projectFileName: "/a/b/project", rootFiles: toExternalFiles([f1.path, f2.path]), options: {} })
service.openExternalProject({ projectFileName: "/a/b/project", rootFiles: toExternalFiles([f1.path, f2.path]), options: {} });
service.openClientFile(f1.path);
service.openClientFile(f2.path, "let x: string");
@ -1213,7 +1213,7 @@ namespace ts.projectSystem {
const host = createServerHost([f1, f2, libFile]);
const service = createProjectService(host);
service.openExternalProject({ projectFileName: "/a/b/project", rootFiles: [{ fileName: f1.path }, { fileName: f2.path, hasMixedContent: true }], options: {} })
service.openExternalProject({ projectFileName: "/a/b/project", rootFiles: [{ fileName: f1.path }, { fileName: f2.path, hasMixedContent: true }], options: {} });
service.openClientFile(f1.path);
service.openClientFile(f2.path, "let somelongname: string");
@ -2040,7 +2040,7 @@ namespace ts.projectSystem {
for (const f of [f2, f3]) {
const scriptInfo = projectService.getScriptInfoForNormalizedPath(server.toNormalizedPath(f.path));
assert.equal(scriptInfo.containingProjects.length, 0, `expect 0 containing projects for '${f.path}'`)
assert.equal(scriptInfo.containingProjects.length, 0, `expect 0 containing projects for '${f.path}'`);
}
});
@ -2156,7 +2156,7 @@ namespace ts.projectSystem {
projectFileName,
rootFiles: [toExternalFile(f1.path)],
options: {}
})
});
projectService.openClientFile(f1.path, "let x = 1;\nlet y = 2;");
projectService.checkNumberOfProjects({ externalProjects: 1 });
@ -3307,12 +3307,12 @@ namespace ts.projectSystem {
isCancellationRequested: () => false,
setRequest: requestId => {
if (expectedRequestId === undefined) {
assert.isTrue(false, "unexpected call")
assert.isTrue(false, "unexpected call");
}
assert.equal(requestId, expectedRequestId);
},
resetRequest: noop
}
};
const session = createSession(host, /*typingsInstaller*/ undefined, /*projectServiceEventHandler*/ undefined, cancellationToken);
expectedRequestId = session.getNextSeq();
@ -3359,13 +3359,13 @@ namespace ts.projectSystem {
currentId = requestId;
},
resetRequest(requestId) {
assert.equal(requestId, currentId, "unexpected request id in cancellation")
assert.equal(requestId, currentId, "unexpected request id in cancellation");
currentId = undefined;
},
isCancellationRequested() {
return requestToCancel === currentId;
}
}
};
})();
const host = createServerHost([f1, config]);
const session = createSession(host, /*typingsInstaller*/ undefined, () => {}, cancellationToken);
@ -3489,6 +3489,52 @@ namespace ts.projectSystem {
});
});
describe("occurence highlight on string", () => {
it("should be marked if only on string values", () => {
const file1: FileOrFolder = {
path: "/a/b/file1.ts",
content: `let t1 = "div";\nlet t2 = "div";\nlet t3 = { "div": 123 };\nlet t4 = t3["div"];`
};
const host = createServerHost([file1]);
const session = createSession(host);
const projectService = session.getProjectService();
projectService.openClientFile(file1.path);
{
const highlightRequest = makeSessionRequest<protocol.FileLocationRequestArgs>(
CommandNames.Occurrences,
{ file: file1.path, line: 1, offset: 11 }
);
const highlightResponse = session.executeCommand(highlightRequest).response as protocol.OccurrencesResponseItem[];
const firstOccurence = highlightResponse[0];
assert.isTrue(firstOccurence.isInString, "Highlights should be marked with isInString");
}
{
const highlightRequest = makeSessionRequest<protocol.FileLocationRequestArgs>(
CommandNames.Occurrences,
{ file: file1.path, line: 3, offset: 13 }
);
const highlightResponse = session.executeCommand(highlightRequest).response as protocol.OccurrencesResponseItem[];
assert.isTrue(highlightResponse.length === 2);
const firstOccurence = highlightResponse[0];
assert.isUndefined(firstOccurence.isInString, "Highlights should not be marked with isInString if on property name");
}
{
const highlightRequest = makeSessionRequest<protocol.FileLocationRequestArgs>(
CommandNames.Occurrences,
{ file: file1.path, line: 4, offset: 14 }
);
const highlightResponse = session.executeCommand(highlightRequest).response as protocol.OccurrencesResponseItem[];
assert.isTrue(highlightResponse.length === 2);
const firstOccurence = highlightResponse[0];
assert.isUndefined(firstOccurence.isInString, "Highlights should not be marked with isInString if on indexer");
}
});
});
describe("maxNodeModuleJsDepth for inferred projects", () => {
it("should be set to 2 if the project has js root files", () => {
const file1: FileOrFolder = {

View File

@ -1,4 +1,4 @@
/// <reference path="../harness.ts" />
/// <reference path="../harness.ts" />
/// <reference path="./tsserverProjectSystem.ts" />
/// <reference path="../../server/typingsInstaller/typingsInstaller.ts" />
@ -56,7 +56,7 @@ namespace ts.projectSystem {
path: "/a/config.js",
content: "export let x = 1"
};
const typesCache = "/cache"
const typesCache = "/cache";
const typesConfig = {
path: typesCache + "/node_modules/@types/config/index.d.ts",
content: "export let y: number;"
@ -74,7 +74,7 @@ namespace ts.projectSystem {
super(host, { typesRegistry: createTypesRegistry("config"), globalTypingsCacheLocation: typesCache });
}
installWorker(_requestId: number, _args: string[], _cwd: string, _cb: server.typingsInstaller.RequestCompletedAction) {
assert(false, "should not be called")
assert(false, "should not be called");
}
})();
const service = createProjectService(host, { typingsInstaller: installer });

View File

@ -5,9 +5,53 @@ interface DOMTokenList {
}
interface NodeList {
/**
* Returns an array of key, value pairs for every entry in the list
*/
entries(): IterableIterator<[number, Node]>;
/**
* Performs the specified action for each node in an list.
* @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the list.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
forEach(callbackfn: (value: Node, index: number, listObj: NodeList) => void, thisArg?: any): void;
/**
* Returns an list of keys in the list
*/
keys(): IterableIterator<number>;
/**
* Returns an list of values in the list
*/
values(): IterableIterator<Node>;
[Symbol.iterator](): IterableIterator<Node>
}
interface NodeListOf<TNode extends Node> {
/**
* Returns an array of key, value pairs for every entry in the list
*/
entries(): IterableIterator<[number, TNode]>;
/**
* Performs the specified action for each node in an list.
* @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the list.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
forEach(callbackfn: (value: TNode, index: number, listObj: NodeListOf<TNode>) => void, thisArg?: any): void;
/**
* Returns an list of keys in the list
*/
keys(): IterableIterator<number>;
/**
* Returns an list of values in the list
*/
values(): IterableIterator<TNode>;
[Symbol.iterator](): IterableIterator<TNode>
}

View File

@ -10,7 +10,9 @@ interface Array<T> {
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
find(predicate: (value: T, index: number, obj: Array<T>) => boolean, thisArg?: any): T | undefined;
find(predicate: (this: undefined, value: T, index: number, obj: Array<T>) => boolean): T | undefined;
find(predicate: (this: undefined, value: T, index: number, obj: Array<T>) => boolean, thisArg: undefined): T | undefined;
find<Z>(predicate: (this: Z, value: T, index: number, obj: Array<T>) => boolean, thisArg: Z): T | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@ -21,7 +23,9 @@ interface Array<T> {
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
findIndex(predicate: (value: T, index: number, obj: Array<T>) => boolean, thisArg?: any): number;
findIndex(predicate: (this: undefined, value: T, index: number, obj: Array<T>) => boolean): number;
findIndex(predicate: (this: undefined, value: T, index: number, obj: Array<T>) => boolean, thisArg: undefined): number;
findIndex<Z>(predicate: (this: Z, value: T, index: number, obj: Array<T>) => boolean, thisArg: Z): number;
/**
* Returns the this object after filling the section identified by start and end with value
@ -52,7 +56,9 @@ interface ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from<T, U>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: any): Array<U>;
from<T, U>(arrayLike: ArrayLike<T>, mapfn: (this: undefined, v: T, k: number) => U): Array<U>;
from<T, U>(arrayLike: ArrayLike<T>, mapfn: (this: undefined, v: T, k: number) => U, thisArg: undefined): Array<U>;
from<Z, T, U>(arrayLike: ArrayLike<T>, mapfn: (this: Z, v: T, k: number) => U, thisArg: Z): Array<U>;
/**
@ -357,7 +363,9 @@ interface ReadonlyArray<T> {
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
find(predicate: (value: T, index: number, obj: ReadonlyArray<T>) => boolean, thisArg?: any): T | undefined;
find(predicate: (this: undefined, value: T, index: number, obj: ReadonlyArray<T>) => boolean): T | undefined;
find(predicate: (this: undefined, value: T, index: number, obj: ReadonlyArray<T>) => boolean, thisArg: undefined): T | undefined;
find<Z>(predicate: (this: Z, value: T, index: number, obj: ReadonlyArray<T>) => boolean, thisArg: Z): T | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@ -368,7 +376,9 @@ interface ReadonlyArray<T> {
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
findIndex(predicate: (value: T, index: number, obj: Array<T>) => boolean, thisArg?: any): number;
findIndex(predicate: (this: undefined, value: T, index: number, obj: Array<T>) => boolean): number;
findIndex(predicate: (this: undefined, value: T, index: number, obj: Array<T>) => boolean, thisArg: undefined): number;
findIndex<Z>(predicate: (this: Z, value: T, index: number, obj: Array<T>) => boolean, thisArg: Z): number;
}
interface RegExp {

View File

@ -54,7 +54,9 @@ interface ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from<T, U>(iterable: Iterable<T>, mapfn: (v: T, k: number) => U, thisArg?: any): Array<U>;
from<T, U>(iterable: Iterable<T>, mapfn: (this: undefined, v: T, k: number) => U): Array<U>;
from<T, U>(iterable: Iterable<T>, mapfn: (this: undefined, v: T, k: number) => U, thisArg: undefined): Array<U>;
from<Z, T, U>(iterable: Iterable<T>, mapfn: (this: Z, v: T, k: number) => U, thisArg: Z): Array<U>;
/**
* Creates an array from an iterable object.
@ -180,7 +182,11 @@ interface Int8ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int8Array;
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Int8Array;
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Int8Array;
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int8Array;
from(arrayLike: Iterable<number>): Int8Array;
}
/**
@ -212,7 +218,11 @@ interface Uint8ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8Array;
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Uint8Array;
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Uint8Array;
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint8Array;
from(arrayLike: Iterable<number>): Uint8Array;
}
/**
@ -247,7 +257,11 @@ interface Uint8ClampedArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8ClampedArray;
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Uint8ClampedArray;
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Uint8ClampedArray;
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint8ClampedArray;
from(arrayLike: Iterable<number>): Uint8ClampedArray;
}
/**
@ -281,7 +295,11 @@ interface Int16ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int16Array;
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Int16Array;
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Int16Array;
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int16Array;
from(arrayLike: Iterable<number>): Int16Array;
}
/**
@ -313,7 +331,11 @@ interface Uint16ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint16Array;
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Uint16Array;
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Uint16Array;
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint16Array;
from(arrayLike: Iterable<number>): Uint16Array;
}
/**
@ -345,7 +367,11 @@ interface Int32ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int32Array;
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Int32Array;
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Int32Array;
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int32Array;
from(arrayLike: Iterable<number>): Int32Array;
}
/**
@ -377,7 +403,11 @@ interface Uint32ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint32Array;
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Uint32Array;
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Uint32Array;
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint32Array;
from(arrayLike: Iterable<number>): Uint32Array;
}
/**
@ -409,7 +439,11 @@ interface Float32ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Float32Array;
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Float32Array;
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Float32Array;
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Float32Array;
from(arrayLike: Iterable<number>): Float32Array;
}
/**
@ -441,5 +475,9 @@ interface Float64ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Float64Array;
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number): Float64Array;
from(arrayLike: Iterable<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Float64Array;
from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Float64Array;
from(arrayLike: Iterable<number>): Float64Array;
}

424
src/lib/es5.d.ts vendored
View File

@ -147,7 +147,7 @@ interface ObjectConstructor {
* @param o Object to use as a prototype. May be null
* @param properties JavaScript object that contains one or more property descriptors.
*/
create(o: object | null, properties: PropertyDescriptorMap): any;
create(o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any;
/**
* Adds a property to an object, or modifies attributes of an existing property.
@ -155,14 +155,14 @@ interface ObjectConstructor {
* @param p The property name.
* @param attributes Descriptor for the property. It can be for a data property or an accessor property.
*/
defineProperty(o: any, p: string, attributes: PropertyDescriptor): any;
defineProperty(o: any, p: string, attributes: PropertyDescriptor & ThisType<any>): any;
/**
* Adds one or more properties to an object, and/or modifies attributes of existing properties.
* @param o Object on which to add or modify the properties. This can be a native JavaScript object or a DOM object.
* @param properties JavaScript object that contains one or more descriptor objects. Each descriptor object describes a data property or an accessor property.
*/
defineProperties(o: any, properties: PropertyDescriptorMap): any;
defineProperties(o: any, properties: PropertyDescriptorMap & ThisType<any>): any;
/**
* Prevents the modification of attributes of existing properties, and prevents the addition of new properties.
@ -325,53 +325,27 @@ interface String {
* Matches a string with a regular expression, and returns an array containing the results of that search.
* @param regexp A variable name or string literal containing the regular expression pattern and flags.
*/
match(regexp: string): RegExpMatchArray | null;
/**
* Matches a string with a regular expression, and returns an array containing the results of that search.
* @param regexp A regular expression object that contains the regular expression pattern and applicable flags.
*/
match(regexp: RegExp): RegExpMatchArray | null;
match(regexp: string | RegExp): RegExpMatchArray | null;
/**
* Replaces text in a string, using a regular expression or search string.
* @param searchValue A string to search for.
* @param replaceValue A string containing the text to replace for every successful match of searchValue in this string.
*/
replace(searchValue: string, replaceValue: string): string;
replace(searchValue: string | RegExp, replaceValue: string): string;
/**
* Replaces text in a string, using a regular expression or search string.
* @param searchValue A string to search for.
* @param replacer A function that returns the replacement text.
*/
replace(searchValue: string, replacer: (substring: string, ...args: any[]) => string): string;
/**
* Replaces text in a string, using a regular expression or search string.
* @param searchValue A Regular Expression object containing the regular expression pattern and applicable flags.
* @param replaceValue A string containing the text to replace for every successful match of searchValue in this string.
*/
replace(searchValue: RegExp, replaceValue: string): string;
/**
* Replaces text in a string, using a regular expression or search string.
* @param searchValue A Regular Expression object containing the regular expression pattern and applicable flags
* @param replacer A function that returns the replacement text.
*/
replace(searchValue: RegExp, replacer: (substring: string, ...args: any[]) => string): string;
replace(searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string;
/**
* Finds the first substring match in a regular expression search.
* @param regexp The regular expression pattern and applicable flags.
*/
search(regexp: string): number;
/**
* Finds the first substring match in a regular expression search.
* @param regexp The regular expression pattern and applicable flags.
*/
search(regexp: RegExp): number;
search(regexp: string | RegExp): number;
/**
* Returns a section of a string.
@ -386,14 +360,7 @@ interface String {
* @param separator A string that identifies character or characters to use in separating the string. If omitted, a single-element array containing the entire string is returned.
* @param limit A value used to limit the number of elements returned in the array.
*/
split(separator: string, limit?: number): string[];
/**
* Split a string into substrings using the specified separator and return them as an array.
* @param separator A Regular Express that identifies character or characters to use in separating the string. If omitted, a single-element array containing the entire string is returned.
* @param limit A value used to limit the number of elements returned in the array.
*/
split(separator: RegExp, limit?: number): string[];
split(separator: string | RegExp, limit?: number): string[];
/**
* Returns the substring at the specified location within a String object.
@ -861,9 +828,9 @@ interface RegExp {
}
interface RegExpConstructor {
new (pattern: RegExp): RegExp;
new (pattern: RegExp | string): RegExp;
new (pattern: string, flags?: string): RegExp;
(pattern: RegExp): RegExp;
(pattern: RegExp | string): RegExp;
(pattern: string, flags?: string): RegExp;
readonly prototype: RegExp;
@ -1050,37 +1017,49 @@ interface ReadonlyArray<T> {
* @param callbackfn A function that accepts up to three arguments. The every method calls the callbackfn function for each element in array1 until the callbackfn returns false, or until the end of the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
every(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => boolean, thisArg?: any): boolean;
every(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => boolean): boolean;
every(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => boolean, thisArg: undefined): boolean;
every<Z>(callbackfn: (this: Z, value: T, index: number, array: ReadonlyArray<T>) => boolean, thisArg: Z): boolean;
/**
* Determines whether the specified callback function returns true for any element of an array.
* @param callbackfn A function that accepts up to three arguments. The some method calls the callbackfn function for each element in array1 until the callbackfn returns true, or until the end of the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
some(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => boolean, thisArg?: any): boolean;
some(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => boolean): boolean;
some(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => boolean, thisArg: undefined): boolean;
some<Z>(callbackfn: (this: Z, value: T, index: number, array: ReadonlyArray<T>) => boolean, thisArg: Z): boolean;
/**
* Performs the specified action for each element in an array.
* @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
forEach(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => void, thisArg?: any): void;
forEach(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => void): void;
forEach(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => void, thisArg: undefined): void;
forEach<Z>(callbackfn: (this: Z, value: T, index: number, array: ReadonlyArray<T>) => void, thisArg: Z): void;
/**
* Calls a defined callback function on each element of an array, and returns an array that contains the results.
* @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
map<U>(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => U, thisArg?: any): U[];
map<U>(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => U): U[];
map<U>(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => U, thisArg: undefined): U[];
map<Z, U>(callbackfn: (this: Z, value: T, index: number, array: ReadonlyArray<T>) => U, thisArg: Z): U[];
/**
* Returns the elements of an array that meet the condition specified in a callback function.
* @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
filter<S extends T>(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => value is S, thisArg?: any): S[];
filter<S extends T>(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => value is S): S[];
filter<S extends T>(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => value is S, thisArg: undefined): S[];
filter<Z, S extends T>(callbackfn: (this: Z, value: T, index: number, array: ReadonlyArray<T>) => value is S, thisArg: Z): S[];
/**
* Returns the elements of an array that meet the condition specified in a callback function.
* @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
filter(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => any, thisArg?: any): T[];
filter(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => any): T[];
filter(callbackfn: (this: undefined, value: T, index: number, array: ReadonlyArray<T>) => any, thisArg: undefined): T[];
filter<Z>(callbackfn: (this: Z, value: T, index: number, array: ReadonlyArray<T>) => any, thisArg: Z): T[];
/**
* Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
* @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
@ -1197,55 +1176,73 @@ interface Array<T> {
* @param callbackfn A function that accepts up to three arguments. The every method calls the callbackfn function for each element in array1 until the callbackfn returns false, or until the end of the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean;
every(callbackfn: (this: undefined, value: T, index: number, array: T[]) => boolean): boolean;
every(callbackfn: (this: undefined, value: T, index: number, array: T[]) => boolean, thisArg: undefined): boolean;
every<Z>(callbackfn: (this: Z, value: T, index: number, array: T[]) => boolean, thisArg: Z): boolean;
/**
* Determines whether the specified callback function returns true for any element of an array.
* @param callbackfn A function that accepts up to three arguments. The some method calls the callbackfn function for each element in array1 until the callbackfn returns true, or until the end of the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean;
some(callbackfn: (this: undefined, value: T, index: number, array: T[]) => boolean): boolean;
some(callbackfn: (this: undefined, value: T, index: number, array: T[]) => boolean, thisArg: undefined): boolean;
some<Z>(callbackfn: (this: Z, value: T, index: number, array: T[]) => boolean, thisArg: Z): boolean;
/**
* Performs the specified action for each element in an array.
* @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void;
forEach(callbackfn: (this: undefined, value: T, index: number, array: T[]) => void): void;
forEach(callbackfn: (this: undefined, value: T, index: number, array: T[]) => void, thisArg: undefined): void;
forEach<Z>(callbackfn: (this: Z, value: T, index: number, array: T[]) => void, thisArg: Z): void;
/**
* Calls a defined callback function on each element of an array, and returns an array that contains the results.
* @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
map<U>(this: [T, T, T, T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U, U, U, U];
map<U>(this: [T, T, T, T, T], callbackfn: (this: undefined, value: T, index: number, array: T[]) => U): [U, U, U, U, U];
map<U>(this: [T, T, T, T, T], callbackfn: (this: undefined, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U, U, U, U];
map<Z, U>(this: [T, T, T, T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U, U, U, U];
/**
* Calls a defined callback function on each element of an array, and returns an array that contains the results.
* @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
map<U>(this: [T, T, T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U, U, U];
map<U>(this: [T, T, T, T], callbackfn: (this: undefined, value: T, index: number, array: T[]) => U): [U, U, U, U];
map<U>(this: [T, T, T, T], callbackfn: (this: undefined, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U, U, U];
map<Z, U>(this: [T, T, T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U, U, U];
/**
* Calls a defined callback function on each element of an array, and returns an array that contains the results.
* @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
map<U>(this: [T, T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U, U];
map<U>(this: [T, T, T], callbackfn: (this: undefined, value: T, index: number, array: T[]) => U): [U, U, U];
map<U>(this: [T, T, T], callbackfn: (this: undefined, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U, U];
map<Z, U>(this: [T, T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U, U];
/**
* Calls a defined callback function on each element of an array, and returns an array that contains the results.
* @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
map<U>(this: [T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U];
map<U>(this: [T, T], callbackfn: (this: undefined, value: T, index: number, array: T[]) => U): [U, U];
map<U>(this: [T, T], callbackfn: (this: undefined, value: T, index: number, array: T[]) => U, thisArg: undefined): [U, U];
map<Z, U>(this: [T, T], callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): [U, U];
/**
* Calls a defined callback function on each element of an array, and returns an array that contains the results.
* @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];
map<U>(callbackfn: (this: undefined, value: T, index: number, array: T[]) => U): U[];
map<U>(callbackfn: (this: undefined, value: T, index: number, array: T[]) => U, thisArg: undefined): U[];
map<Z, U>(callbackfn: (this: Z, value: T, index: number, array: T[]) => U, thisArg: Z): U[];
/**
* Returns the elements of an array that meet the condition specified in a callback function.
* @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[];
filter(callbackfn: (this: undefined, value: T, index: number, array: T[]) => any): T[];
filter(callbackfn: (this: undefined, value: T, index: number, array: T[]) => any, thisArg: undefined): T[];
filter<Z>(callbackfn: (this: Z, value: T, index: number, array: T[]) => any, thisArg: Z): T[];
/**
* Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
* @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
@ -1366,6 +1363,11 @@ type Record<K extends string, T> = {
[P in K]: T;
}
/**
* Marker for contextual 'this' type
*/
interface ThisType<T> { }
/**
* Represents a raw buffer of binary data, which is used to store data for the
* different typed arrays. ArrayBuffers cannot be read from or written to directly,
@ -1585,7 +1587,9 @@ interface Int8Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
every(callbackfn: (value: number, index: number, array: Int8Array) => boolean, thisArg?: any): boolean;
every(callbackfn: (this: undefined, value: number, index: number, array: Int8Array) => boolean): boolean;
every(callbackfn: (this: undefined, value: number, index: number, array: Int8Array) => boolean, thisArg: undefined): boolean;
every<Z>(callbackfn: (this: Z, value: number, index: number, array: Int8Array) => boolean, thisArg: Z): boolean;
/**
* Returns the this object after filling the section identified by start and end with value
@ -1604,7 +1608,9 @@ interface Int8Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
filter(callbackfn: (value: number, index: number, array: Int8Array) => any, thisArg?: any): Int8Array;
filter(callbackfn: (this: undefined, value: number, index: number, array: Int8Array) => any): Int8Array;
filter(callbackfn: (this: undefined, value: number, index: number, array: Int8Array) => any, thisArg: undefined): Int8Array;
filter<Z>(callbackfn: (this: Z, value: number, index: number, array: Int8Array) => any, thisArg: Z): Int8Array;
/**
* Returns the value of the first element in the array where predicate is true, and undefined
@ -1615,7 +1621,9 @@ interface Int8Array {
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number | undefined;
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number | undefined;
find<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@ -1626,7 +1634,9 @@ interface Int8Array {
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number;
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number;
findIndex<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number;
/**
* Performs the specified action for each element in an array.
@ -1635,7 +1645,9 @@ interface Int8Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
forEach(callbackfn: (value: number, index: number, array: Int8Array) => void, thisArg?: any): void;
forEach(callbackfn: (this: undefined, value: number, index: number, array: Int8Array) => void): void;
forEach(callbackfn: (this: undefined, value: number, index: number, array: Int8Array) => void, thisArg: undefined): void;
forEach<Z>(callbackfn: (this: Z, value: number, index: number, array: Int8Array) => void, thisArg: Z): void;
/**
* Returns the index of the first occurrence of a value in an array.
@ -1673,7 +1685,9 @@ interface Int8Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
map(callbackfn: (value: number, index: number, array: Int8Array) => number, thisArg?: any): Int8Array;
map(callbackfn: (this: undefined, value: number, index: number, array: Int8Array) => number): Int8Array;
map(callbackfn: (this: undefined, value: number, index: number, array: Int8Array) => number, thisArg: undefined): Int8Array;
map<Z>(callbackfn: (this: Z, value: number, index: number, array: Int8Array) => number, thisArg: Z): Int8Array;
/**
* Calls the specified callback function for all the elements in an array. The return value of
@ -1757,7 +1771,9 @@ interface Int8Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
some(callbackfn: (value: number, index: number, array: Int8Array) => boolean, thisArg?: any): boolean;
some(callbackfn: (this: undefined, value: number, index: number, array: Int8Array) => boolean): boolean;
some(callbackfn: (this: undefined, value: number, index: number, array: Int8Array) => boolean, thisArg: undefined): boolean;
some<Z>(callbackfn: (this: Z, value: number, index: number, array: Int8Array) => boolean, thisArg: Z): boolean;
/**
* Sorts an array.
@ -1809,7 +1825,11 @@ interface Int8ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int8Array;
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number): Int8Array;
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Int8Array;
from<Z>(arrayLike: ArrayLike<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int8Array;
from(arrayLike: ArrayLike<number>): Int8Array;
}
declare const Int8Array: Int8ArrayConstructor;
@ -1858,7 +1878,9 @@ interface Uint8Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
every(callbackfn: (value: number, index: number, array: Uint8Array) => boolean, thisArg?: any): boolean;
every(callbackfn: (this: undefined, value: number, index: number, array: Uint8Array) => boolean): boolean;
every(callbackfn: (this: undefined, value: number, index: number, array: Uint8Array) => boolean, thisArg: undefined): boolean;
every<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint8Array) => boolean, thisArg: Z): boolean;
/**
* Returns the this object after filling the section identified by start and end with value
@ -1877,7 +1899,9 @@ interface Uint8Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
filter(callbackfn: (value: number, index: number, array: Uint8Array) => any, thisArg?: any): Uint8Array;
filter(callbackfn: (this: undefined, value: number, index: number, array: Uint8Array) => any): Uint8Array;
filter(callbackfn: (this: undefined, value: number, index: number, array: Uint8Array) => any, thisArg: undefined): Uint8Array;
filter<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint8Array) => any, thisArg: Z): Uint8Array;
/**
* Returns the value of the first element in the array where predicate is true, and undefined
@ -1888,7 +1912,9 @@ interface Uint8Array {
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number | undefined;
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number | undefined;
find<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@ -1899,7 +1925,9 @@ interface Uint8Array {
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number;
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number;
findIndex<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number;
/**
* Performs the specified action for each element in an array.
@ -1908,7 +1936,9 @@ interface Uint8Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
forEach(callbackfn: (value: number, index: number, array: Uint8Array) => void, thisArg?: any): void;
forEach(callbackfn: (this: undefined, value: number, index: number, array: Uint8Array) => void): void;
forEach(callbackfn: (this: undefined, value: number, index: number, array: Uint8Array) => void, thisArg: undefined): void;
forEach<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint8Array) => void, thisArg: Z): void;
/**
* Returns the index of the first occurrence of a value in an array.
@ -1946,7 +1976,9 @@ interface Uint8Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
map(callbackfn: (value: number, index: number, array: Uint8Array) => number, thisArg?: any): Uint8Array;
map(callbackfn: (this: undefined, value: number, index: number, array: Uint8Array) => number): Uint8Array;
map(callbackfn: (this: undefined, value: number, index: number, array: Uint8Array) => number, thisArg: undefined): Uint8Array;
map<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint8Array) => number, thisArg: Z): Uint8Array;
/**
* Calls the specified callback function for all the elements in an array. The return value of
@ -2030,7 +2062,9 @@ interface Uint8Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
some(callbackfn: (value: number, index: number, array: Uint8Array) => boolean, thisArg?: any): boolean;
some(callbackfn: (this: undefined, value: number, index: number, array: Uint8Array) => boolean): boolean;
some(callbackfn: (this: undefined, value: number, index: number, array: Uint8Array) => boolean, thisArg: undefined): boolean;
some<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint8Array) => boolean, thisArg: Z): boolean;
/**
* Sorts an array.
@ -2083,7 +2117,11 @@ interface Uint8ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8Array;
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number): Uint8Array;
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Uint8Array;
from<Z>(arrayLike: ArrayLike<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint8Array;
from(arrayLike: ArrayLike<number>): Uint8Array;
}
declare const Uint8Array: Uint8ArrayConstructor;
@ -2132,7 +2170,9 @@ interface Uint8ClampedArray {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
every(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg?: any): boolean;
every(callbackfn: (this: undefined, value: number, index: number, array: Uint8ClampedArray) => boolean): boolean;
every(callbackfn: (this: undefined, value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg: undefined): boolean;
every<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg: Z): boolean;
/**
* Returns the this object after filling the section identified by start and end with value
@ -2151,7 +2191,9 @@ interface Uint8ClampedArray {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
filter(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => any, thisArg?: any): Uint8ClampedArray;
filter(callbackfn: (this: undefined, value: number, index: number, array: Uint8ClampedArray) => any): Uint8ClampedArray;
filter(callbackfn: (this: undefined, value: number, index: number, array: Uint8ClampedArray) => any, thisArg: undefined): Uint8ClampedArray;
filter<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint8ClampedArray) => any, thisArg: Z): Uint8ClampedArray;
/**
* Returns the value of the first element in the array where predicate is true, and undefined
@ -2162,7 +2204,9 @@ interface Uint8ClampedArray {
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number | undefined;
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number | undefined;
find<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@ -2173,7 +2217,9 @@ interface Uint8ClampedArray {
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number;
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number;
findIndex<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number;
/**
* Performs the specified action for each element in an array.
@ -2182,7 +2228,9 @@ interface Uint8ClampedArray {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
forEach(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => void, thisArg?: any): void;
forEach(callbackfn: (this: undefined, value: number, index: number, array: Uint8ClampedArray) => void): void;
forEach(callbackfn: (this: undefined, value: number, index: number, array: Uint8ClampedArray) => void, thisArg: undefined): void;
forEach<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint8ClampedArray) => void, thisArg: Z): void;
/**
* Returns the index of the first occurrence of a value in an array.
@ -2220,7 +2268,9 @@ interface Uint8ClampedArray {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
map(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => number, thisArg?: any): Uint8ClampedArray;
map(callbackfn: (this: undefined, value: number, index: number, array: Uint8ClampedArray) => number): Uint8ClampedArray;
map(callbackfn: (this: undefined, value: number, index: number, array: Uint8ClampedArray) => number, thisArg: undefined): Uint8ClampedArray;
map<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint8ClampedArray) => number, thisArg: Z): Uint8ClampedArray;
/**
* Calls the specified callback function for all the elements in an array. The return value of
@ -2304,7 +2354,9 @@ interface Uint8ClampedArray {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
some(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg?: any): boolean;
some(callbackfn: (this: undefined, value: number, index: number, array: Uint8ClampedArray) => boolean): boolean;
some(callbackfn: (this: undefined, value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg: undefined): boolean;
some<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg: Z): boolean;
/**
* Sorts an array.
@ -2357,7 +2409,11 @@ interface Uint8ClampedArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8ClampedArray;
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number): Uint8ClampedArray;
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Uint8ClampedArray;
from<Z>(arrayLike: ArrayLike<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint8ClampedArray;
from(arrayLike: ArrayLike<number>): Uint8ClampedArray;
}
declare const Uint8ClampedArray: Uint8ClampedArrayConstructor;
@ -2405,7 +2461,9 @@ interface Int16Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
every(callbackfn: (value: number, index: number, array: Int16Array) => boolean, thisArg?: any): boolean;
every(callbackfn: (this: undefined, value: number, index: number, array: Int16Array) => boolean): boolean;
every(callbackfn: (this: undefined, value: number, index: number, array: Int16Array) => boolean, thisArg: undefined): boolean;
every<Z>(callbackfn: (this: Z, value: number, index: number, array: Int16Array) => boolean, thisArg: Z): boolean;
/**
* Returns the this object after filling the section identified by start and end with value
@ -2424,7 +2482,9 @@ interface Int16Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
filter(callbackfn: (value: number, index: number, array: Int16Array) => any, thisArg?: any): Int16Array;
filter(callbackfn: (this: undefined, value: number, index: number, array: Int16Array) => any): Int16Array;
filter(callbackfn: (this: undefined, value: number, index: number, array: Int16Array) => any, thisArg: undefined): Int16Array;
filter<Z>(callbackfn: (this: Z, value: number, index: number, array: Int16Array) => any, thisArg: Z): Int16Array;
/**
* Returns the value of the first element in the array where predicate is true, and undefined
@ -2435,7 +2495,9 @@ interface Int16Array {
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number | undefined;
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number | undefined;
find<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@ -2446,7 +2508,9 @@ interface Int16Array {
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number;
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number;
findIndex<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number;
/**
* Performs the specified action for each element in an array.
@ -2455,7 +2519,9 @@ interface Int16Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
forEach(callbackfn: (value: number, index: number, array: Int16Array) => void, thisArg?: any): void;
forEach(callbackfn: (this: undefined, value: number, index: number, array: Int16Array) => void): void;
forEach(callbackfn: (this: undefined, value: number, index: number, array: Int16Array) => void, thisArg: undefined): void;
forEach<Z>(callbackfn: (this: Z, value: number, index: number, array: Int16Array) => void, thisArg: Z): void;
/**
* Returns the index of the first occurrence of a value in an array.
@ -2493,7 +2559,9 @@ interface Int16Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
map(callbackfn: (value: number, index: number, array: Int16Array) => number, thisArg?: any): Int16Array;
map(callbackfn: (this: undefined, value: number, index: number, array: Int16Array) => number): Int16Array;
map(callbackfn: (this: undefined, value: number, index: number, array: Int16Array) => number, thisArg: undefined): Int16Array;
map<Z>(callbackfn: (this: Z, value: number, index: number, array: Int16Array) => number, thisArg: Z): Int16Array;
/**
* Calls the specified callback function for all the elements in an array. The return value of
@ -2577,7 +2645,9 @@ interface Int16Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
some(callbackfn: (value: number, index: number, array: Int16Array) => boolean, thisArg?: any): boolean;
some(callbackfn: (this: undefined, value: number, index: number, array: Int16Array) => boolean): boolean;
some(callbackfn: (this: undefined, value: number, index: number, array: Int16Array) => boolean, thisArg: undefined): boolean;
some<Z>(callbackfn: (this: Z, value: number, index: number, array: Int16Array) => boolean, thisArg: Z): boolean;
/**
* Sorts an array.
@ -2630,7 +2700,11 @@ interface Int16ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int16Array;
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number): Int16Array;
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Int16Array;
from<Z>(arrayLike: ArrayLike<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int16Array;
from(arrayLike: ArrayLike<number>): Int16Array;
}
declare const Int16Array: Int16ArrayConstructor;
@ -2679,7 +2753,9 @@ interface Uint16Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
every(callbackfn: (value: number, index: number, array: Uint16Array) => boolean, thisArg?: any): boolean;
every(callbackfn: (this: undefined, value: number, index: number, array: Uint16Array) => boolean): boolean;
every(callbackfn: (this: undefined, value: number, index: number, array: Uint16Array) => boolean, thisArg: undefined): boolean;
every<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint16Array) => boolean, thisArg: Z): boolean;
/**
* Returns the this object after filling the section identified by start and end with value
@ -2698,7 +2774,9 @@ interface Uint16Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
filter(callbackfn: (value: number, index: number, array: Uint16Array) => any, thisArg?: any): Uint16Array;
filter(callbackfn: (this: undefined, value: number, index: number, array: Uint16Array) => any): Uint16Array;
filter(callbackfn: (this: undefined, value: number, index: number, array: Uint16Array) => any, thisArg: undefined): Uint16Array;
filter<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint16Array) => any, thisArg: Z): Uint16Array;
/**
* Returns the value of the first element in the array where predicate is true, and undefined
@ -2709,7 +2787,9 @@ interface Uint16Array {
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number | undefined;
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number | undefined;
find<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@ -2720,7 +2800,9 @@ interface Uint16Array {
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number;
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number;
findIndex<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number;
/**
* Performs the specified action for each element in an array.
@ -2729,7 +2811,9 @@ interface Uint16Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
forEach(callbackfn: (value: number, index: number, array: Uint16Array) => void, thisArg?: any): void;
forEach(callbackfn: (this: undefined, value: number, index: number, array: Uint16Array) => void): void;
forEach(callbackfn: (this: undefined, value: number, index: number, array: Uint16Array) => void, thisArg: undefined): void;
forEach<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint16Array) => void, thisArg: Z): void;
/**
* Returns the index of the first occurrence of a value in an array.
@ -2767,7 +2851,9 @@ interface Uint16Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
map(callbackfn: (value: number, index: number, array: Uint16Array) => number, thisArg?: any): Uint16Array;
map(callbackfn: (this: undefined, value: number, index: number, array: Uint16Array) => number): Uint16Array;
map(callbackfn: (this: undefined, value: number, index: number, array: Uint16Array) => number, thisArg: undefined): Uint16Array;
map<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint16Array) => number, thisArg: Z): Uint16Array;
/**
* Calls the specified callback function for all the elements in an array. The return value of
@ -2851,7 +2937,9 @@ interface Uint16Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
some(callbackfn: (value: number, index: number, array: Uint16Array) => boolean, thisArg?: any): boolean;
some(callbackfn: (this: undefined, value: number, index: number, array: Uint16Array) => boolean): boolean;
some(callbackfn: (this: undefined, value: number, index: number, array: Uint16Array) => boolean, thisArg: undefined): boolean;
some<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint16Array) => boolean, thisArg: Z): boolean;
/**
* Sorts an array.
@ -2904,7 +2992,11 @@ interface Uint16ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint16Array;
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number): Uint16Array;
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Uint16Array;
from<Z>(arrayLike: ArrayLike<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint16Array;
from(arrayLike: ArrayLike<number>): Uint16Array;
}
declare const Uint16Array: Uint16ArrayConstructor;
@ -2952,7 +3044,9 @@ interface Int32Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
every(callbackfn: (value: number, index: number, array: Int32Array) => boolean, thisArg?: any): boolean;
every(callbackfn: (this: undefined, value: number, index: number, array: Int32Array) => boolean): boolean;
every(callbackfn: (this: undefined, value: number, index: number, array: Int32Array) => boolean, thisArg: undefined): boolean;
every<Z>(callbackfn: (this: Z, value: number, index: number, array: Int32Array) => boolean, thisArg: Z): boolean;
/**
* Returns the this object after filling the section identified by start and end with value
@ -2971,7 +3065,9 @@ interface Int32Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
filter(callbackfn: (value: number, index: number, array: Int32Array) => any, thisArg?: any): Int32Array;
filter(callbackfn: (this: undefined, value: number, index: number, array: Int32Array) => any): Int32Array;
filter(callbackfn: (this: undefined, value: number, index: number, array: Int32Array) => any, thisArg: undefined): Int32Array;
filter<Z>(callbackfn: (this: Z, value: number, index: number, array: Int32Array) => any, thisArg: Z): Int32Array;
/**
* Returns the value of the first element in the array where predicate is true, and undefined
@ -2982,7 +3078,9 @@ interface Int32Array {
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number | undefined;
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number | undefined;
find<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@ -2993,7 +3091,9 @@ interface Int32Array {
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number;
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number;
findIndex<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number;
/**
* Performs the specified action for each element in an array.
@ -3002,7 +3102,9 @@ interface Int32Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
forEach(callbackfn: (value: number, index: number, array: Int32Array) => void, thisArg?: any): void;
forEach(callbackfn: (this: undefined, value: number, index: number, array: Int32Array) => void): void;
forEach(callbackfn: (this: undefined, value: number, index: number, array: Int32Array) => void, thisArg: undefined): void;
forEach<Z>(callbackfn: (this: Z, value: number, index: number, array: Int32Array) => void, thisArg: Z): void;
/**
* Returns the index of the first occurrence of a value in an array.
@ -3040,7 +3142,9 @@ interface Int32Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
map(callbackfn: (value: number, index: number, array: Int32Array) => number, thisArg?: any): Int32Array;
map(callbackfn: (this: undefined, value: number, index: number, array: Int32Array) => number): Int32Array;
map(callbackfn: (this: undefined, value: number, index: number, array: Int32Array) => number, thisArg: undefined): Int32Array;
map<Z>(callbackfn: (this: Z, value: number, index: number, array: Int32Array) => number, thisArg: Z): Int32Array;
/**
* Calls the specified callback function for all the elements in an array. The return value of
@ -3124,7 +3228,9 @@ interface Int32Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
some(callbackfn: (value: number, index: number, array: Int32Array) => boolean, thisArg?: any): boolean;
some(callbackfn: (this: undefined, value: number, index: number, array: Int32Array) => boolean): boolean;
some(callbackfn: (this: undefined, value: number, index: number, array: Int32Array) => boolean, thisArg: undefined): boolean;
some<Z>(callbackfn: (this: Z, value: number, index: number, array: Int32Array) => boolean, thisArg: Z): boolean;
/**
* Sorts an array.
@ -3177,7 +3283,11 @@ interface Int32ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int32Array;
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number): Int32Array;
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Int32Array;
from<Z>(arrayLike: ArrayLike<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int32Array;
from(arrayLike: ArrayLike<number>): Int32Array;
}
declare const Int32Array: Int32ArrayConstructor;
@ -3225,7 +3335,9 @@ interface Uint32Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
every(callbackfn: (value: number, index: number, array: Uint32Array) => boolean, thisArg?: any): boolean;
every(callbackfn: (this: undefined, value: number, index: number, array: Uint32Array) => boolean): boolean;
every(callbackfn: (this: undefined, value: number, index: number, array: Uint32Array) => boolean, thisArg: undefined): boolean;
every<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint32Array) => boolean, thisArg: Z): boolean;
/**
* Returns the this object after filling the section identified by start and end with value
@ -3244,7 +3356,9 @@ interface Uint32Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
filter(callbackfn: (value: number, index: number, array: Uint32Array) => any, thisArg?: any): Uint32Array;
filter(callbackfn: (this: undefined, value: number, index: number, array: Uint32Array) => any): Uint32Array;
filter(callbackfn: (this: undefined, value: number, index: number, array: Uint32Array) => any, thisArg: undefined): Uint32Array;
filter<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint32Array) => any, thisArg: Z): Uint32Array;
/**
* Returns the value of the first element in the array where predicate is true, and undefined
@ -3255,7 +3369,9 @@ interface Uint32Array {
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number | undefined;
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number | undefined;
find<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@ -3266,7 +3382,9 @@ interface Uint32Array {
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number;
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number;
findIndex<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number;
/**
* Performs the specified action for each element in an array.
@ -3275,7 +3393,9 @@ interface Uint32Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
forEach(callbackfn: (value: number, index: number, array: Uint32Array) => void, thisArg?: any): void;
forEach(callbackfn: (this: undefined, value: number, index: number, array: Uint32Array) => void): void;
forEach(callbackfn: (this: undefined, value: number, index: number, array: Uint32Array) => void, thisArg: undefined): void;
forEach<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint32Array) => void, thisArg: Z): void;
/**
* Returns the index of the first occurrence of a value in an array.
@ -3313,7 +3433,9 @@ interface Uint32Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
map(callbackfn: (value: number, index: number, array: Uint32Array) => number, thisArg?: any): Uint32Array;
map(callbackfn: (this: undefined, value: number, index: number, array: Uint32Array) => number): Uint32Array;
map(callbackfn: (this: undefined, value: number, index: number, array: Uint32Array) => number, thisArg: undefined): Uint32Array;
map<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint32Array) => number, thisArg: Z): Uint32Array;
/**
* Calls the specified callback function for all the elements in an array. The return value of
@ -3397,7 +3519,9 @@ interface Uint32Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
some(callbackfn: (value: number, index: number, array: Uint32Array) => boolean, thisArg?: any): boolean;
some(callbackfn: (this: undefined, value: number, index: number, array: Uint32Array) => boolean): boolean;
some(callbackfn: (this: undefined, value: number, index: number, array: Uint32Array) => boolean, thisArg: undefined): boolean;
some<Z>(callbackfn: (this: Z, value: number, index: number, array: Uint32Array) => boolean, thisArg: Z): boolean;
/**
* Sorts an array.
@ -3450,7 +3574,11 @@ interface Uint32ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint32Array;
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number): Uint32Array;
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Uint32Array;
from<Z>(arrayLike: ArrayLike<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint32Array;
from(arrayLike: ArrayLike<number>): Uint32Array;
}
declare const Uint32Array: Uint32ArrayConstructor;
@ -3498,7 +3626,9 @@ interface Float32Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
every(callbackfn: (value: number, index: number, array: Float32Array) => boolean, thisArg?: any): boolean;
every(callbackfn: (this: undefined, value: number, index: number, array: Float32Array) => boolean): boolean;
every(callbackfn: (this: undefined, value: number, index: number, array: Float32Array) => boolean, thisArg: undefined): boolean;
every<Z>(callbackfn: (this: Z, value: number, index: number, array: Float32Array) => boolean, thisArg: Z): boolean;
/**
* Returns the this object after filling the section identified by start and end with value
@ -3517,7 +3647,9 @@ interface Float32Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
filter(callbackfn: (value: number, index: number, array: Float32Array) => any, thisArg?: any): Float32Array;
filter(callbackfn: (this: undefined, value: number, index: number, array: Float32Array) => any): Float32Array;
filter(callbackfn: (this: undefined, value: number, index: number, array: Float32Array) => any, thisArg: undefined): Float32Array;
filter<Z>(callbackfn: (this: Z, value: number, index: number, array: Float32Array) => any, thisArg: Z): Float32Array;
/**
* Returns the value of the first element in the array where predicate is true, and undefined
@ -3528,7 +3660,9 @@ interface Float32Array {
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number | undefined;
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number | undefined;
find<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@ -3539,7 +3673,9 @@ interface Float32Array {
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number;
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number;
findIndex<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number;
/**
* Performs the specified action for each element in an array.
@ -3548,7 +3684,9 @@ interface Float32Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
forEach(callbackfn: (value: number, index: number, array: Float32Array) => void, thisArg?: any): void;
forEach(callbackfn: (this: undefined, value: number, index: number, array: Float32Array) => void): void;
forEach(callbackfn: (this: undefined, value: number, index: number, array: Float32Array) => void, thisArg: undefined): void;
forEach<Z>(callbackfn: (this: Z, value: number, index: number, array: Float32Array) => void, thisArg: Z): void;
/**
* Returns the index of the first occurrence of a value in an array.
@ -3586,7 +3724,9 @@ interface Float32Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
map(callbackfn: (value: number, index: number, array: Float32Array) => number, thisArg?: any): Float32Array;
map(callbackfn: (this: undefined, value: number, index: number, array: Float32Array) => number): Float32Array;
map(callbackfn: (this: undefined, value: number, index: number, array: Float32Array) => number, thisArg: undefined): Float32Array;
map<Z>(callbackfn: (this: Z, value: number, index: number, array: Float32Array) => number, thisArg: Z): Float32Array;
/**
* Calls the specified callback function for all the elements in an array. The return value of
@ -3670,7 +3810,9 @@ interface Float32Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
some(callbackfn: (value: number, index: number, array: Float32Array) => boolean, thisArg?: any): boolean;
some(callbackfn: (this: undefined, value: number, index: number, array: Float32Array) => boolean): boolean;
some(callbackfn: (this: undefined, value: number, index: number, array: Float32Array) => boolean, thisArg: undefined): boolean;
some<Z>(callbackfn: (this: Z, value: number, index: number, array: Float32Array) => boolean, thisArg: Z): boolean;
/**
* Sorts an array.
@ -3723,7 +3865,11 @@ interface Float32ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Float32Array;
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number): Float32Array;
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Float32Array;
from<Z>(arrayLike: ArrayLike<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Float32Array;
from(arrayLike: ArrayLike<number>): Float32Array;
}
declare const Float32Array: Float32ArrayConstructor;
@ -3772,7 +3918,9 @@ interface Float64Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
every(callbackfn: (value: number, index: number, array: Float64Array) => boolean, thisArg?: any): boolean;
every(callbackfn: (this: undefined, value: number, index: number, array: Float64Array) => boolean): boolean;
every(callbackfn: (this: undefined, value: number, index: number, array: Float64Array) => boolean, thisArg: undefined): boolean;
every<Z>(callbackfn: (this: Z, value: number, index: number, array: Float64Array) => boolean, thisArg: Z): boolean;
/**
* Returns the this object after filling the section identified by start and end with value
@ -3791,7 +3939,9 @@ interface Float64Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
filter(callbackfn: (value: number, index: number, array: Float64Array) => any, thisArg?: any): Float64Array;
filter(callbackfn: (this: undefined, value: number, index: number, array: Float64Array) => any): Float64Array;
filter(callbackfn: (this: undefined, value: number, index: number, array: Float64Array) => any, thisArg: undefined): Float64Array;
filter<Z>(callbackfn: (this: Z, value: number, index: number, array: Float64Array) => any, thisArg: Z): Float64Array;
/**
* Returns the value of the first element in the array where predicate is true, and undefined
@ -3802,7 +3952,9 @@ interface Float64Array {
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number | undefined;
find(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number | undefined;
find<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
@ -3813,7 +3965,9 @@ interface Float64Array {
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean): number;
findIndex(predicate: (this: undefined, value: number, index: number, obj: Array<number>) => boolean, thisArg: undefined): number;
findIndex<Z>(predicate: (this: Z, value: number, index: number, obj: Array<number>) => boolean, thisArg: Z): number;
/**
* Performs the specified action for each element in an array.
@ -3822,7 +3976,9 @@ interface Float64Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
forEach(callbackfn: (value: number, index: number, array: Float64Array) => void, thisArg?: any): void;
forEach(callbackfn: (this: undefined, value: number, index: number, array: Float64Array) => void): void;
forEach(callbackfn: (this: undefined, value: number, index: number, array: Float64Array) => void, thisArg: undefined): void;
forEach<Z>(callbackfn: (this: Z, value: number, index: number, array: Float64Array) => void, thisArg: Z): void;
/**
* Returns the index of the first occurrence of a value in an array.
@ -3860,7 +4016,9 @@ interface Float64Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
map(callbackfn: (value: number, index: number, array: Float64Array) => number, thisArg?: any): Float64Array;
map(callbackfn: (this: undefined, value: number, index: number, array: Float64Array) => number): Float64Array;
map(callbackfn: (this: undefined, value: number, index: number, array: Float64Array) => number, thisArg: undefined): Float64Array;
map<Z>(callbackfn: (this: Z, value: number, index: number, array: Float64Array) => number, thisArg: Z): Float64Array;
/**
* Calls the specified callback function for all the elements in an array. The return value of
@ -3944,7 +4102,9 @@ interface Float64Array {
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
* If thisArg is omitted, undefined is used as the this value.
*/
some(callbackfn: (value: number, index: number, array: Float64Array) => boolean, thisArg?: any): boolean;
some(callbackfn: (this: undefined, value: number, index: number, array: Float64Array) => boolean): boolean;
some(callbackfn: (this: undefined, value: number, index: number, array: Float64Array) => boolean, thisArg: undefined): boolean;
some<Z>(callbackfn: (this: Z, value: number, index: number, array: Float64Array) => boolean, thisArg: Z): boolean;
/**
* Sorts an array.
@ -3997,7 +4157,11 @@ interface Float64ArrayConstructor {
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Float64Array;
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number): Float64Array;
from(arrayLike: ArrayLike<number>, mapfn: (this: undefined, v: number, k: number) => number, thisArg: undefined): Float64Array;
from<Z>(arrayLike: ArrayLike<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Float64Array;
from(arrayLike: ArrayLike<number>): Float64Array;
}
declare const Float64Array: Float64ArrayConstructor;

View File

@ -1,7 +1,6 @@
/// <reference path="..\compiler\commandLineParser.ts" />
/// <reference path="..\services\services.ts" />
/// <reference path="session.ts" />
/// <reference types="node" />
namespace ts.server {

View File

@ -37,7 +37,7 @@ function createCancellationToken(args: string[]): ServerCancellationToken {
// when client wants to signal cancellation it should create a named pipe with name=<cancellationPipeName>
// server will synchronously check the presence of the pipe and treat its existance as indicator that current request should be canceled.
// in case if client prefers to use more fine-grained schema than one name for all request it can add '*' to the end of cancelellationPipeName.
// in this case pipe name will be build dynamically as <cancellationPipeName><request_seq>.
// in this case pipe name will be build dynamically as <cancellationPipeName><request_seq>.
if (cancellationPipeName.charAt(cancellationPipeName.length - 1) === "*") {
const namePrefix = cancellationPipeName.slice(0, -1);
if (namePrefix.length === 0 || namePrefix.indexOf("*") >= 0) {
@ -48,7 +48,7 @@ function createCancellationToken(args: string[]): ServerCancellationToken {
return {
isCancellationRequested: () => perRequestPipeName !== undefined && pipeExists(perRequestPipeName),
setRequest(requestId: number) {
currentRequestId = currentRequestId;
currentRequestId = requestId;
perRequestPipeName = namePrefix + requestId;
},
resetRequest(requestId: number) {
@ -67,4 +67,4 @@ function createCancellationToken(args: string[]): ServerCancellationToken {
};
}
}
export = createCancellationToken;
export = createCancellationToken;

View File

@ -5,6 +5,9 @@
"module": "commonjs",
"types": [
"node"
],
"lib": [
"es6"
]
},
"files": [

View File

@ -382,7 +382,9 @@ namespace ts.server {
const end = this.lineOffsetToPosition(fileName, entry.end);
return {
fileName,
textSpan: ts.createTextSpanFromBounds(start, end)
textSpan: ts.createTextSpanFromBounds(start, end),
kind: ScriptElementKind.unknown,
displayParts: []
};
});
}

View File

@ -1,4 +1,4 @@
/// <reference path="..\compiler\commandLineParser.ts" />
/// <reference path="..\compiler\commandLineParser.ts" />
/// <reference path="..\services\services.ts" />
/// <reference path="utilities.ts" />
/// <reference path="session.ts" />
@ -140,7 +140,7 @@ namespace ts.server {
getScriptKind: _ => undefined,
hasMixedContent: (fileName, extraFileExtensions) => {
const mixedContentExtensions = ts.map(ts.filter(extraFileExtensions, item => item.isMixedContent), item => item.extension);
return forEach(mixedContentExtensions, extension => fileExtensionIs(fileName, extension))
return forEach(mixedContentExtensions, extension => fileExtensionIs(fileName, extension));
}
};
@ -1377,7 +1377,7 @@ namespace ts.server {
// close projects that were missing in the input list
forEachKey(projectsToClose, externalProjectName => {
this.closeExternalProject(externalProjectName, /*suppressRefresh*/ true)
this.closeExternalProject(externalProjectName, /*suppressRefresh*/ true);
});
this.refreshInferredProjects();

View File

@ -1,4 +1,4 @@
/// <reference path="..\services\services.ts" />
/// <reference path="..\services\services.ts" />
/// <reference path="utilities.ts"/>
/// <reference path="scriptInfo.ts"/>
/// <reference path="lsHost.ts"/>
@ -723,7 +723,7 @@ namespace ts.server {
const fileName = resolvedTypeReferenceDirective.resolvedFileName;
const typeFilePath = toPath(fileName, currentDirectory, getCanonicalFileName);
referencedFiles.set(typeFilePath, true);
})
});
}
const allFileNames = arrayFrom(referencedFiles.keys()) as Path[];
@ -745,7 +745,7 @@ namespace ts.server {
const id = nextId;
nextId++;
return makeInferredProjectName(id);
}
};
})();
private _isJsInferredProject = false;

View File

@ -621,6 +621,11 @@ namespace ts.server.protocol {
* True if the occurrence is a write location, false otherwise.
*/
isWriteAccess: boolean;
/**
* True if the occurrence is in a string, undefined otherwise;
*/
isInString?: true;
}
export interface OccurrencesResponse extends Response {
@ -2127,6 +2132,17 @@ namespace ts.server.protocol {
payload: any;
}
export type TypesInstallerInitializationFailedEventName = "typesInstallerInitializationFailed";
export interface TypesInstallerInitializationFailedEvent extends Event {
event: TypesInstallerInitializationFailedEventName;
body: TypesInstallerInitializationFailedEventBody;
}
export interface TypesInstallerInitializationFailedEventBody {
message: string;
}
export type TypingsInstalledTelemetryEventName = "typingsInstalled";
export interface TypingsInstalledTelemetryEventBody extends TelemetryEventBody {
@ -2218,6 +2234,7 @@ namespace ts.server.protocol {
insertSpaceAfterFunctionKeywordForAnonymousFunctions?: boolean;
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis?: boolean;
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets?: boolean;
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces?: boolean;
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces?: boolean;
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces?: boolean;
insertSpaceBeforeFunctionParenthesis?: boolean;

View File

@ -48,7 +48,7 @@ namespace ts.server {
public reloadFromFile(tempFileName?: string) {
if (this.svc || (tempFileName !== this.fileName)) {
this.reload(this.getFileText(tempFileName))
this.reload(this.getFileText(tempFileName));
}
else {
this.setText(undefined);

View File

@ -47,14 +47,14 @@ namespace ts.server {
if (process.env.XDG_CACHE_HOME) {
return process.env.XDG_CACHE_HOME;
}
const usersDir = platformIsDarwin ? "Users" : "home"
const usersDir = platformIsDarwin ? "Users" : "home";
const homePath = (os.homedir && os.homedir()) ||
process.env.HOME ||
((process.env.LOGNAME || process.env.USER) && `/${usersDir}/${process.env.LOGNAME || process.env.USER}`) ||
os.tmpdir();
const cacheFolder = platformIsDarwin
? "Library/Caches"
: ".cache"
: ".cache";
return combinePaths(normalizeSlashes(homePath), cacheFolder);
}
@ -131,6 +131,14 @@ namespace ts.server {
constructor(private readonly logFilename: string,
private readonly traceToConsole: boolean,
private readonly level: LogLevel) {
if (this.logFilename) {
try {
this.fd = fs.openSync(this.logFilename, "w");
}
catch(_) {
// swallow the error and keep logging disabled if file cannot be opened
}
}
}
static padStringRight(str: string, padding: string) {
@ -175,11 +183,6 @@ namespace ts.server {
}
msg(s: string, type: Msg.Types = Msg.Err) {
if (this.fd < 0) {
if (this.logFilename) {
this.fd = fs.openSync(this.logFilename, "w");
}
}
if (this.fd >= 0 || this.traceToConsole) {
s = s + "\n";
const prefix = Logger.padStringRight(type + " " + this.seq.toString(), " ");
@ -301,11 +304,23 @@ namespace ts.server {
});
}
private handleMessage(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes) {
private handleMessage(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse) {
if (this.logger.hasLevel(LogLevel.verbose)) {
this.logger.info(`Received response: ${JSON.stringify(response)}`);
}
if (response.kind === EventInitializationFailed) {
if (!this.eventSender) {
return;
}
const body: protocol.TypesInstallerInitializationFailedEventBody = {
message: response.message
}
const eventName: protocol.TypesInstallerInitializationFailedEventName = "typesInstallerInitializationFailed";
this.eventSender.event(body, eventName);
return;
}
if (response.kind === EventBeginInstallTypes) {
if (!this.eventSender) {
return;
@ -410,6 +425,9 @@ namespace ts.server {
}
function parseLoggingEnvironmentString(logEnvStr: string): LogOptions {
if (!logEnvStr) {
return {};
}
const logEnv: LogOptions = { logToFile: true };
const args = logEnvStr.split(" ");
const len = args.length - 1;
@ -422,8 +440,8 @@ namespace ts.server {
logEnv.file = stripQuotes(value);
break;
case "-level":
const level: LogLevel = (<any>LogLevel)[value];
logEnv.detailLevel = typeof level === "number" ? level : LogLevel.normal;
const level = getLogLevel(value);
logEnv.detailLevel = level !== undefined ? level : LogLevel.normal;
break;
case "-traceToConsole":
logEnv.traceToConsole = value.toLowerCase() === "true";
@ -437,28 +455,32 @@ namespace ts.server {
return logEnv;
}
// TSS_LOG "{ level: "normal | verbose | terse", file?: string}"
function createLoggerFromEnv() {
let fileName: string = undefined;
let detailLevel = LogLevel.normal;
let traceToConsole = false;
const logEnvStr = process.env["TSS_LOG"];
if (logEnvStr) {
const logEnv = parseLoggingEnvironmentString(logEnvStr);
if (logEnv.logToFile) {
if (logEnv.file) {
fileName = logEnv.file;
}
else {
fileName = __dirname + "/.log" + process.pid.toString();
function getLogLevel(level: string) {
if (level) {
const l = level.toLowerCase();
for (const name in LogLevel) {
if (isNaN(+name) && l === name.toLowerCase()) {
return <LogLevel><any>LogLevel[name];
}
}
if (logEnv.detailLevel) {
detailLevel = logEnv.detailLevel;
}
traceToConsole = logEnv.traceToConsole;
}
return new Logger(fileName, traceToConsole, detailLevel);
return undefined;
}
// TSS_LOG "{ level: "normal | verbose | terse", file?: string}"
function createLogger() {
const cmdLineLogFileName = findArgument("--logFile");
const cmdLineVerbosity = getLogLevel(findArgument("--logVerbosity"));
const envLogOptions = parseLoggingEnvironmentString(process.env["TSS_LOG"]);
const logFileName = cmdLineLogFileName
? stripQuotes(cmdLineLogFileName)
: envLogOptions.logToFile
? envLogOptions.file || (__dirname + "/.log" + process.pid.toString())
: undefined;
const logVerbosity = cmdLineVerbosity || envLogOptions.detailLevel;
return new Logger(logFileName, envLogOptions.traceToConsole, logVerbosity)
}
// This places log file in the directory containing editorServices.js
// TODO: check that this location is writable
@ -555,7 +577,6 @@ namespace ts.server {
// to increase the chunk size or decrease the interval
// time dynamically to match the large reference set?
const pollingWatchedFileSet = createPollingWatchedFileSet();
const logger = createLoggerFromEnv();
const pending: Buffer[] = [];
let canWrite = true;
@ -607,6 +628,8 @@ namespace ts.server {
return s.length > 2 && s.charCodeAt(0) === CharacterCodes.slash && s.charCodeAt(1) === CharacterCodes.slash;
}
const logger = createLogger();
const sys = <ServerHost>ts.sys;
// use watchGuard process on Windows when node version is 4 or later
const useWatchGuard = process.platform === "win32" && getNodeMajorVersion() >= 4;
@ -653,7 +676,7 @@ namespace ts.server {
// this drive is unsafe - return no-op watcher
return { close() { } };
}
}
};
}
// Override sys.write because fs.writeSync is not reliable on Node 4

View File

@ -226,7 +226,7 @@ namespace ts.server {
/**
* Represents operation that can schedule its next step to be executed later.
* Scheduling is done via instance of NextStep. If on current step subsequent step was not scheduled - operation is assumed to be completed.
* Scheduling is done via instance of NextStep. If on current step subsequent step was not scheduled - operation is assumed to be completed.
*/
class MultistepOperation {
private requestId: number;
@ -239,7 +239,7 @@ namespace ts.server {
this.next = {
immediate: action => this.immediate(action),
delay: (ms, action) => this.delay(ms, action)
}
};
}
public startNew(action: (next: NextStep) => void) {
@ -262,7 +262,7 @@ namespace ts.server {
private immediate(action: () => void) {
const requestId = this.requestId;
Debug.assert(requestId === this.operationHost.getCurrentRequestId(), "immediate: incorrect request id")
Debug.assert(requestId === this.operationHost.getCurrentRequestId(), "immediate: incorrect request id");
this.setImmediateId(this.operationHost.getServerHost().setImmediate(() => {
this.immediateId = undefined;
this.operationHost.executeWithRequestId(requestId, () => this.executeAction(action));
@ -271,7 +271,7 @@ namespace ts.server {
private delay(ms: number, action: () => void) {
const requestId = this.requestId;
Debug.assert(requestId === this.operationHost.getCurrentRequestId(), "delay: incorrect request id")
Debug.assert(requestId === this.operationHost.getCurrentRequestId(), "delay: incorrect request id");
this.setTimerHandle(this.operationHost.getServerHost().setTimeout(() => {
this.timerHandle = undefined;
this.operationHost.executeWithRequestId(requestId, () => this.executeAction(action));
@ -351,7 +351,7 @@ namespace ts.server {
logError: (err, cmd) => this.logError(err, cmd),
sendRequestCompletedEvent: requestId => this.sendRequestCompletedEvent(requestId),
isCancellationRequested: () => cancellationToken.isCancellationRequested()
}
};
this.errorCheck = new MultistepOperation(multistepOperationHost);
this.projectService = new ProjectService(host, logger, cancellationToken, useSingleInferredProject, typingsInstaller, this.eventHander);
this.gcTimer = new GcTimer(host, /*delay*/ 7000, logger);
@ -651,16 +651,21 @@ namespace ts.server {
}
return occurrences.map(occurrence => {
const { fileName, isWriteAccess, textSpan } = occurrence;
const { fileName, isWriteAccess, textSpan, isInString } = occurrence;
const scriptInfo = project.getScriptInfo(fileName);
const start = scriptInfo.positionToLineOffset(textSpan.start);
const end = scriptInfo.positionToLineOffset(ts.textSpanEnd(textSpan));
return {
const result: protocol.OccurrencesResponseItem = {
start,
end,
file: fileName,
isWriteAccess,
};
// no need to serialize the property if it is not true
if (isInString) {
result.isInString = isInString;
}
return result;
});
}
@ -1420,8 +1425,9 @@ namespace ts.server {
const scriptInfo = project.getScriptInfoForNormalizedPath(file);
const startPosition = getStartPosition();
const endPosition = getEndPosition();
const formatOptions = this.projectService.getFormatCodeOptions(file);
const codeActions = project.getLanguageService().getCodeFixesAtPosition(file, startPosition, endPosition, args.errorCodes);
const codeActions = project.getLanguageService().getCodeFixesAtPosition(file, startPosition, endPosition, args.errorCodes, formatOptions);
if (!codeActions) {
return undefined;
}

View File

@ -5,6 +5,7 @@ namespace ts.server {
export const ActionInvalidate: ActionInvalidate = "action::invalidate";
export const EventBeginInstallTypes: EventBeginInstallTypes = "event::beginInstallTypes";
export const EventEndInstallTypes: EventEndInstallTypes = "event::endInstallTypes";
export const EventInitializationFailed: EventInitializationFailed = "event::initializationFailed";
export namespace Arguments {
export const GlobalCacheLocation = "--globalTypingsCacheLocation";

View File

@ -10,7 +10,8 @@
"target": "es5",
"noUnusedLocals": true,
"noUnusedParameters": true,
"declaration": true
"declaration": true,
"types": []
},
"files": [
"editorServices.ts",

View File

@ -47,9 +47,15 @@ declare namespace ts.server {
export type ActionInvalidate = "action::invalidate";
export type EventBeginInstallTypes = "event::beginInstallTypes";
export type EventEndInstallTypes = "event::endInstallTypes";
export type EventInitializationFailed = "event::initializationFailed";
export interface TypingInstallerResponse {
readonly kind: ActionSet | ActionInvalidate | EventBeginInstallTypes | EventEndInstallTypes;
readonly kind: ActionSet | ActionInvalidate | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed;
}
export interface InitializationFailedResponse extends TypingInstallerResponse {
readonly kind: EventInitializationFailed;
readonly message: string;
}
export interface ProjectResponse extends TypingInstallerResponse {

View File

@ -1,4 +1,4 @@
/// <reference path="typingsInstaller.ts"/>
/// <reference path="typingsInstaller.ts"/>
/// <reference types="node" />
namespace ts.server.typingsInstaller {
@ -13,14 +13,20 @@ namespace ts.server.typingsInstaller {
} = require("path");
class FileLog implements Log {
private logEnabled = true;
constructor(private readonly logFile?: string) {
}
isEnabled() {
return this.logFile !== undefined;
return this.logEnabled && this.logFile !== undefined;
}
writeLine(text: string) {
fs.appendFileSync(this.logFile, text + sys.newLine);
try {
fs.appendFileSync(this.logFile, text + sys.newLine);
}
catch(e) {
this.logEnabled = false;
}
}
}
@ -61,15 +67,15 @@ namespace ts.server.typingsInstaller {
return combinePaths(normalizeSlashes(globalTypingsCacheLocation), `node_modules/${TypesRegistryPackageName}/index.json`);
}
type ExecSync = {
(command: string, options: { cwd: string, stdio?: "ignore" }): any
}
type ExecSync = (command: string, options: { cwd: string, stdio?: "ignore" }) => any;
export class NodeTypingsInstaller extends TypingsInstaller {
private readonly execSync: ExecSync;
private readonly npmPath: string;
readonly typesRegistry: Map<void>;
private delayedInitializationError: InitializationFailedResponse;
constructor(globalTypingsCacheLocation: string, throttleLimit: number, log: Log) {
super(
sys,
@ -95,6 +101,11 @@ namespace ts.server.typingsInstaller {
if (this.log.isEnabled()) {
this.log.writeLine(`Error updating ${TypesRegistryPackageName} package: ${(<Error>e).message}`);
}
// store error info to report it later when it is known that server is already listening to events from typings installer
this.delayedInitializationError = {
kind: "event::initializationFailed",
message: (<Error>e).message
};
}
this.typesRegistry = loadTypesRegistryFile(getTypesRegistryFileLocation(globalTypingsCacheLocation), this.installTypingHost, this.log);
@ -102,6 +113,11 @@ namespace ts.server.typingsInstaller {
listen() {
process.on("message", (req: DiscoverTypings | CloseProject) => {
if (this.delayedInitializationError) {
// report initializationFailed error
this.sendResponse(this.delayedInitializationError);
this.delayedInitializationError = undefined;
}
switch (req.kind) {
case "discover":
this.install(req);
@ -112,7 +128,7 @@ namespace ts.server.typingsInstaller {
});
}
protected sendResponse(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes) {
protected sendResponse(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse) {
if (this.log.isEnabled()) {
this.log.writeLine(`Sending response: ${JSON.stringify(response)}`);
}

View File

@ -5,6 +5,10 @@
"outFile": "../../../built/local/typingsInstaller.js",
"types": [
"node"
],
"lib": [
"es6",
"scripthost"
]
},
"files": [

View File

@ -1,4 +1,4 @@
/// <reference path="../../compiler/core.ts" />
/// <reference path="../../compiler/core.ts" />
/// <reference path="../../compiler/moduleNameResolver.ts" />
/// <reference path="../../services/jsTyping.ts"/>
/// <reference path="../types.ts"/>

View File

@ -1,8 +1,14 @@
{
"extends": "../../tsconfig-base",
"extends": "../../tsconfig-base",
"compilerOptions": {
"removeComments": true,
"outFile": "../../../built/local/watchGuard.js"
"outFile": "../../../built/local/watchGuard.js",
"types": [
"node"
],
"lib": [
"es6"
]
},
"files": [
"watchGuard.ts"

View File

@ -11,7 +11,7 @@ const fs: { watch(directoryName: string, options: any, callback: () => {}): any
// This means that here we treat any result (success or exception) from fs.watch as success since it does not tear down the process.
// The only case that should be considered as failure - when watchGuard process crashes.
try {
const watcher = fs.watch(directoryName, { recursive: true }, () => ({}))
const watcher = fs.watch(directoryName, { recursive: true }, () => ({}));
watcher.close();
}
catch (_e) {

View File

@ -370,8 +370,8 @@ namespace ts.BreakpointResolver {
}
function textSpanFromVariableDeclaration(variableDeclaration: VariableDeclaration): TextSpan {
const declarations = variableDeclaration.parent.declarations;
if (declarations && declarations[0] === variableDeclaration) {
if (variableDeclaration.parent.kind === SyntaxKind.VariableDeclarationList &&
variableDeclaration.parent.declarations[0] === variableDeclaration) {
// First declaration - include let keyword
return textSpan(findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent), variableDeclaration);
}
@ -400,8 +400,8 @@ namespace ts.BreakpointResolver {
return textSpanFromVariableDeclaration(variableDeclaration);
}
const declarations = variableDeclaration.parent.declarations;
if (declarations && declarations[0] !== variableDeclaration) {
if (variableDeclaration.parent.kind === SyntaxKind.VariableDeclarationList &&
variableDeclaration.parent.declarations[0] !== variableDeclaration) {
// If we cannot set breakpoint on this declaration, set it on previous one
// Because the variable declaration may be binding pattern and
// we would like to set breakpoint in last binding element if that's the case,

View File

@ -1,4 +1,4 @@
/* @internal */
/* @internal */
namespace ts {
export interface CodeFix {
errorCodes: number[];
@ -13,6 +13,7 @@ namespace ts {
newLineCharacter: string;
host: LanguageServiceHost;
cancellationToken: CancellationToken;
rulesProvider: formatting.RulesProvider;
}
export namespace codefix {

View File

@ -22,8 +22,8 @@ namespace ts.codefix {
const classDecl = token.parent as ClassLikeDeclaration;
const startPos = classDecl.members.pos;
const classType = checker.getTypeAtLocation(classDecl) as InterfaceType;
const instantiatedExtendsType = checker.getBaseTypes(classType)[0];
const extendsNode = getClassExtendsHeritageClauseElement(classDecl);
const instantiatedExtendsType = checker.getTypeAtLocation(extendsNode);
// Note that this is ultimately derived from a map indexed by symbol names,
// so duplicates cannot occur.

View File

@ -17,7 +17,7 @@ namespace ts.codefix {
}
const startPos: number = classDecl.members.pos;
const classType = checker.getTypeAtLocation(classDecl);
const classType = checker.getTypeAtLocation(classDecl) as InterfaceType;
const implementedTypeNodes = getClassImplementsHeritageClauseElements(classDecl);
const hasNumericIndexSignature = !!checker.getIndexTypeOfType(classType, IndexKind.Number);
@ -25,9 +25,9 @@ namespace ts.codefix {
const result: CodeAction[] = [];
for (const implementedTypeNode of implementedTypeNodes) {
const implementedType = checker.getTypeFromTypeNode(implementedTypeNode) as InterfaceType;
// Note that this is ultimately derived from a map indexed by symbol names,
// so duplicates cannot occur.
const implementedType = checker.getTypeAtLocation(implementedTypeNode) as InterfaceType;
const implementedTypeSymbols = checker.getPropertiesOfType(implementedType);
const nonPrivateMembers = implementedTypeSymbols.filter(symbol => !(getModifierFlags(symbol.valueDeclaration) & ModifierFlags.Private));

View File

@ -26,22 +26,13 @@ namespace ts.codefix {
}
}
}
const newPosition = getOpenBraceEnd(<ConstructorDeclaration>constructor, sourceFile);
const changes = [{
fileName: sourceFile.fileName, textChanges: [{
newText: superCall.getText(sourceFile),
span: { start: newPosition, length: 0 }
},
{
newText: "",
span: { start: superCall.getStart(sourceFile), length: superCall.getWidth(sourceFile) }
}]
}];
const changeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
changeTracker.insertNodeAfter(sourceFile, getOpenBrace(<ConstructorDeclaration>constructor, sourceFile), superCall, { suffix: context.newLineCharacter });
changeTracker.deleteNode(sourceFile, superCall);
return [{
description: getLocaleSpecificMessage(Diagnostics.Make_super_call_the_first_statement_in_the_constructor),
changes
changes: changeTracker.getChanges()
}];
function findSuperCall(n: Node): ExpressionStatement {

View File

@ -10,10 +10,13 @@ namespace ts.codefix {
return undefined;
}
const newPosition = getOpenBraceEnd(<ConstructorDeclaration>token.parent, sourceFile);
const changeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
const superCall = createStatement(createCall(createSuper(), /*typeArguments*/ undefined, /*argumentsArray*/ emptyArray));
changeTracker.insertNodeAfter(sourceFile, getOpenBrace(<ConstructorDeclaration>token.parent, sourceFile), superCall, { suffix: context.newLineCharacter });
return [{
description: getLocaleSpecificMessage(Diagnostics.Add_missing_super_call),
changes: [{ fileName: sourceFile.fileName, textChanges: [{ newText: "super();", span: { start: newPosition, length: 0 } }] }]
changes: changeTracker.getChanges()
}];
}
});

View File

@ -21,26 +21,20 @@ namespace ts.codefix {
return undefined;
}
let changeStart = extendsToken.getStart(sourceFile);
let changeEnd = extendsToken.getEnd();
const textChanges: TextChange[] = [{ newText: " implements", span: { start: changeStart, length: changeEnd - changeStart } }];
const changeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
changeTracker.replaceNode(sourceFile, extendsToken, createToken(SyntaxKind.ImplementsKeyword));
// We replace existing keywords with commas.
for (let i = 1; i < heritageClauses.length; i++) {
const keywordToken = heritageClauses[i].getFirstToken();
if (keywordToken) {
changeStart = keywordToken.getStart(sourceFile);
changeEnd = keywordToken.getEnd();
textChanges.push({ newText: ",", span: { start: changeStart, length: changeEnd - changeStart } });
changeTracker.replaceNode(sourceFile, keywordToken, createToken(SyntaxKind.CommaToken));
}
}
const result = [{
description: getLocaleSpecificMessage(Diagnostics.Change_extends_to_implements),
changes: [{
fileName: sourceFile.fileName,
textChanges: textChanges
}]
changes: changeTracker.getChanges()
}];
return result;

View File

@ -5,11 +5,15 @@ namespace ts.codefix {
getCodeActions: (context: CodeFixContext) => {
const sourceFile = context.sourceFile;
const token = getTokenAtPosition(sourceFile, context.span.start);
const start = token.getStart(sourceFile);
if (token.kind !== SyntaxKind.Identifier) {
return undefined;
}
const changeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
changeTracker.replaceNode(sourceFile, token, createPropertyAccess(createThis(), <Identifier>token));
return [{
description: getLocaleSpecificMessage(Diagnostics.Add_this_to_unresolved_variable),
changes: [{ fileName: sourceFile.fileName, textChanges: [{ newText: "this.", span: { start, length: 0 } }] }]
changes: changeTracker.getChanges()
}];
}
});

View File

@ -23,8 +23,6 @@ namespace ts.codefix {
* @returns Empty string iff there we can't figure out a representation for `symbol` in `enclosingDeclaration`.
*/
function getInsertionForMemberSymbol(symbol: Symbol, enclosingDeclaration: ClassLikeDeclaration, checker: TypeChecker, newlineChar: string): string {
// const name = symbol.getName();
const type = checker.getTypeOfSymbolAtLocation(symbol, enclosingDeclaration);
const declarations = symbol.getDeclarations();
if (!(declarations && declarations.length)) {
return "";
@ -34,6 +32,8 @@ namespace ts.codefix {
const name = declaration.name ? declaration.name.getText() : undefined;
const visibility = getVisibilityPrefixWithSpace(getModifierFlags(declaration));
const type = checker.getTypeOfSymbolAtLocation(symbol, enclosingDeclaration);
switch (declaration.kind) {
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:

View File

@ -1,10 +1,10 @@
/* @internal */
/* @internal */
namespace ts.codefix {
type ImportCodeActionKind = "CodeChange" | "InsertingIntoExistingImport" | "NewImport";
interface ImportCodeAction extends CodeAction {
kind: ImportCodeActionKind,
moduleSpecifier?: string
kind: ImportCodeActionKind;
moduleSpecifier?: string;
}
enum ModuleSpecifierComparison {
@ -75,7 +75,7 @@ namespace ts.codefix {
getAllActions() {
let result: ImportCodeAction[] = [];
for (const key in this.symbolIdToActionMap) {
result = concatenate(result, this.symbolIdToActionMap[key])
result = concatenate(result, this.symbolIdToActionMap[key]);
}
return result;
}
@ -130,7 +130,7 @@ namespace ts.codefix {
// this is a module id -> module import declaration map
const cachedImportDeclarations: (ImportDeclaration | ImportEqualsDeclaration)[][] = [];
let cachedNewImportInsertPosition: number;
let lastImportDeclaration: Node;
const currentTokenMeaning = getMeaningFromLocation(token);
if (context.errorCode === Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code) {
@ -138,14 +138,14 @@ namespace ts.codefix {
return getCodeActionForImport(symbol, /*isDefault*/ false, /*isNamespaceImport*/ true);
}
const allPotentialModules = checker.getAmbientModules();
const candidateModules = checker.getAmbientModules();
for (const otherSourceFile of allSourceFiles) {
if (otherSourceFile !== sourceFile && isExternalOrCommonJsModule(otherSourceFile)) {
allPotentialModules.push(otherSourceFile.symbol);
candidateModules.push(otherSourceFile.symbol);
}
}
for (const moduleSymbol of allPotentialModules) {
for (const moduleSymbol of candidateModules) {
context.cancellationToken.throwIfCancellationRequested();
// check the default export
@ -277,14 +277,12 @@ namespace ts.codefix {
* If the existing import declaration already has a named import list, just
* insert the identifier into that list.
*/
const textChange = getTextChangeForImportClause(namedImportDeclaration.importClause);
const fileTextChanges = getTextChangeForImportClause(namedImportDeclaration.importClause);
const moduleSpecifierWithoutQuotes = stripQuotes(namedImportDeclaration.moduleSpecifier.getText());
actions.push(createCodeAction(
Diagnostics.Add_0_to_existing_import_declaration_from_1,
[name, moduleSpecifierWithoutQuotes],
textChange.newText,
textChange.span,
sourceFile.fileName,
fileTextChanges,
"InsertingIntoExistingImport",
moduleSpecifierWithoutQuotes
));
@ -302,49 +300,31 @@ namespace ts.codefix {
return declaration.moduleReference.getText();
}
function getTextChangeForImportClause(importClause: ImportClause): TextChange {
const newImportText = isDefault ? `default as ${name}` : name;
function getTextChangeForImportClause(importClause: ImportClause): FileTextChanges[] {
//const newImportText = isDefault ? `default as ${name}` : name;
const importList = <NamedImports>importClause.namedBindings;
const newImportSpecifier = createImportSpecifier(/*propertyName*/ undefined, createIdentifier(name));
// case 1:
// original text: import default from "module"
// change to: import default, { name } from "module"
if (!importList && importClause.name) {
const start = importClause.name.getEnd();
return {
newText: `, { ${newImportText} }`,
span: { start, length: 0 }
};
}
// case 2:
// original text: import {} from "module"
// change to: import { name } from "module"
if (importList.elements.length === 0) {
const start = importList.getStart();
return {
newText: `{ ${newImportText} }`,
span: { start, length: importList.getEnd() - start }
};
if (!importList || importList.elements.length === 0) {
const newImportClause = createImportClause(importClause.name, createNamedImports([newImportSpecifier]));
return createChangeTracker().replaceNode(sourceFile, importClause, newImportClause).getChanges();
}
// case 3:
// original text: import { foo, bar } from "module"
// change to: import { foo, bar, name } from "module"
const insertPoint = importList.elements[importList.elements.length - 1].getEnd();
/**
* If the import list has one import per line, preserve that. Otherwise, insert on same line as last element
* import {
* foo
* } from "./module";
*/
const startLine = getLineOfLocalPosition(sourceFile, importList.getStart());
const endLine = getLineOfLocalPosition(sourceFile, importList.getEnd());
const oneImportPerLine = endLine - startLine > importList.elements.length;
return {
newText: `,${oneImportPerLine ? context.newLineCharacter : " "}${newImportText}`,
span: { start: insertPoint, length: 0 }
};
return createChangeTracker().insertNodeInListAfter(
sourceFile,
importList.elements[importList.elements.length - 1],
newImportSpecifier).getChanges();
}
function getCodeActionForNamespaceImport(declaration: ImportDeclaration | ImportEqualsDeclaration): ImportCodeAction {
@ -370,48 +350,47 @@ namespace ts.codefix {
return createCodeAction(
Diagnostics.Change_0_to_1,
[name, `${namespacePrefix}.${name}`],
`${namespacePrefix}.`,
{ start: token.getStart(), length: 0 },
sourceFile.fileName,
createChangeTracker().replaceNode(sourceFile, token, createPropertyAccess(createIdentifier(namespacePrefix), name)).getChanges(),
"CodeChange"
);
}
}
function getCodeActionForNewImport(moduleSpecifier?: string): ImportCodeAction {
if (!cachedNewImportInsertPosition) {
if (!lastImportDeclaration) {
// insert after any existing imports
let lastModuleSpecifierEnd = -1;
for (const moduleSpecifier of sourceFile.imports) {
const end = moduleSpecifier.getEnd();
if (!lastModuleSpecifierEnd || end > lastModuleSpecifierEnd) {
lastModuleSpecifierEnd = end;
for (let i = sourceFile.statements.length - 1; i >= 0; i--) {
const statement = sourceFile.statements[i];
if (statement.kind === SyntaxKind.ImportEqualsDeclaration || statement.kind === SyntaxKind.ImportDeclaration) {
lastImportDeclaration = statement;
break;
}
}
cachedNewImportInsertPosition = lastModuleSpecifierEnd > 0 ? sourceFile.getLineEndOfPosition(lastModuleSpecifierEnd) : sourceFile.getStart();
}
const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
const moduleSpecifierWithoutQuotes = stripQuotes(moduleSpecifier || getModuleSpecifierForNewImport());
const importStatementText = isDefault
? `import ${name} from "${moduleSpecifierWithoutQuotes}"`
const changeTracker = createChangeTracker();
const importClause = isDefault
? createImportClause(createIdentifier(name), /*namedBindings*/ undefined)
: isNamespaceImport
? `import * as ${name} from "${moduleSpecifierWithoutQuotes}"`
: `import { ${name} } from "${moduleSpecifierWithoutQuotes}"`;
? createImportClause(/*name*/ undefined, createNamespaceImport(createIdentifier(name)))
: createImportClause(/*name*/ undefined, createNamedImports([createImportSpecifier(/*propertyName*/ undefined, createIdentifier(name))]));
const importDecl = createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, importClause, createLiteral(moduleSpecifierWithoutQuotes));
if (!lastImportDeclaration) {
changeTracker.insertNodeAt(sourceFile, sourceFile.getStart(), importDecl, { suffix: `${context.newLineCharacter}${context.newLineCharacter}` });
}
else {
changeTracker.insertNodeAfter(sourceFile, lastImportDeclaration, importDecl, { suffix: context.newLineCharacter });
}
// if this file doesn't have any import statements, insert an import statement and then insert a new line
// between the only import statement and user code. Otherwise just insert the statement because chances
// are there are already a new line seperating code and import statements.
const newText = cachedNewImportInsertPosition === sourceFile.getStart()
? `${importStatementText};${context.newLineCharacter}${context.newLineCharacter}`
: `${context.newLineCharacter}${importStatementText};`;
return createCodeAction(
Diagnostics.Import_0_from_1,
[name, `"${moduleSpecifierWithoutQuotes}"`],
newText,
{ start: cachedNewImportInsertPosition, length: 0 },
sourceFile.fileName,
changeTracker.getChanges(),
"NewImport",
moduleSpecifierWithoutQuotes
);
@ -576,17 +555,19 @@ namespace ts.codefix {
}
function createChangeTracker() {
return textChanges.ChangeTracker.fromCodeFixContext(context);;
}
function createCodeAction(
description: DiagnosticMessage,
diagnosticArgs: string[],
newText: string,
span: TextSpan,
fileName: string,
changes: FileTextChanges[],
kind: ImportCodeActionKind,
moduleSpecifier?: string): ImportCodeAction {
return {
description: formatMessage.apply(undefined, [undefined, description].concat(<any[]>diagnosticArgs)),
changes: [{ fileName, textChanges: [{ newText, span }] }],
changes,
kind,
moduleSpecifier
};

View File

@ -1,4 +1,4 @@
/* @internal */
/* @internal */
namespace ts.codefix {
registerCodeFix({
errorCodes: [
@ -25,17 +25,17 @@ namespace ts.codefix {
const forStatement = <ForStatement>token.parent.parent.parent;
const forInitializer = <VariableDeclarationList>forStatement.initializer;
if (forInitializer.declarations.length === 1) {
return createCodeFixToRemoveNode(forInitializer);
return deleteNode(forInitializer);
}
else {
return removeSingleItem(forInitializer.declarations, token);
return deleteNodeInList(token.parent);
}
case SyntaxKind.ForOfStatement:
const forOfStatement = <ForOfStatement>token.parent.parent.parent;
if (forOfStatement.initializer.kind === SyntaxKind.VariableDeclarationList) {
const forOfInitializer = <VariableDeclarationList>forOfStatement.initializer;
return createCodeFix("{}", forOfInitializer.declarations[0].getStart(), forOfInitializer.declarations[0].getWidth());
return replaceNode(forOfInitializer.declarations[0], createObjectLiteral());
}
break;
@ -47,51 +47,59 @@ namespace ts.codefix {
case SyntaxKind.CatchClause:
const catchClause = <CatchClause>token.parent.parent;
const parameter = catchClause.variableDeclaration.getChildren()[0];
return createCodeFixToRemoveNode(parameter);
return deleteNode(parameter);
default:
const variableStatement = <VariableStatement>token.parent.parent.parent;
if (variableStatement.declarationList.declarations.length === 1) {
return createCodeFixToRemoveNode(variableStatement);
return deleteNode(variableStatement);
}
else {
const declarations = variableStatement.declarationList.declarations;
return removeSingleItem(declarations, token);
return deleteNodeInList(token.parent);
}
}
case SyntaxKind.TypeParameter:
const typeParameters = (<DeclarationWithTypeParameters>token.parent.parent).typeParameters;
if (typeParameters.length === 1) {
return createCodeFix("", token.parent.pos - 1, token.parent.end - token.parent.pos + 2);
const previousToken = getTokenAtPosition(sourceFile, typeParameters.pos - 1);
if (!previousToken || previousToken.kind !== SyntaxKind.LessThanToken) {
return deleteRange(typeParameters);
}
const nextToken = getTokenAtPosition(sourceFile, typeParameters.end);
if (!nextToken || nextToken.kind !== SyntaxKind.GreaterThanToken) {
return deleteRange(typeParameters);
}
return deleteNodeRange(previousToken, nextToken);
}
else {
return removeSingleItem(typeParameters, token);
return deleteNodeInList(token.parent);
}
case ts.SyntaxKind.Parameter:
const functionDeclaration = <FunctionDeclaration>token.parent.parent;
if (functionDeclaration.parameters.length === 1) {
return createCodeFixToRemoveNode(token.parent);
return deleteNode(token.parent);
}
else {
return removeSingleItem(functionDeclaration.parameters, token);
return deleteNodeInList(token.parent);
}
// handle case where 'import a = A;'
case SyntaxKind.ImportEqualsDeclaration:
const importEquals = findImportDeclaration(token);
return createCodeFixToRemoveNode(importEquals);
const importEquals = getAncestor(token, SyntaxKind.ImportEqualsDeclaration);
return deleteNode(importEquals);
case SyntaxKind.ImportSpecifier:
const namedImports = <NamedImports>token.parent.parent;
if (namedImports.elements.length === 1) {
// Only 1 import and it is unused. So the entire declaration should be removed.
const importSpec = findImportDeclaration(token);
return createCodeFixToRemoveNode(importSpec);
const importSpec = getAncestor(token, SyntaxKind.ImportDeclaration);
return deleteNode(importSpec);
}
else {
return removeSingleItem(namedImports.elements, token);
// delete import specifier
return deleteNodeInList(token.parent);
}
// handle case where "import d, * as ns from './file'"
@ -99,98 +107,79 @@ namespace ts.codefix {
case SyntaxKind.ImportClause: // this covers both 'import |d|' and 'import |d,| *'
const importClause = <ImportClause>token.parent;
if (!importClause.namedBindings) { // |import d from './file'| or |import * as ns from './file'|
const importDecl = findImportDeclaration(importClause);
return createCodeFixToRemoveNode(importDecl);
const importDecl = getAncestor(importClause, SyntaxKind.ImportDeclaration);
return deleteNode(importDecl);
}
else {
// import |d,| * as ns from './file'
const start = importClause.name.getStart();
let end = findFirstNonSpaceCharPosStarting(importClause.name.end);
if (sourceFile.text.charCodeAt(end) === CharacterCodes.comma) {
end = findFirstNonSpaceCharPosStarting(end + 1);
const start = importClause.name.getStart(sourceFile);
const nextToken = getTokenAtPosition(sourceFile, importClause.name.end);
if (nextToken && nextToken.kind === SyntaxKind.CommaToken) {
// shift first non-whitespace position after comma to the start position of the node
return deleteRange({ pos: start, end: skipTrivia(sourceFile.text, nextToken.end, /*stopAfterLineBreaks*/ false, /*stopAtComments*/true) });
}
else {
return deleteNode(importClause.name);
}
return createCodeFix("", start, end - start);
}
case SyntaxKind.NamespaceImport:
const namespaceImport = <NamespaceImport>token.parent;
if (namespaceImport.name == token && !(<ImportClause>namespaceImport.parent).name) {
const importDecl = findImportDeclaration(namespaceImport);
return createCodeFixToRemoveNode(importDecl);
const importDecl = getAncestor(namespaceImport, SyntaxKind.ImportDeclaration);
return deleteNode(importDecl);
}
else {
const start = (<ImportClause>namespaceImport.parent).name.end;
return createCodeFix("", start, (<ImportClause>namespaceImport.parent).namedBindings.end - start);
const previousToken = getTokenAtPosition(sourceFile, namespaceImport.pos - 1);
if (previousToken && previousToken.kind === SyntaxKind.CommaToken) {
const startPosition = textChanges.getAdjustedStartPosition(sourceFile, previousToken, {}, textChanges.Position.FullStart);
return deleteRange({ pos: startPosition, end: namespaceImport.end });
}
return deleteRange(namespaceImport);
}
}
break;
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.NamespaceImport:
return createCodeFixToRemoveNode(token.parent);
return deleteNode(token.parent);
}
if (isDeclarationName(token)) {
return createCodeFixToRemoveNode(token.parent);
return deleteNode(token.parent);
}
else if (isLiteralComputedPropertyDeclarationName(token)) {
return createCodeFixToRemoveNode(token.parent.parent);
return deleteNode(token.parent.parent);
}
else {
return undefined;
}
function findImportDeclaration(token: Node): Node {
let importDecl = token;
while (importDecl.kind != SyntaxKind.ImportDeclaration && importDecl.parent) {
importDecl = importDecl.parent;
}
return importDecl;
function deleteNode(n: Node) {
return makeChange(textChanges.ChangeTracker.fromCodeFixContext(context).deleteNode(sourceFile, n));
}
function createCodeFixToRemoveNode(node: Node) {
let end = node.getEnd();
const endCharCode = sourceFile.text.charCodeAt(end);
const afterEndCharCode = sourceFile.text.charCodeAt(end + 1);
if (isLineBreak(endCharCode)) {
end += 1;
}
// in the case of CR LF, you could have two consecutive new line characters for one new line.
// this needs to be differenciated from two LF LF chars that actually mean two new lines.
if (isLineBreak(afterEndCharCode) && endCharCode !== afterEndCharCode) {
end += 1;
}
const start = node.getStart();
return createCodeFix("", start, end - start);
function deleteRange(range: TextRange) {
return makeChange(textChanges.ChangeTracker.fromCodeFixContext(context).deleteRange(sourceFile, range));
}
function findFirstNonSpaceCharPosStarting(start: number) {
while (isWhiteSpace(sourceFile.text.charCodeAt(start))) {
start += 1;
}
return start;
function deleteNodeInList(n: Node) {
return makeChange(textChanges.ChangeTracker.fromCodeFixContext(context).deleteNodeInList(sourceFile, n));
}
function createCodeFix(newText: string, start: number, length: number): CodeAction[] {
function deleteNodeRange(start: Node, end: Node) {
return makeChange(textChanges.ChangeTracker.fromCodeFixContext(context).deleteNodeRange(sourceFile, start, end));
}
function replaceNode(n: Node, newNode: Node) {
return makeChange(textChanges.ChangeTracker.fromCodeFixContext(context).replaceNode(sourceFile, n, newNode));
}
function makeChange(changeTracker: textChanges.ChangeTracker) {
return [{
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Remove_declaration_for_Colon_0), { 0: token.getText() }),
changes: [{
fileName: sourceFile.fileName,
textChanges: [{ newText, span: { start, length } }]
}]
changes: changeTracker.getChanges()
}];
}
function removeSingleItem<T extends Node>(elements: NodeArray<T>, token: T): CodeAction[] {
if (elements[0] === token.parent) {
return createCodeFix("", token.parent.pos, token.parent.end - token.parent.pos + 1);
}
else {
return createCodeFix("", token.parent.pos - 1, token.parent.end - token.parent.pos + 1);
}
}
}
});
}

View File

@ -1,10 +1,12 @@
/// <reference path="./pathCompletions.ts" />
/* @internal */
namespace ts.Completions {
export type Log = (message: string) => void;
export function getCompletionsAtPosition(host: LanguageServiceHost, typeChecker: TypeChecker, log: Log, compilerOptions: CompilerOptions, sourceFile: SourceFile, position: number): CompletionInfo | undefined {
if (isInReferenceComment(sourceFile, position)) {
return getTripleSlashReferenceCompletion(sourceFile, position, compilerOptions, host);
return PathCompletions.getTripleSlashReferenceCompletion(sourceFile, position, compilerOptions, host);
}
if (isInString(sourceFile, position)) {
@ -16,11 +18,16 @@ namespace ts.Completions {
return undefined;
}
const { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, isJsDocTagName } = completionData;
const { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, requestJsDocTagName, requestJsDocTag } = completionData;
if (isJsDocTagName) {
if (requestJsDocTagName) {
// If the current position is a jsDoc tag name, only tag names should be provided for completion
return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries: JsDoc.getAllJsDocCompletionEntries() };
return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries: JsDoc.getJSDocTagNameCompletions() };
}
if (requestJsDocTag) {
// If the current position is a jsDoc tag, only tags should be provided for completion
return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries: JsDoc.getJSDocTagCompletions() };
}
const entries: CompletionEntry[] = [];
@ -54,7 +61,7 @@ namespace ts.Completions {
}
// Add keywords if this is not a member completion list
if (!isMemberCompletion && !isJsDocTagName) {
if (!isMemberCompletion && !requestJsDocTag && !requestJsDocTagName) {
addRange(entries, keywordCompletions);
}
@ -171,7 +178,7 @@ namespace ts.Completions {
// i.e. import * as ns from "/*completion position*/";
// import x = require("/*completion position*/");
// var y = require("/*completion position*/");
return getStringLiteralCompletionEntriesFromModuleNames(<StringLiteral>node, compilerOptions, host, typeChecker);
return PathCompletions.getStringLiteralCompletionEntriesFromModuleNames(<StringLiteral>node, compilerOptions, host, typeChecker);
}
else if (isEqualityExpression(node.parent)) {
// Get completions from the type of the other operand
@ -273,489 +280,6 @@ namespace ts.Completions {
}
}
function getStringLiteralCompletionEntriesFromModuleNames(node: StringLiteral, compilerOptions: CompilerOptions, host: LanguageServiceHost, typeChecker: TypeChecker): CompletionInfo {
const literalValue = normalizeSlashes(node.text);
const scriptPath = node.getSourceFile().path;
const scriptDirectory = getDirectoryPath(scriptPath);
const span = getDirectoryFragmentTextSpan((<StringLiteral>node).text, node.getStart() + 1);
let entries: CompletionEntry[];
if (isPathRelativeToScript(literalValue) || isRootedDiskPath(literalValue)) {
const extensions = getSupportedExtensions(compilerOptions);
if (compilerOptions.rootDirs) {
entries = getCompletionEntriesForDirectoryFragmentWithRootDirs(
compilerOptions.rootDirs, literalValue, scriptDirectory, extensions, /*includeExtensions*/false, span, compilerOptions, host, scriptPath);
}
else {
entries = getCompletionEntriesForDirectoryFragment(
literalValue, scriptDirectory, extensions, /*includeExtensions*/false, span, host, scriptPath);
}
}
else {
// Check for node modules
entries = getCompletionEntriesForNonRelativeModules(literalValue, scriptDirectory, span, compilerOptions, host, typeChecker);
}
return {
isGlobalCompletion: false,
isMemberCompletion: false,
isNewIdentifierLocation: true,
entries
};
}
/**
* Takes a script path and returns paths for all potential folders that could be merged with its
* containing folder via the "rootDirs" compiler option
*/
function getBaseDirectoriesFromRootDirs(rootDirs: string[], basePath: string, scriptPath: string, ignoreCase: boolean): string[] {
// Make all paths absolute/normalized if they are not already
rootDirs = map(rootDirs, rootDirectory => normalizePath(isRootedDiskPath(rootDirectory) ? rootDirectory : combinePaths(basePath, rootDirectory)));
// Determine the path to the directory containing the script relative to the root directory it is contained within
let relativeDirectory: string;
for (const rootDirectory of rootDirs) {
if (containsPath(rootDirectory, scriptPath, basePath, ignoreCase)) {
relativeDirectory = scriptPath.substr(rootDirectory.length);
break;
}
}
// Now find a path for each potential directory that is to be merged with the one containing the script
return deduplicate(map(rootDirs, rootDirectory => combinePaths(rootDirectory, relativeDirectory)));
}
function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs: string[], fragment: string, scriptPath: string, extensions: string[], includeExtensions: boolean, span: TextSpan, compilerOptions: CompilerOptions, host: LanguageServiceHost, exclude?: string): CompletionEntry[] {
const basePath = compilerOptions.project || host.getCurrentDirectory();
const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames());
const baseDirectories = getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptPath, ignoreCase);
const result: CompletionEntry[] = [];
for (const baseDirectory of baseDirectories) {
getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensions, includeExtensions, span, host, exclude, result);
}
return result;
}
/**
* Given a path ending at a directory, gets the completions for the path, and filters for those entries containing the basename.
*/
function getCompletionEntriesForDirectoryFragment(fragment: string, scriptPath: string, extensions: string[], includeExtensions: boolean, span: TextSpan, host: LanguageServiceHost, exclude?: string, result: CompletionEntry[] = []): CompletionEntry[] {
if (fragment === undefined) {
fragment = "";
}
fragment = normalizeSlashes(fragment);
/**
* Remove the basename from the path. Note that we don't use the basename to filter completions;
* the client is responsible for refining completions.
*/
fragment = getDirectoryPath(fragment);
if (fragment === "") {
fragment = "." + directorySeparator;
}
fragment = ensureTrailingDirectorySeparator(fragment);
const absolutePath = normalizeAndPreserveTrailingSlash(isRootedDiskPath(fragment) ? fragment : combinePaths(scriptPath, fragment));
const baseDirectory = getDirectoryPath(absolutePath);
const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames());
if (tryDirectoryExists(host, baseDirectory)) {
// Enumerate the available files if possible
const files = tryReadDirectory(host, baseDirectory, extensions, /*exclude*/undefined, /*include*/["./*"]);
if (files) {
/**
* Multiple file entries might map to the same truncated name once we remove extensions
* (happens iff includeExtensions === false)so we use a set-like data structure. Eg:
*
* both foo.ts and foo.tsx become foo
*/
const foundFiles = createMap<boolean>();
for (let filePath of files) {
filePath = normalizePath(filePath);
if (exclude && comparePaths(filePath, exclude, scriptPath, ignoreCase) === Comparison.EqualTo) {
continue;
}
const foundFileName = includeExtensions ? getBaseFileName(filePath) : removeFileExtension(getBaseFileName(filePath));
if (!foundFiles.get(foundFileName)) {
foundFiles.set(foundFileName, true);
}
}
forEachKey(foundFiles, foundFile => {
result.push(createCompletionEntryForModule(foundFile, ScriptElementKind.scriptElement, span));
});
}
// If possible, get folder completion as well
const directories = tryGetDirectories(host, baseDirectory);
if (directories) {
for (const directory of directories) {
const directoryName = getBaseFileName(normalizePath(directory));
result.push(createCompletionEntryForModule(directoryName, ScriptElementKind.directory, span));
}
}
}
return result;
}
/**
* Check all of the declared modules and those in node modules. Possible sources of modules:
* Modules that are found by the type checker
* Modules found relative to "baseUrl" compliler options (including patterns from "paths" compiler option)
* Modules from node_modules (i.e. those listed in package.json)
* This includes all files that are found in node_modules/moduleName/ with acceptable file extensions
*/
function getCompletionEntriesForNonRelativeModules(fragment: string, scriptPath: string, span: TextSpan, compilerOptions: CompilerOptions, host: LanguageServiceHost, typeChecker: TypeChecker): CompletionEntry[] {
const { baseUrl, paths } = compilerOptions;
let result: CompletionEntry[];
if (baseUrl) {
const fileExtensions = getSupportedExtensions(compilerOptions);
const projectDir = compilerOptions.project || host.getCurrentDirectory();
const absolute = isRootedDiskPath(baseUrl) ? baseUrl : combinePaths(projectDir, baseUrl);
result = getCompletionEntriesForDirectoryFragment(fragment, normalizePath(absolute), fileExtensions, /*includeExtensions*/false, span, host);
if (paths) {
for (const path in paths) {
if (paths.hasOwnProperty(path)) {
if (path === "*") {
if (paths[path]) {
for (const pattern of paths[path]) {
for (const match of getModulesForPathsPattern(fragment, baseUrl, pattern, fileExtensions, host)) {
result.push(createCompletionEntryForModule(match, ScriptElementKind.externalModuleName, span));
}
}
}
}
else if (startsWith(path, fragment)) {
const entry = paths[path] && paths[path].length === 1 && paths[path][0];
if (entry) {
result.push(createCompletionEntryForModule(path, ScriptElementKind.externalModuleName, span));
}
}
}
}
}
}
else {
result = [];
}
getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, span, result);
for (const moduleName of enumeratePotentialNonRelativeModules(fragment, scriptPath, compilerOptions, typeChecker, host)) {
result.push(createCompletionEntryForModule(moduleName, ScriptElementKind.externalModuleName, span));
}
return result;
}
function getModulesForPathsPattern(fragment: string, baseUrl: string, pattern: string, fileExtensions: string[], host: LanguageServiceHost): string[] {
if (host.readDirectory) {
const parsed = hasZeroOrOneAsteriskCharacter(pattern) ? tryParsePattern(pattern) : undefined;
if (parsed) {
// The prefix has two effective parts: the directory path and the base component after the filepath that is not a
// full directory component. For example: directory/path/of/prefix/base*
const normalizedPrefix = normalizeAndPreserveTrailingSlash(parsed.prefix);
const normalizedPrefixDirectory = getDirectoryPath(normalizedPrefix);
const normalizedPrefixBase = getBaseFileName(normalizedPrefix);
const fragmentHasPath = fragment.indexOf(directorySeparator) !== -1;
// Try and expand the prefix to include any path from the fragment so that we can limit the readDirectory call
const expandedPrefixDirectory = fragmentHasPath ? combinePaths(normalizedPrefixDirectory, normalizedPrefixBase + getDirectoryPath(fragment)) : normalizedPrefixDirectory;
const normalizedSuffix = normalizePath(parsed.suffix);
const baseDirectory = combinePaths(baseUrl, expandedPrefixDirectory);
const completePrefix = fragmentHasPath ? baseDirectory : ensureTrailingDirectorySeparator(baseDirectory) + normalizedPrefixBase;
// If we have a suffix, then we need to read the directory all the way down. We could create a glob
// that encodes the suffix, but we would have to escape the character "?" which readDirectory
// doesn't support. For now, this is safer but slower
const includeGlob = normalizedSuffix ? "**/*" : "./*";
const matches = tryReadDirectory(host, baseDirectory, fileExtensions, undefined, [includeGlob]);
if (matches) {
const result: string[] = [];
// Trim away prefix and suffix
for (const match of matches) {
const normalizedMatch = normalizePath(match);
if (!endsWith(normalizedMatch, normalizedSuffix) || !startsWith(normalizedMatch, completePrefix)) {
continue;
}
const start = completePrefix.length;
const length = normalizedMatch.length - start - normalizedSuffix.length;
result.push(removeFileExtension(normalizedMatch.substr(start, length)));
}
return result;
}
}
}
return undefined;
}
function enumeratePotentialNonRelativeModules(fragment: string, scriptPath: string, options: CompilerOptions, typeChecker: TypeChecker, host: LanguageServiceHost): string[] {
// Check If this is a nested module
const isNestedModule = fragment.indexOf(directorySeparator) !== -1;
const moduleNameFragment = isNestedModule ? fragment.substr(0, fragment.lastIndexOf(directorySeparator)) : undefined;
// Get modules that the type checker picked up
const ambientModules = map(typeChecker.getAmbientModules(), sym => stripQuotes(sym.name));
let nonRelativeModules = filter(ambientModules, moduleName => startsWith(moduleName, fragment));
// Nested modules of the form "module-name/sub" need to be adjusted to only return the string
// after the last '/' that appears in the fragment because that's where the replacement span
// starts
if (isNestedModule) {
const moduleNameWithSeperator = ensureTrailingDirectorySeparator(moduleNameFragment);
nonRelativeModules = map(nonRelativeModules, moduleName => {
if (startsWith(fragment, moduleNameWithSeperator)) {
return moduleName.substr(moduleNameWithSeperator.length);
}
return moduleName;
});
}
if (!options.moduleResolution || options.moduleResolution === ModuleResolutionKind.NodeJs) {
for (const visibleModule of enumerateNodeModulesVisibleToScript(host, scriptPath)) {
if (!isNestedModule) {
nonRelativeModules.push(visibleModule.moduleName);
}
else if (startsWith(visibleModule.moduleName, moduleNameFragment)) {
const nestedFiles = tryReadDirectory(host, visibleModule.moduleDir, supportedTypeScriptExtensions, /*exclude*/undefined, /*include*/["./*"]);
if (nestedFiles) {
for (let f of nestedFiles) {
f = normalizePath(f);
const nestedModule = removeFileExtension(getBaseFileName(f));
nonRelativeModules.push(nestedModule);
}
}
}
}
}
return deduplicate(nonRelativeModules);
}
function getTripleSlashReferenceCompletion(sourceFile: SourceFile, position: number, compilerOptions: CompilerOptions, host: LanguageServiceHost): CompletionInfo {
const token = getTokenAtPosition(sourceFile, position);
if (!token) {
return undefined;
}
const commentRanges: CommentRange[] = getLeadingCommentRanges(sourceFile.text, token.pos);
if (!commentRanges || !commentRanges.length) {
return undefined;
}
const range = forEach(commentRanges, commentRange => position >= commentRange.pos && position <= commentRange.end && commentRange);
if (!range) {
return undefined;
}
const completionInfo: CompletionInfo = {
/**
* We don't want the editor to offer any other completions, such as snippets, inside a comment.
*/
isGlobalCompletion: false,
isMemberCompletion: false,
/**
* The user may type in a path that doesn't yet exist, creating a "new identifier"
* with respect to the collection of identifiers the server is aware of.
*/
isNewIdentifierLocation: true,
entries: []
};
const text = sourceFile.text.substr(range.pos, position - range.pos);
const match = tripleSlashDirectiveFragmentRegex.exec(text);
if (match) {
const prefix = match[1];
const kind = match[2];
const toComplete = match[3];
const scriptPath = getDirectoryPath(sourceFile.path);
if (kind === "path") {
// Give completions for a relative path
const span: TextSpan = getDirectoryFragmentTextSpan(toComplete, range.pos + prefix.length);
completionInfo.entries = getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, getSupportedExtensions(compilerOptions), /*includeExtensions*/true, span, host, sourceFile.path);
}
else {
// Give completions based on the typings available
const span: TextSpan = { start: range.pos + prefix.length, length: match[0].length - prefix.length };
completionInfo.entries = getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, span);
}
}
return completionInfo;
}
function getCompletionEntriesFromTypings(host: LanguageServiceHost, options: CompilerOptions, scriptPath: string, span: TextSpan, result: CompletionEntry[] = []): CompletionEntry[] {
// Check for typings specified in compiler options
if (options.types) {
for (const moduleName of options.types) {
result.push(createCompletionEntryForModule(moduleName, ScriptElementKind.externalModuleName, span));
}
}
else if (host.getDirectories) {
let typeRoots: string[];
try {
// Wrap in try catch because getEffectiveTypeRoots touches the filesystem
typeRoots = getEffectiveTypeRoots(options, host);
}
catch (e) {}
if (typeRoots) {
for (const root of typeRoots) {
getCompletionEntriesFromDirectories(host, root, span, result);
}
}
}
if (host.getDirectories) {
// Also get all @types typings installed in visible node_modules directories
for (const packageJson of findPackageJsons(scriptPath, host)) {
const typesDir = combinePaths(getDirectoryPath(packageJson), "node_modules/@types");
getCompletionEntriesFromDirectories(host, typesDir, span, result);
}
}
return result;
}
function getCompletionEntriesFromDirectories(host: LanguageServiceHost, directory: string, span: TextSpan, result: Push<CompletionEntry>) {
if (host.getDirectories && tryDirectoryExists(host, directory)) {
const directories = tryGetDirectories(host, directory);
if (directories) {
for (let typeDirectory of directories) {
typeDirectory = normalizePath(typeDirectory);
result.push(createCompletionEntryForModule(getBaseFileName(typeDirectory), ScriptElementKind.externalModuleName, span));
}
}
}
}
function findPackageJsons(currentDir: string, host: LanguageServiceHost): string[] {
const paths: string[] = [];
let currentConfigPath: string;
while (true) {
currentConfigPath = findConfigFile(currentDir, (f) => tryFileExists(host, f), "package.json");
if (currentConfigPath) {
paths.push(currentConfigPath);
currentDir = getDirectoryPath(currentConfigPath);
const parent = getDirectoryPath(currentDir);
if (currentDir === parent) {
break;
}
currentDir = parent;
}
else {
break;
}
}
return paths;
}
function enumerateNodeModulesVisibleToScript(host: LanguageServiceHost, scriptPath: string) {
const result: VisibleModuleInfo[] = [];
if (host.readFile && host.fileExists) {
for (const packageJson of findPackageJsons(scriptPath, host)) {
const contents = tryReadingPackageJson(packageJson);
if (!contents) {
return;
}
const nodeModulesDir = combinePaths(getDirectoryPath(packageJson), "node_modules");
const foundModuleNames: string[] = [];
// Provide completions for all non @types dependencies
for (const key of nodeModulesDependencyKeys) {
addPotentialPackageNames(contents[key], foundModuleNames);
}
for (const moduleName of foundModuleNames) {
const moduleDir = combinePaths(nodeModulesDir, moduleName);
result.push({
moduleName,
moduleDir
});
}
}
}
return result;
function tryReadingPackageJson(filePath: string) {
try {
const fileText = tryReadFile(host, filePath);
return fileText ? JSON.parse(fileText) : undefined;
}
catch (e) {
return undefined;
}
}
function addPotentialPackageNames(dependencies: any, result: string[]) {
if (dependencies) {
for (const dep in dependencies) {
if (dependencies.hasOwnProperty(dep) && !startsWith(dep, "@types/")) {
result.push(dep);
}
}
}
}
}
function createCompletionEntryForModule(name: string, kind: string, replacementSpan: TextSpan): CompletionEntry {
return { name, kind, kindModifiers: ScriptElementKindModifier.none, sortText: name, replacementSpan };
}
// Replace everything after the last directory seperator that appears
function getDirectoryFragmentTextSpan(text: string, textStart: number): TextSpan {
const index = text.lastIndexOf(directorySeparator);
const offset = index !== -1 ? index + 1 : 0;
return { start: textStart + offset, length: text.length - offset };
}
// Returns true if the path is explicitly relative to the script (i.e. relative to . or ..)
function isPathRelativeToScript(path: string) {
if (path && path.length >= 2 && path.charCodeAt(0) === CharacterCodes.dot) {
const slashIndex = path.length >= 3 && path.charCodeAt(1) === CharacterCodes.dot ? 2 : 1;
const slashCharCode = path.charCodeAt(slashIndex);
return slashCharCode === CharacterCodes.slash || slashCharCode === CharacterCodes.backslash;
}
return false;
}
function normalizeAndPreserveTrailingSlash(path: string) {
return hasTrailingDirectorySeparator(path) ? ensureTrailingDirectorySeparator(normalizePath(path)) : normalizePath(path);
}
export function getCompletionEntryDetails(typeChecker: TypeChecker, log: (message: string) => void, compilerOptions: CompilerOptions, sourceFile: SourceFile, position: number, entryName: string): CompletionEntryDetails {
// Compute all the completion symbols again.
const completionData = getCompletionData(typeChecker, log, sourceFile, position);
@ -814,7 +338,10 @@ namespace ts.Completions {
function getCompletionData(typeChecker: TypeChecker, log: (message: string) => void, sourceFile: SourceFile, position: number) {
const isJavaScriptFile = isSourceFileJavaScript(sourceFile);
let isJsDocTagName = false;
// JsDoc tag-name is just the name of the JSDoc tagname (exclude "@")
let requestJsDocTagName = false;
// JsDoc tag includes both "@" and tag-name
let requestJsDocTag = false;
let start = timestamp();
const currentToken = getTokenAtPosition(sourceFile, position);
@ -826,10 +353,32 @@ namespace ts.Completions {
log("getCompletionData: Is inside comment: " + (timestamp() - start));
if (insideComment) {
// The current position is next to the '@' sign, when no tag name being provided yet.
// Provide a full list of tag names
if (hasDocComment(sourceFile, position) && sourceFile.text.charCodeAt(position - 1) === CharacterCodes.at) {
isJsDocTagName = true;
if (hasDocComment(sourceFile, position)) {
// The current position is next to the '@' sign, when no tag name being provided yet.
// Provide a full list of tag names
if (sourceFile.text.charCodeAt(position - 1) === CharacterCodes.at) {
requestJsDocTagName = true;
}
else {
// When completion is requested without "@", we will have check to make sure that
// there are no comments prefix the request position. We will only allow "*" and space.
// e.g
// /** |c| /*
//
// /**
// |c|
// */
//
// /**
// * |c|
// */
//
// /**
// * |c|
// */
const lineStart = getLineStartPositionForPosition(position, sourceFile);
requestJsDocTag = !(sourceFile.text.substring(lineStart, position).match(/[^\*|\s|(/\*\*)]/));
}
}
// Completion should work inside certain JsDoc tags. For example:
@ -839,7 +388,7 @@ namespace ts.Completions {
const tag = getJsDocTagAtPosition(sourceFile, position);
if (tag) {
if (tag.tagName.pos <= position && position <= tag.tagName.end) {
isJsDocTagName = true;
requestJsDocTagName = true;
}
switch (tag.kind) {
@ -854,8 +403,8 @@ namespace ts.Completions {
}
}
if (isJsDocTagName) {
return { symbols: undefined, isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, location: undefined, isRightOfDot: false, isJsDocTagName };
if (requestJsDocTagName || requestJsDocTag) {
return { symbols: undefined, isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, location: undefined, isRightOfDot: false, requestJsDocTagName, requestJsDocTag };
}
if (!insideJsDocTagExpression) {
@ -898,8 +447,8 @@ namespace ts.Completions {
return undefined;
}
const { parent, kind } = contextToken;
if (kind === SyntaxKind.DotToken) {
let parent = contextToken.parent;
if (contextToken.kind === SyntaxKind.DotToken) {
if (parent.kind === SyntaxKind.PropertyAccessExpression) {
node = (<PropertyAccessExpression>contextToken.parent).expression;
isRightOfDot = true;
@ -915,16 +464,24 @@ namespace ts.Completions {
}
}
else if (sourceFile.languageVariant === LanguageVariant.JSX) {
switch (contextToken.parent.kind) {
// <UI.Test /* completion position */ />
// If the tagname is a property access expression, we will then walk up to the top most of property access expression.
// Then, try to get a JSX container and its associated attributes type.
if (parent && parent.kind === SyntaxKind.PropertyAccessExpression) {
contextToken = parent;
parent = parent.parent;
}
switch (parent.kind) {
case SyntaxKind.JsxClosingElement:
if (kind === SyntaxKind.SlashToken) {
if (contextToken.kind === SyntaxKind.SlashToken) {
isStartingCloseTag = true;
location = contextToken;
}
break;
case SyntaxKind.BinaryExpression:
if (!((contextToken.parent as BinaryExpression).left.flags & NodeFlags.ThisNodeHasError)) {
if (!((parent as BinaryExpression).left.flags & NodeFlags.ThisNodeHasError)) {
// It has a left-hand side, so we're not in an opening JSX tag.
break;
}
@ -933,7 +490,7 @@ namespace ts.Completions {
case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.JsxElement:
case SyntaxKind.JsxOpeningElement:
if (kind === SyntaxKind.LessThanToken) {
if (contextToken.kind === SyntaxKind.LessThanToken) {
isRightOfOpenTag = true;
location = contextToken;
}
@ -983,7 +540,7 @@ namespace ts.Completions {
log("getCompletionData: Semantic work: " + (timestamp() - semanticStart));
return { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), isJsDocTagName };
return { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), requestJsDocTagName, requestJsDocTag };
function getTypeScriptMemberSymbols(): void {
// Right of dot member completion list
@ -1401,6 +958,7 @@ namespace ts.Completions {
case SyntaxKind.LessThanSlashToken:
case SyntaxKind.SlashToken:
case SyntaxKind.Identifier:
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.JsxAttributes:
case SyntaxKind.JsxAttribute:
case SyntaxKind.JsxSpreadAttribute:
@ -1457,20 +1015,18 @@ namespace ts.Completions {
}
function isFunction(kind: SyntaxKind): boolean {
if (!isFunctionLikeKind(kind)) {
return false;
}
switch (kind) {
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
case SyntaxKind.IndexSignature:
case SyntaxKind.Constructor:
case SyntaxKind.ConstructorType:
case SyntaxKind.FunctionType:
return false;
default:
return true;
}
return false;
}
/**
@ -1748,59 +1304,6 @@ namespace ts.Completions {
});
}
/**
* Matches a triple slash reference directive with an incomplete string literal for its path. Used
* to determine if the caret is currently within the string literal and capture the literal fragment
* for completions.
* For example, this matches
*
* /// <reference path="fragment
*
* but not
*
* /// <reference path="fragment"
*/
const tripleSlashDirectiveFragmentRegex = /^(\/\/\/\s*<reference\s+(path|types)\s*=\s*(?:'|"))([^\3"]*)$/;
interface VisibleModuleInfo {
moduleName: string;
moduleDir: string;
}
const nodeModulesDependencyKeys = ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"];
function tryGetDirectories(host: LanguageServiceHost, directoryName: string): string[] {
return tryIOAndConsumeErrors(host, host.getDirectories, directoryName);
}
function tryReadDirectory(host: LanguageServiceHost, path: string, extensions?: string[], exclude?: string[], include?: string[]): string[] {
return tryIOAndConsumeErrors(host, host.readDirectory, path, extensions, exclude, include);
}
function tryReadFile(host: LanguageServiceHost, path: string): string {
return tryIOAndConsumeErrors(host, host.readFile, path);
}
function tryFileExists(host: LanguageServiceHost, path: string): boolean {
return tryIOAndConsumeErrors(host, host.fileExists, path);
}
function tryDirectoryExists(host: LanguageServiceHost, path: string): boolean {
try {
return directoryProbablyExists(path, host);
}
catch (e) {}
return undefined;
}
function tryIOAndConsumeErrors<T>(host: LanguageServiceHost, toApply: (...a: any[]) => T, ...args: any[]) {
try {
return toApply && toApply.apply(host, args);
}
catch (e) {}
return undefined;
}
function isEqualityExpression(node: Node): node is BinaryExpression {
return isBinaryExpression(node) && isEqualityOperatorKind(node.operatorToken.kind);
}

View File

@ -1,4 +1,4 @@
namespace ts {
namespace ts {
/**
* The document registry represents a store of SourceFile objects that can be shared between
* multiple LanguageService instances. A LanguageService instance holds on the SourceFile (AST)

View File

@ -1,4 +1,4 @@
/// <reference path="./importTracker.ts" />
/// <reference path="./importTracker.ts" />
/* @internal */
namespace ts.FindAllReferences {

View File

@ -314,24 +314,55 @@ namespace ts.formatting {
return 0;
}
/* @internal */
export function formatNode(node: Node, sourceFileLike: SourceFileLike, languageVariant: LanguageVariant, initialIndentation: number, delta: number, rulesProvider: RulesProvider): TextChange[] {
const range = { pos: 0, end: sourceFileLike.text.length };
return formatSpanWorker(
range,
node,
initialIndentation,
delta,
getFormattingScanner(sourceFileLike.text, languageVariant, range.pos, range.end),
rulesProvider.getFormatOptions(),
rulesProvider,
FormattingRequestKind.FormatSelection,
_ => false, // assume that node does not have any errors
sourceFileLike);
}
function formatSpan(originalRange: TextRange,
sourceFile: SourceFile,
options: FormatCodeSettings,
rulesProvider: RulesProvider,
requestKind: FormattingRequestKind): TextChange[] {
// find the smallest node that fully wraps the range and compute the initial indentation for the node
const enclosingNode = findEnclosingNode(originalRange, sourceFile);
return formatSpanWorker(
originalRange,
enclosingNode,
SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, options),
getOwnOrInheritedDelta(enclosingNode, options, sourceFile),
getFormattingScanner(sourceFile.text, sourceFile.languageVariant, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end),
options,
rulesProvider,
requestKind,
prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange),
sourceFile);
}
const rangeContainsError = prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange);
function formatSpanWorker(originalRange: TextRange,
enclosingNode: Node,
initialIndentation: number,
delta: number,
formattingScanner: FormattingScanner,
options: FormatCodeSettings,
rulesProvider: RulesProvider,
requestKind: FormattingRequestKind,
rangeContainsError: (r: TextRange) => boolean,
sourceFile: SourceFileLike): TextChange[] {
// formatting context is used by rules provider
const formattingContext = new FormattingContext(sourceFile, requestKind);
// find the smallest node that fully wraps the range and compute the initial indentation for the node
const enclosingNode = findEnclosingNode(originalRange, sourceFile);
const formattingScanner = getFormattingScanner(sourceFile, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end);
const initialIndentation = SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, options);
let previousRangeHasError: boolean;
let previousRange: TextRangeWithKind;
let previousParent: Node;
@ -351,7 +382,6 @@ namespace ts.formatting {
undecoratedStartLine = sourceFile.getLineAndCharacterOfPosition(getNonDecoratorTokenPosOfNode(enclosingNode, sourceFile)).line;
}
const delta = getOwnOrInheritedDelta(enclosingNode, options, sourceFile);
processNode(enclosingNode, enclosingNode, startLine, undecoratedStartLine, initialIndentation, delta);
}

View File

@ -15,7 +15,7 @@ namespace ts.formatting {
private contextNodeBlockIsOnOneLine: boolean;
private nextNodeBlockIsOnOneLine: boolean;
constructor(public sourceFile: SourceFile, public formattingRequestKind: FormattingRequestKind) {
constructor(public readonly sourceFile: SourceFileLike, public formattingRequestKind: FormattingRequestKind) {
}
public updateContext(currentRange: TextRangeWithKind, currentTokenParent: Node, nextRange: TextRangeWithKind, nextTokenParent: Node, commonParent: Node) {

View File

@ -30,11 +30,11 @@ namespace ts.formatting {
RescanJsxText,
}
export function getFormattingScanner(sourceFile: SourceFile, startPos: number, endPos: number): FormattingScanner {
export function getFormattingScanner(text: string, languageVariant: LanguageVariant, startPos: number, endPos: number): FormattingScanner {
Debug.assert(scanner === undefined, "Scanner should be undefined");
scanner = sourceFile.languageVariant === LanguageVariant.JSX ? jsxScanner : standardScanner;
scanner = languageVariant === LanguageVariant.JSX ? jsxScanner : standardScanner;
scanner.setText(sourceFile.text);
scanner.setText(text);
scanner.setTextPos(startPos);
let wasNewLine = true;
@ -276,8 +276,8 @@ namespace ts.formatting {
function isOnToken(): boolean {
Debug.assert(scanner !== undefined);
const current = (lastTokenInfo && lastTokenInfo.token.kind) || scanner.getToken();
const startPos = (lastTokenInfo && lastTokenInfo.token.pos) || scanner.getStartPos();
const current = lastTokenInfo ? lastTokenInfo.token.kind : scanner.getToken();
const startPos = lastTokenInfo ? lastTokenInfo.token.pos : scanner.getStartPos();
return startPos < endPos && current !== SyntaxKind.EndOfFileToken && !isTrivia(current);
}

View File

@ -24,6 +24,10 @@ namespace ts.formatting {
return this.rulesMap;
}
public getFormatOptions(): Readonly<ts.FormatCodeSettings> {
return this.options;
}
public ensureUpToDate(options: ts.FormatCodeSettings) {
if (!this.options || !ts.compareDataObjects(this.options, options)) {
const activeRules = this.createActiveRules(options);

View File

@ -8,7 +8,19 @@ namespace ts.formatting {
Unknown = -1
}
export function getIndentation(position: number, sourceFile: SourceFile, options: EditorSettings): number {
/**
* Computed indentation for a given position in source file
* @param position - position in file
* @param sourceFile - target source file
* @param options - set of editor options that control indentation
* @param assumeNewLineBeforeCloseBrace - false when getIndentation is called on the text from the real source file.
* true - when we need to assume that position is on the newline. This is usefult for codefixes, i.e.
* function f() {
* |}
* when inserting some text after open brace we would like to get the value of indentation as if newline was already there.
* However by default indentation at position | will be 0 so 'assumeNewLineBeforeCloseBrace' allows to override this behavior,
*/
export function getIndentation(position: number, sourceFile: SourceFile, options: EditorSettings, assumeNewLineBeforeCloseBrace = false): number {
if (position > sourceFile.text.length) {
return getBaseIndentation(options); // past EOF
}
@ -71,13 +83,14 @@ namespace ts.formatting {
if (positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current, previous)) {
currentStart = getStartLineAndCharacterForNode(current, sourceFile);
if (nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile)) {
indentationDelta = 0;
const nextTokenKind = nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile);
if (nextTokenKind !== NextTokenKind.Unknown) {
// handle cases when codefix is about to be inserted before the close brace
indentationDelta = assumeNewLineBeforeCloseBrace && nextTokenKind === NextTokenKind.CloseBrace ? options.indentSize : 0;
}
else {
indentationDelta = lineAtPosition !== currentStart.line ? options.indentSize : 0;
}
break;
}
@ -218,15 +231,21 @@ namespace ts.formatting {
return findColumnForFirstNonWhitespaceCharacterInLine(currentLineAndChar, sourceFile, options);
}
function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken: Node, current: Node, lineAtPosition: number, sourceFile: SourceFile): boolean {
const enum NextTokenKind {
Unknown,
OpenBrace,
CloseBrace
}
function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken: Node, current: Node, lineAtPosition: number, sourceFile: SourceFile): NextTokenKind {
const nextToken = findNextToken(precedingToken, current);
if (!nextToken) {
return false;
return NextTokenKind.Unknown;
}
if (nextToken.kind === SyntaxKind.OpenBraceToken) {
// open braces are always indented at the parent level
return true;
return NextTokenKind.OpenBrace;
}
else if (nextToken.kind === SyntaxKind.CloseBraceToken) {
// close braces are indented at the parent level if they are located on the same line with cursor
@ -239,17 +258,17 @@ namespace ts.formatting {
// $}
const nextTokenStartLine = getStartLineAndCharacterForNode(nextToken, sourceFile).line;
return lineAtPosition === nextTokenStartLine;
return lineAtPosition === nextTokenStartLine ? NextTokenKind.CloseBrace : NextTokenKind.Unknown;
}
return false;
return NextTokenKind.Unknown;
}
function getStartLineAndCharacterForNode(n: Node, sourceFile: SourceFile): LineAndCharacter {
function getStartLineAndCharacterForNode(n: Node, sourceFile: SourceFileLike): LineAndCharacter {
return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));
}
export function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFile): boolean {
export function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFileLike): boolean {
if (parent.kind === SyntaxKind.IfStatement && (<IfStatement>parent).elseStatement === child) {
const elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile);
Debug.assert(elseKeyword !== undefined);
@ -261,15 +280,15 @@ namespace ts.formatting {
return false;
}
function getContainingList(node: Node, sourceFile: SourceFile): NodeArray<Node> {
function getListIfStartEndIsInListRange(list: NodeArray<Node>, start: number, end: number) {
return list && rangeContainsStartEnd(list, start, end) ? list : undefined;
}
export function getContainingList(node: Node, sourceFile: SourceFile): NodeArray<Node> {
if (node.parent) {
switch (node.parent.kind) {
case SyntaxKind.TypeReference:
if ((<TypeReferenceNode>node.parent).typeArguments &&
rangeContainsStartEnd((<TypeReferenceNode>node.parent).typeArguments, node.getStart(sourceFile), node.getEnd())) {
return (<TypeReferenceNode>node.parent).typeArguments;
}
break;
return getListIfStartEndIsInListRange((<TypeReferenceNode>node.parent).typeArguments, node.getStart(sourceFile), node.getEnd());
case SyntaxKind.ObjectLiteralExpression:
return (<ObjectLiteralExpression>node.parent).properties;
case SyntaxKind.ArrayLiteralExpression:
@ -280,30 +299,26 @@ namespace ts.formatting {
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.CallSignature:
case SyntaxKind.Constructor:
case SyntaxKind.ConstructorType:
case SyntaxKind.ConstructSignature: {
const start = node.getStart(sourceFile);
if ((<SignatureDeclaration>node.parent).typeParameters &&
rangeContainsStartEnd((<SignatureDeclaration>node.parent).typeParameters, start, node.getEnd())) {
return (<SignatureDeclaration>node.parent).typeParameters;
}
if (rangeContainsStartEnd((<SignatureDeclaration>node.parent).parameters, start, node.getEnd())) {
return (<SignatureDeclaration>node.parent).parameters;
}
break;
return getListIfStartEndIsInListRange((<SignatureDeclaration>node.parent).typeParameters, start, node.getEnd()) ||
getListIfStartEndIsInListRange((<SignatureDeclaration>node.parent).parameters, start, node.getEnd());
}
case SyntaxKind.ClassDeclaration:
return getListIfStartEndIsInListRange((<ClassDeclaration>node.parent).typeParameters, node.getStart(sourceFile), node.getEnd());
case SyntaxKind.NewExpression:
case SyntaxKind.CallExpression: {
const start = node.getStart(sourceFile);
if ((<CallExpression>node.parent).typeArguments &&
rangeContainsStartEnd((<CallExpression>node.parent).typeArguments, start, node.getEnd())) {
return (<CallExpression>node.parent).typeArguments;
}
if ((<CallExpression>node.parent).arguments &&
rangeContainsStartEnd((<CallExpression>node.parent).arguments, start, node.getEnd())) {
return (<CallExpression>node.parent).arguments;
}
break;
return getListIfStartEndIsInListRange((<CallExpression>node.parent).typeArguments, start, node.getEnd()) ||
getListIfStartEndIsInListRange((<CallExpression>node.parent).arguments, start, node.getEnd());
}
case SyntaxKind.VariableDeclarationList:
return getListIfStartEndIsInListRange((<VariableDeclarationList>node.parent).declarations, node.getStart(sourceFile), node.getEnd());
case SyntaxKind.NamedImports:
case SyntaxKind.NamedExports:
return getListIfStartEndIsInListRange((<NamedImportsOrExports>node.parent).elements, node.getStart(sourceFile), node.getEnd());
}
}
return undefined;
@ -400,7 +415,7 @@ namespace ts.formatting {
value of 'character' for '$' is 3
value of 'column' for '$' is 6 (assuming that tab size is 4)
*/
export function findFirstNonWhitespaceCharacterAndColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorSettings) {
export function findFirstNonWhitespaceCharacterAndColumn(startPos: number, endPos: number, sourceFile: SourceFileLike, options: EditorSettings) {
let character = 0;
let column = 0;
for (let pos = startPos; pos < endPos; pos++) {
@ -421,7 +436,7 @@ namespace ts.formatting {
return { column, character };
}
export function findFirstNonWhitespaceColumn(startPos: number, endPos: number, sourceFile: SourceFile, options: EditorSettings): number {
export function findFirstNonWhitespaceColumn(startPos: number, endPos: number, sourceFile: SourceFileLike, options: EditorSettings): number {
return findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options).column;
}

View File

@ -1,4 +1,4 @@
/* @internal */
/* @internal */
namespace ts.GoToDefinition {
export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile, position: number): DefinitionInfo[] {
/// Triple slash reference comments

View File

@ -0,0 +1,27 @@
/* @internal */
namespace ts.GoToImplementation {
export function getImplementationAtPosition(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFiles: SourceFile[], node: Node): ImplementationLocation[] {
const context = new FindAllReferences.FindImplementationsContext(typeChecker, cancellationToken);
// If invoked directly on a shorthand property assignment, then return
// the declaration of the symbol being assigned (not the symbol being assigned to).
if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) {
const result: ImplementationLocation[] = [];
FindAllReferences.getReferenceEntriesForShorthandPropertyAssignment(node, context, result);
return result.length > 0 ? result : undefined;
}
else if (node.kind === SyntaxKind.SuperKeyword || isSuperProperty(node.parent)) {
// References to and accesses on the super keyword only have one possible implementation, so no
// need to "Find all References"
const symbol = typeChecker.getSymbolAtLocation(node);
return symbol.valueDeclaration && [context.getReferenceEntryFromNode(symbol.valueDeclaration)];
}
else {
// Perform "Find all References" and retrieve only those that are implementations
const referencedSymbols = FindAllReferences.getReferencedSymbolsForNode(context,
node, sourceFiles, /*findInStrings*/false, /*findInComments*/false, /*isForRename*/false, /*implementations*/true);
const result = flatMap(referencedSymbols, symbol => symbol.references);
return result && result.length > 0 ? result : undefined;
}
}
}

View File

@ -1,4 +1,4 @@
/* @internal */
/* @internal */
namespace ts.JsDoc {
const jsDocTagNames = [
"augments",
@ -42,7 +42,8 @@ namespace ts.JsDoc {
"prop",
"version"
];
let jsDocCompletionEntries: CompletionEntry[];
let jsDocTagNameCompletionEntries: CompletionEntry[];
let jsDocTagCompletionEntries: CompletionEntry[];
export function getJsDocCommentsFromDeclarations(declarations: Declaration[]) {
// Only collect doc comments from duplicate declarations once:
@ -88,8 +89,8 @@ namespace ts.JsDoc {
return undefined;
}
export function getAllJsDocCompletionEntries(): CompletionEntry[] {
return jsDocCompletionEntries || (jsDocCompletionEntries = ts.map(jsDocTagNames, tagName => {
export function getJSDocTagNameCompletions(): CompletionEntry[] {
return jsDocTagNameCompletionEntries || (jsDocTagNameCompletionEntries = ts.map(jsDocTagNames, tagName => {
return {
name: tagName,
kind: ScriptElementKind.keyword,
@ -99,6 +100,17 @@ namespace ts.JsDoc {
}));
}
export function getJSDocTagCompletions(): CompletionEntry[] {
return jsDocTagCompletionEntries || (jsDocTagCompletionEntries = ts.map(jsDocTagNames, tagName => {
return {
name: `@${tagName}`,
kind: ScriptElementKind.keyword,
kindModifiers: "",
sortText: "0"
};
}));
}
/**
* Checks if position points to a valid position to add JSDoc comments, and if so,
* returns the appropriate template. Otherwise returns an empty string.
@ -166,7 +178,8 @@ namespace ts.JsDoc {
const posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position);
const lineStart = sourceFile.getLineStarts()[posLineAndChar.line];
const indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character);
// replace non-whitespace characters in prefix with spaces.
const indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character).replace(/\S/i, () => " ");
const isJavaScriptFile = hasJavaScriptFileExtension(sourceFile.fileName);
let docParams = "";

View File

@ -1,4 +1,4 @@
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
/// <reference path='../compiler/types.ts' />

View File

@ -1,4 +1,4 @@
/* @internal */
/* @internal */
namespace ts.NavigateTo {
type RawNavigateToItem = { name: string; fileName: string; matchKind: PatternMatchKind; isCaseSensitive: boolean; declaration: Declaration };

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