Merge branch 'master' into js-object-literal-assignments-as-declarations

This commit is contained in:
Nathan Shively-Sanders
2018-02-20 09:14:36 -08:00
94 changed files with 2464 additions and 1075 deletions
+96
View File
@@ -0,0 +1,96 @@
workflows:
version: 2
main:
jobs:
- node9:
filters:
branches:
only:
- master
- release-2.5
- release-2.6
- release-2.7
- circleci
- node8:
filters:
branches:
only:
- master
- release-2.5
- release-2.6
- release-2.7
- circleci
- node6:
filters:
branches:
only:
- master
- release-2.5
- release-2.6
- release-2.7
- circleci
nightly:
triggers:
- schedule:
cron: "0 8 * * *"
filters:
branches:
only: master
jobs:
- node9:
filters:
branches:
only:
- master
- release-2.5
- release-2.6
- release-2.7
- circleci
context: nightlies
- node8:
filters:
branches:
only:
- master
- release-2.5
- release-2.6
- release-2.7
- circleci
context: nightlies
- node6:
filters:
branches:
only:
- master
- release-2.5
- release-2.6
- release-2.7
- circleci
context: nightlies
base: &base
environment:
- workerCount: 4
steps:
- checkout
- run: |
npm uninstall typescript --no-save
npm uninstall tslint --no-save
npm install
#npm update Appeared in Jenkins only
npm test
version: 2
jobs:
node9:
docker:
- image: circleci/node:9
<<: *base
node8:
docker:
- image: circleci/node:8
<<: *base
node6:
docker:
- image: circleci/node:6
<<: *base
+5 -9
View File
@@ -53,7 +53,6 @@ const cmdLineOptions = minimist(process.argv.slice(2), {
"ru": "runners", "runner": "runners",
"r": "reporter",
"c": "colors", "color": "colors",
"f": "files", "file": "files",
"w": "workers",
},
default: {
@@ -69,7 +68,6 @@ const cmdLineOptions = minimist(process.argv.slice(2), {
light: process.env.light === undefined || process.env.light !== "false",
reporter: process.env.reporter || process.env.r,
lint: process.env.lint || true,
files: process.env.f || process.env.file || process.env.files || "",
workers: process.env.workerCount || os.cpus().length,
}
});
@@ -1112,13 +1110,11 @@ function spawnLintWorker(files: {path: string}[], callback: (failures: number) =
gulp.task("lint", "Runs tslint on the compiler sources. Optional arguments are: --f[iles]=regex", ["build-rules"], () => {
if (fold.isTravis()) console.log(fold.start("lint"));
const fileMatcher = cmdLineOptions.files;
const files = fileMatcher
? `src/**/${fileMatcher}`
: `Gulpfile.ts "scripts/generateLocalizedDiagnosticMessages.ts" "scripts/tslint/**/*.ts" "src/**/*.ts" --exclude "src/lib/*.d.ts"`;
const cmd = `node node_modules/tslint/bin/tslint ${files} --formatters-dir ./built/local/tslint/formatters --format autolinkableStylish`;
console.log("Linting: " + cmd);
child_process.execSync(cmd, { stdio: [0, 1, 2] });
for (const project of ["scripts/tslint/tsconfig.json", "src/tsconfig-base.json"]) {
const cmd = `node node_modules/tslint/bin/tslint --project ${project} --formatters-dir ./built/local/tslint/formatters --format autolinkableStylish`;
console.log("Linting: " + cmd);
child_process.execSync(cmd, { stdio: [0, 1, 2] });
}
if (fold.isTravis()) console.log(fold.end("lint"));
});
+8 -9
View File
@@ -141,6 +141,7 @@ var harnessSources = harnessCoreSources.concat([
"typingsInstaller.ts",
"projectErrors.ts",
"matchFiles.ts",
"organizeImports.ts",
"initializeTSConfig.ts",
"extractConstants.ts",
"extractFunctions.ts",
@@ -1301,15 +1302,13 @@ function spawnLintWorker(files, callback) {
desc("Runs tslint on the compiler sources. Optional arguments are: f[iles]=regex");
task("lint", ["build-rules"], () => {
if (fold.isTravis()) console.log(fold.start("lint"));
const fileMatcher = process.env.f || process.env.file || process.env.files;
const files = fileMatcher
? `src/**/${fileMatcher}`
: `Gulpfile.ts scripts/generateLocalizedDiagnosticMessages.ts "scripts/tslint/**/*.ts" "src/**/*.ts" --exclude "src/lib/*.d.ts"`;
const cmd = `node node_modules/tslint/bin/tslint ${files} --formatters-dir ./built/local/tslint/formatters --format autolinkableStylish`;
console.log("Linting: " + cmd);
jake.exec([cmd], { interactive: true, windowsVerbatimArguments: true }, () => {
function lint(project, cb) {
const cmd = `node node_modules/tslint/bin/tslint --project ${project} --formatters-dir ./built/local/tslint/formatters --format autolinkableStylish`;
console.log("Linting: " + cmd);
jake.exec([cmd], { interactive: true, windowsVerbatimArguments: true }, cb);
}
lint("scripts/tslint/tsconfig.json", () => lint("src/tsconfig-base.json", () => {
if (fold.isTravis()) console.log(fold.end("lint"));
complete();
});
}));
});
+2 -2
View File
@@ -27,7 +27,7 @@ function walk(ctx: Lint.WalkContext<void>): void {
/** Skip certain function/method names whose parameter names are not informative. */
function shouldIgnoreCalledExpression(expression: ts.Expression): boolean {
if (expression.kind === ts.SyntaxKind.PropertyAccessExpression) {
const methodName = (expression as ts.PropertyAccessExpression).name.text as string;
const methodName = (expression as ts.PropertyAccessExpression).name.text;
if (methodName.indexOf("set") === 0) {
return true;
}
@@ -45,7 +45,7 @@ function walk(ctx: Lint.WalkContext<void>): void {
}
}
else if (expression.kind === ts.SyntaxKind.Identifier) {
const functionName = (expression as ts.Identifier).text as string;
const functionName = (expression as ts.Identifier).text;
if (functionName.indexOf("set") === 0) {
return true;
}
@@ -0,0 +1,98 @@
/**
* @license
* Copyright 2016 Palantir Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as ts from "typescript";
import * as Lint from "tslint";
export class Rule extends Lint.Rules.TypedRule {
/* tslint:disable:object-literal-sort-keys */
public static metadata: Lint.IRuleMetadata = {
ruleName: "no-unnecessary-type-assertion",
description: "Warns if a type assertion does not change the type of an expression.",
options: {
type: "list",
listType: {
type: "array",
items: { type: "string" },
},
},
optionsDescription: "A list of whitelisted assertion types to ignore",
type: "typescript",
hasFix: true,
typescriptOnly: true,
requiresTypeInfo: true,
};
/* tslint:enable:object-literal-sort-keys */
public static FAILURE_STRING = "This assertion is unnecessary since it does not change the type of the expression.";
public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
return this.applyWithWalker(new Walker(sourceFile, this.ruleName, this.ruleArguments, program.getTypeChecker()));
}
}
class Walker extends Lint.AbstractWalker<string[]> {
constructor(sourceFile: ts.SourceFile, ruleName: string, options: string[], private readonly checker: ts.TypeChecker) {
super(sourceFile, ruleName, options);
}
public walk(sourceFile: ts.SourceFile) {
const cb = (node: ts.Node): void => {
switch (node.kind) {
case ts.SyntaxKind.TypeAssertionExpression:
case ts.SyntaxKind.AsExpression:
this.verifyCast(node as ts.TypeAssertion | ts.AsExpression);
}
return ts.forEachChild(node, cb);
};
return ts.forEachChild(sourceFile, cb);
}
private verifyCast(node: ts.TypeAssertion | ts.NonNullExpression | ts.AsExpression) {
if (ts.isAssertionExpression(node) && this.options.indexOf(node.type.getText(this.sourceFile)) !== -1) {
return;
}
const castType = this.checker.getTypeAtLocation(node);
if (castType === undefined) {
return;
}
if (node.kind !== ts.SyntaxKind.NonNullExpression &&
(castType.flags & ts.TypeFlags.Literal ||
castType.flags & ts.TypeFlags.Object &&
(castType as ts.ObjectType).objectFlags & ts.ObjectFlags.Tuple) ||
// Sometimes tuple types don't have ObjectFlags.Tuple set, like when
// they're being matched against an inferred type. So, in addition,
// check if any properties are numbers, which implies that this is
// likely a tuple type.
(castType.getProperties().some((symbol) => !isNaN(Number(symbol.name))))) {
// It's not always safe to remove a cast to a literal type or tuple
// type, as those types are sometimes widened without the cast.
return;
}
const uncastType = this.checker.getTypeAtLocation(node.expression);
if (uncastType === castType) {
this.addFailureAtNode(node, Rule.FAILURE_STRING, node.kind === ts.SyntaxKind.TypeAssertionExpression
? Lint.Replacement.deleteFromTo(node.getStart(), node.expression.getStart())
: Lint.Replacement.deleteFromTo(node.expression.getEnd(), node.getEnd()));
}
}
}
+1
View File
@@ -1,5 +1,6 @@
{
"compilerOptions": {
"lib": ["es6"],
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
+12 -15
View File
@@ -264,7 +264,7 @@ namespace ts {
return (isGlobalScopeAugmentation(<ModuleDeclaration>node) ? "__global" : `"${moduleName}"`) as __String;
}
if (name.kind === SyntaxKind.ComputedPropertyName) {
const nameExpression = (<ComputedPropertyName>name).expression;
const nameExpression = name.expression;
// treat computed property names where expression is string/numeric literal as just string/numeric literal
if (isStringOrNumericLiteral(nameExpression)) {
return escapeLeadingUnderscores(nameExpression.text);
@@ -459,10 +459,7 @@ namespace ts {
// and this case is specially handled. Module augmentations should only be merged with original module definition
// and should never be merged directly with other augmentation, and the latter case would be possible if automatic merge is allowed.
if (node.kind === SyntaxKind.JSDocTypedefTag) Debug.assert(isInJavaScriptFile(node)); // We shouldn't add symbols for JSDoc nodes if not in a JS file.
const isJSDocTypedefInJSDocNamespace = node.kind === SyntaxKind.JSDocTypedefTag &&
(node as JSDocTypedefTag).name &&
(node as JSDocTypedefTag).name.kind === SyntaxKind.Identifier &&
((node as JSDocTypedefTag).name as Identifier).isInJSDocNamespace;
const isJSDocTypedefInJSDocNamespace = isJSDocTypedefTag(node) && node.name && node.name.kind === SyntaxKind.Identifier && node.name.isInJSDocNamespace;
if ((!isAmbientModule(node) && (hasExportModifier || container.flags & NodeFlags.ExportContext)) || isJSDocTypedefInJSDocNamespace) {
const exportKind = symbolFlags & SymbolFlags.Value ? SymbolFlags.ExportValue : 0;
const local = declareSymbol(container.locals, /*parent*/ undefined, node, exportKind, symbolExcludes);
@@ -527,7 +524,7 @@ namespace ts {
if (!isIIFE) {
currentFlow = { flags: FlowFlags.Start };
if (containerFlags & (ContainerFlags.IsFunctionExpression | ContainerFlags.IsObjectLiteralOrClassExpressionMethod)) {
(<FlowStart>currentFlow).container = <FunctionExpression | ArrowFunction | MethodDeclaration>node;
currentFlow.container = <FunctionExpression | ArrowFunction | MethodDeclaration>node;
}
}
// We create a return control flow graph for IIFEs and constructors. For constructors
@@ -997,7 +994,7 @@ namespace ts {
addAntecedent(postLoopLabel, currentFlow);
bind(node.initializer);
if (node.initializer.kind !== SyntaxKind.VariableDeclarationList) {
bindAssignmentTargetFlow(<Expression>node.initializer);
bindAssignmentTargetFlow(node.initializer);
}
bindIterativeStatement(node.statement, postLoopLabel, preLoopLabel);
addAntecedent(preLoopLabel, currentFlow);
@@ -1170,7 +1167,7 @@ namespace ts {
i++;
}
const preCaseLabel = createBranchLabel();
addAntecedent(preCaseLabel, createFlowSwitchClause(preSwitchCaseFlow, <SwitchStatement>node.parent, clauseStart, i + 1));
addAntecedent(preCaseLabel, createFlowSwitchClause(preSwitchCaseFlow, node.parent, clauseStart, i + 1));
addAntecedent(preCaseLabel, fallthroughFlow);
currentFlow = finishFlowLabel(preCaseLabel);
const clause = clauses[i];
@@ -1251,13 +1248,13 @@ namespace ts {
else if (node.kind === SyntaxKind.ObjectLiteralExpression) {
for (const p of (<ObjectLiteralExpression>node).properties) {
if (p.kind === SyntaxKind.PropertyAssignment) {
bindDestructuringTargetFlow((<PropertyAssignment>p).initializer);
bindDestructuringTargetFlow(p.initializer);
}
else if (p.kind === SyntaxKind.ShorthandPropertyAssignment) {
bindAssignmentTargetFlow((<ShorthandPropertyAssignment>p).name);
bindAssignmentTargetFlow(p.name);
}
else if (p.kind === SyntaxKind.SpreadAssignment) {
bindAssignmentTargetFlow((<SpreadAssignment>p).expression);
bindAssignmentTargetFlow(p.expression);
}
}
}
@@ -1572,7 +1569,7 @@ namespace ts {
}
function hasExportDeclarations(node: ModuleDeclaration | SourceFile): boolean {
const body = node.kind === SyntaxKind.SourceFile ? node : (<ModuleDeclaration>node).body;
const body = node.kind === SyntaxKind.SourceFile ? node : node.body;
if (body && (body.kind === SyntaxKind.SourceFile || body.kind === SyntaxKind.ModuleBlock)) {
for (const stat of (<BlockLike>body).statements) {
if (stat.kind === SyntaxKind.ExportDeclaration || stat.kind === SyntaxKind.ExportAssignment) {
@@ -2210,7 +2207,7 @@ namespace ts {
function checkTypePredicate(node: TypePredicateNode) {
const { parameterName, type } = node;
if (parameterName && parameterName.kind === SyntaxKind.Identifier) {
checkStrictModeIdentifier(parameterName as Identifier);
checkStrictModeIdentifier(parameterName);
}
if (parameterName && parameterName.kind === SyntaxKind.ThisType) {
seenThisKeyword = true;
@@ -2565,13 +2562,13 @@ namespace ts {
}
}
checkStrictModeFunctionName(<FunctionDeclaration>node);
checkStrictModeFunctionName(node);
if (inStrictMode) {
checkStrictModeFunctionDeclaration(node);
bindBlockScopedDeclaration(node, SymbolFlags.Function, SymbolFlags.FunctionExcludes);
}
else {
declareSymbolAndAddToSymbolTable(<Declaration>node, SymbolFlags.Function, SymbolFlags.FunctionExcludes);
declareSymbolAndAddToSymbolTable(node, SymbolFlags.Function, SymbolFlags.FunctionExcludes);
}
}
+1 -1
View File
@@ -228,7 +228,7 @@ namespace ts {
host = oldProgramOrHost as CompilerHost;
}
else {
newProgram = newProgramOrRootNames as Program;
newProgram = newProgramOrRootNames;
host = hostOrOptions as BuilderProgramHost;
oldProgram = oldProgramOrHost as BuilderProgram;
}
+197 -198
View File
File diff suppressed because it is too large Load Diff
+13
View File
@@ -1438,6 +1438,14 @@ namespace ts {
}
}
export function group<T>(values: ReadonlyArray<T>, getGroupId: (value: T) => string): ReadonlyArray<ReadonlyArray<T>> {
const groupIdToGroup = createMultiMap<T>();
for (const value of values) {
groupIdToGroup.add(getGroupId(value), value);
}
return arrayFrom(groupIdToGroup.values());
}
/**
* Tests whether a value is an array.
*/
@@ -1897,6 +1905,11 @@ namespace ts {
Comparison.EqualTo;
}
/** True is greater than false. */
export function compareBooleans(a: boolean, b: boolean): Comparison {
return compareValues(a ? 1 : 0, b ? 1 : 0);
}
function compareMessageText(text1: string | DiagnosticMessageChain, text2: string | DiagnosticMessageChain): Comparison {
while (text1 && text2) {
// We still have both chains.
+13 -23
View File
@@ -350,8 +350,8 @@ namespace ts {
// and also for non-optional initialized parameters that aren't a parameter property
// these types may need to add `undefined`.
const shouldUseResolverType = declaration.kind === SyntaxKind.Parameter &&
(resolver.isRequiredInitializedParameter(declaration as ParameterDeclaration) ||
resolver.isOptionalUninitializedParameterProperty(declaration as ParameterDeclaration));
(resolver.isRequiredInitializedParameter(declaration) ||
resolver.isOptionalUninitializedParameterProperty(declaration));
if (type && !shouldUseResolverType) {
// Write the type
emitType(type);
@@ -839,10 +839,10 @@ namespace ts {
function isVisibleNamedBinding(namedBindings: NamespaceImport | NamedImports): boolean {
if (namedBindings) {
if (namedBindings.kind === SyntaxKind.NamespaceImport) {
return resolver.isDeclarationVisible(<NamespaceImport>namedBindings);
return resolver.isDeclarationVisible(namedBindings);
}
else {
return forEach((<NamedImports>namedBindings).elements, namedImport => resolver.isDeclarationVisible(namedImport));
return namedBindings.elements.some(namedImport => resolver.isDeclarationVisible(namedImport));
}
}
}
@@ -865,11 +865,11 @@ namespace ts {
}
if (node.importClause.namedBindings.kind === SyntaxKind.NamespaceImport) {
write("* as ");
writeTextOfNode(currentText, (<NamespaceImport>node.importClause.namedBindings).name);
writeTextOfNode(currentText, node.importClause.namedBindings.name);
}
else {
write("{ ");
emitCommaList((<NamedImports>node.importClause.namedBindings).elements, emitImportOrExportSpecifier, resolver.isDeclarationVisible);
emitCommaList(node.importClause.namedBindings.elements, emitImportOrExportSpecifier, resolver.isDeclarationVisible);
write(" }");
}
}
@@ -886,18 +886,8 @@ namespace ts {
// external modules since they are indistinguishable from script files with ambient modules. To fix this in such d.ts files we'll emit top level 'export {}'
// so compiler will treat them as external modules.
resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || parent.kind !== SyntaxKind.ModuleDeclaration;
let moduleSpecifier: Node;
if (parent.kind === SyntaxKind.ImportEqualsDeclaration) {
const node = parent as ImportEqualsDeclaration;
moduleSpecifier = getExternalModuleImportEqualsDeclarationExpression(node);
}
else if (parent.kind === SyntaxKind.ModuleDeclaration) {
moduleSpecifier = (<ModuleDeclaration>parent).name;
}
else {
const node = parent as (ImportDeclaration | ExportDeclaration);
moduleSpecifier = node.moduleSpecifier;
}
const moduleSpecifier = parent.kind === SyntaxKind.ImportEqualsDeclaration ? getExternalModuleImportEqualsDeclarationExpression(parent) :
parent.kind === SyntaxKind.ModuleDeclaration ? parent.name : parent.moduleSpecifier;
if (moduleSpecifier.kind === SyntaxKind.StringLiteral && isBundledEmit && (compilerOptions.out || compilerOptions.outFile)) {
const moduleName = getExternalModuleNameFromDeclaration(host, resolver, parent);
@@ -1293,7 +1283,7 @@ namespace ts {
// so there is no check needed to see if declaration is visible
if (node.kind !== SyntaxKind.VariableDeclaration || isVariableDeclarationVisible(node)) {
if (isBindingPattern(node.name)) {
emitBindingPattern(<BindingPattern>node.name);
emitBindingPattern(node.name);
}
else {
writeNameOfDeclaration(node, getVariableDeclarationTypeVisibilityError);
@@ -1301,7 +1291,7 @@ namespace ts {
// If optional property emit ? but in the case of parameterProperty declaration with "?" indicating optional parameter for the constructor
// we don't want to emit property declaration with "?"
if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature ||
(node.kind === SyntaxKind.Parameter && !isParameterPropertyDeclaration(<ParameterDeclaration>node))) && hasQuestionToken(node)) {
(node.kind === SyntaxKind.Parameter && !isParameterPropertyDeclaration(node))) && hasQuestionToken(node)) {
write("?");
}
if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) && node.parent.kind === SyntaxKind.TypeLiteral) {
@@ -1389,7 +1379,7 @@ namespace ts {
if (bindingElement.name) {
if (isBindingPattern(bindingElement.name)) {
emitBindingPattern(<BindingPattern>bindingElement.name);
emitBindingPattern(bindingElement.name);
}
else {
writeTextOfNode(currentText, bindingElement.name);
@@ -1782,7 +1772,7 @@ namespace ts {
// For bindingPattern, we can't simply writeTextOfNode from the source file
// because we want to omit the initializer and using writeTextOfNode will result in initializer get emitted.
// Therefore, we will have to recursively emit each element in the bindingPattern.
emitBindingPattern(<BindingPattern>node.name);
emitBindingPattern(node.name);
}
else {
writeTextOfNode(currentText, node.name);
@@ -1921,7 +1911,7 @@ namespace ts {
// emit : declare function foo([a, [[b]], c]: [number, [[string]], number]): void;
// original with rest: function foo([a, ...c]) {}
// emit : declare function foo([a, ...c]): void;
emitBindingPattern(<BindingPattern>bindingElement.name);
emitBindingPattern(bindingElement.name);
}
else {
Debug.assert(bindingElement.name.kind === SyntaxKind.Identifier);
+6 -6
View File
@@ -951,7 +951,7 @@ namespace ts {
function emitEntityName(node: EntityName) {
if (node.kind === SyntaxKind.Identifier) {
emitExpression(<Identifier>node);
emitExpression(node);
}
else {
emit(node);
@@ -1709,7 +1709,7 @@ namespace ts {
emit(node);
}
else {
emitExpression(<Expression>node);
emitExpression(node);
}
}
}
@@ -2068,7 +2068,7 @@ namespace ts {
function emitModuleReference(node: ModuleReference) {
if (node.kind === SyntaxKind.Identifier) {
emitExpression(<Identifier>node);
emitExpression(node);
}
else {
emit(node);
@@ -2472,12 +2472,12 @@ namespace ts {
function emitPrologueDirectivesIfNeeded(sourceFileOrBundle: Bundle | SourceFile) {
if (isSourceFile(sourceFileOrBundle)) {
setSourceFile(sourceFileOrBundle as SourceFile);
emitPrologueDirectives((sourceFileOrBundle as SourceFile).statements);
setSourceFile(sourceFileOrBundle);
emitPrologueDirectives(sourceFileOrBundle.statements);
}
else {
const seenPrologueDirectives = createMap<true>();
for (const sourceFile of (sourceFileOrBundle as Bundle).sourceFiles) {
for (const sourceFile of sourceFileOrBundle.sourceFiles) {
setSourceFile(sourceFile);
emitPrologueDirectives(sourceFile.statements, /*startWithNewLine*/ true, seenPrologueDirectives);
}
+25 -25
View File
@@ -644,7 +644,7 @@ namespace ts {
}
export function updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode | undefined) {
return <FunctionTypeNode>updateSignatureDeclaration(node, typeParameters, parameters, type);
return updateSignatureDeclaration(node, typeParameters, parameters, type);
}
export function createConstructorTypeNode(typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined) {
@@ -652,7 +652,7 @@ namespace ts {
}
export function updateConstructorTypeNode(node: ConstructorTypeNode, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode | undefined) {
return <ConstructorTypeNode>updateSignatureDeclaration(node, typeParameters, parameters, type);
return updateSignatureDeclaration(node, typeParameters, parameters, type);
}
export function createTypeQueryNode(exprName: EntityName) {
@@ -1285,7 +1285,7 @@ namespace ts {
export function createYield(asteriskTokenOrExpression?: AsteriskToken | Expression, expression?: Expression) {
const node = <YieldExpression>createSynthesizedNode(SyntaxKind.YieldExpression);
node.asteriskToken = asteriskTokenOrExpression && asteriskTokenOrExpression.kind === SyntaxKind.AsteriskToken ? <AsteriskToken>asteriskTokenOrExpression : undefined;
node.expression = asteriskTokenOrExpression && asteriskTokenOrExpression.kind !== SyntaxKind.AsteriskToken ? <Expression>asteriskTokenOrExpression : expression;
node.expression = asteriskTokenOrExpression && asteriskTokenOrExpression.kind !== SyntaxKind.AsteriskToken ? asteriskTokenOrExpression : expression;
return node;
}
@@ -3415,13 +3415,13 @@ namespace ts {
switch (property.kind) {
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
return createExpressionForAccessorDeclaration(node.properties, <AccessorDeclaration>property, receiver, node.multiLine);
return createExpressionForAccessorDeclaration(node.properties, property, receiver, node.multiLine);
case SyntaxKind.PropertyAssignment:
return createExpressionForPropertyAssignment(<PropertyAssignment>property, receiver);
return createExpressionForPropertyAssignment(property, receiver);
case SyntaxKind.ShorthandPropertyAssignment:
return createExpressionForShorthandPropertyAssignment(<ShorthandPropertyAssignment>property, receiver);
return createExpressionForShorthandPropertyAssignment(property, receiver);
case SyntaxKind.MethodDeclaration:
return createExpressionForMethodDeclaration(<MethodDeclaration>property, receiver);
return createExpressionForMethodDeclaration(property, receiver);
}
}
@@ -4065,13 +4065,13 @@ namespace ts {
export function parenthesizePostfixOperand(operand: Expression) {
return isLeftHandSideExpression(operand)
? <LeftHandSideExpression>operand
? operand
: setTextRange(createParen(operand), operand);
}
export function parenthesizePrefixOperand(operand: Expression) {
return isUnaryExpression(operand)
? <UnaryExpression>operand
? operand
: setTextRange(createParen(operand), operand);
}
@@ -4203,7 +4203,7 @@ namespace ts {
export function parenthesizeConciseBody(body: ConciseBody): ConciseBody {
if (!isBlock(body) && getLeftmostExpression(body, /*stopAtCallExpressions*/ false).kind === SyntaxKind.ObjectLiteralExpression) {
return setTextRange(createParen(<Expression>body), body);
return setTextRange(createParen(body), body);
}
return body;
@@ -4360,10 +4360,10 @@ namespace ts {
const name = namespaceDeclaration.name;
return isGeneratedIdentifier(name) ? name : createIdentifier(getSourceTextOfNodeFromSourceFile(sourceFile, name) || idText(name));
}
if (node.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node).importClause) {
if (node.kind === SyntaxKind.ImportDeclaration && node.importClause) {
return getGeneratedNameForNode(node);
}
if (node.kind === SyntaxKind.ExportDeclaration && (<ExportDeclaration>node).moduleSpecifier) {
if (node.kind === SyntaxKind.ExportDeclaration && node.moduleSpecifier) {
return getGeneratedNameForNode(node);
}
return undefined;
@@ -4484,7 +4484,7 @@ namespace ts {
// `{a}` in `let [{a} = 1] = ...`
// `[a]` in `let [[a]] = ...`
// `[a]` in `let [[a] = 1] = ...`
return <ObjectBindingPattern | ArrayBindingPattern | Identifier>bindingElement.name;
return bindingElement.name;
}
if (isObjectLiteralElementLike(bindingElement)) {
@@ -4546,12 +4546,12 @@ namespace ts {
case SyntaxKind.Parameter:
case SyntaxKind.BindingElement:
// `...` in `let [...a] = ...`
return (<ParameterDeclaration | BindingElement>bindingElement).dotDotDotToken;
return bindingElement.dotDotDotToken;
case SyntaxKind.SpreadElement:
case SyntaxKind.SpreadAssignment:
// `...` in `[...a] = ...`
return <SpreadElement | SpreadAssignment>bindingElement;
return bindingElement;
}
return undefined;
@@ -4567,8 +4567,8 @@ namespace ts {
// `[a]` in `let { [a]: b } = ...`
// `"a"` in `let { "a": b } = ...`
// `1` in `let { 1: b } = ...`
if ((<BindingElement>bindingElement).propertyName) {
const propertyName = (<BindingElement>bindingElement).propertyName;
if (bindingElement.propertyName) {
const propertyName = bindingElement.propertyName;
return isComputedPropertyName(propertyName) && isStringOrNumericLiteral(propertyName.expression)
? propertyName.expression
: propertyName;
@@ -4581,8 +4581,8 @@ namespace ts {
// `[a]` in `({ [a]: b } = ...)`
// `"a"` in `({ "a": b } = ...)`
// `1` in `({ 1: b } = ...)`
if ((<PropertyAssignment>bindingElement).name) {
const propertyName = (<PropertyAssignment>bindingElement).name;
if (bindingElement.name) {
const propertyName = bindingElement.name;
return isComputedPropertyName(propertyName) && isStringOrNumericLiteral(propertyName.expression)
? propertyName.expression
: propertyName;
@@ -4592,7 +4592,7 @@ namespace ts {
case SyntaxKind.SpreadAssignment:
// `a` in `({ ...a } = ...)`
return (<SpreadAssignment>bindingElement).name;
return bindingElement.name;
}
const target = getTargetOfBindingOrAssignmentElement(bindingElement);
@@ -4629,7 +4629,7 @@ namespace ts {
Debug.assertNode(element.name, isIdentifier);
return setOriginalNode(setTextRange(createSpread(<Identifier>element.name), element), element);
}
const expression = convertToAssignmentElementTarget(<ObjectBindingPattern | ArrayBindingPattern | Identifier>element.name);
const expression = convertToAssignmentElementTarget(element.name);
return element.initializer
? setOriginalNode(
setTextRange(
@@ -4651,7 +4651,7 @@ namespace ts {
return setOriginalNode(setTextRange(createSpreadAssignment(<Identifier>element.name), element), element);
}
if (element.propertyName) {
const expression = convertToAssignmentElementTarget(<ObjectBindingPattern | ArrayBindingPattern | Identifier>element.name);
const expression = convertToAssignmentElementTarget(element.name);
return setOriginalNode(setTextRange(createPropertyAssignment(element.propertyName, element.initializer ? createAssignment(expression, element.initializer) : expression), element), element);
}
Debug.assertNode(element.name, isIdentifier);
@@ -4684,7 +4684,7 @@ namespace ts {
);
}
Debug.assertNode(node, isObjectLiteralExpression);
return <ObjectLiteralExpression>node;
return node;
}
export function convertToArrayAssignmentPattern(node: ArrayBindingOrAssignmentPattern) {
@@ -4698,7 +4698,7 @@ namespace ts {
);
}
Debug.assertNode(node, isArrayLiteralExpression);
return <ArrayLiteralExpression>node;
return node;
}
export function convertToAssignmentElementTarget(node: BindingOrAssignmentElementTarget): Expression {
@@ -4707,6 +4707,6 @@ namespace ts {
}
Debug.assertNode(node, isExpression);
return <Expression>node;
return node;
}
}
+8 -8
View File
@@ -690,7 +690,7 @@ namespace ts {
// Prime the scanner.
nextToken();
if (token() === SyntaxKind.EndOfFileToken) {
sourceFile.endOfFileToken = <EndOfFileToken>parseTokenNode();
sourceFile.endOfFileToken = parseTokenNode<EndOfFileToken>();
}
else if (token() === SyntaxKind.OpenBraceToken ||
lookAhead(() => token() === SyntaxKind.StringLiteral)) {
@@ -773,7 +773,7 @@ namespace ts {
sourceFile.statements = parseList(ParsingContext.SourceElements, parseStatement);
Debug.assert(token() === SyntaxKind.EndOfFileToken);
sourceFile.endOfFileToken = addJSDocComment(parseTokenNode() as EndOfFileToken);
sourceFile.endOfFileToken = addJSDocComment(parseTokenNode());
setExternalModuleIndicator(sourceFile);
@@ -1794,7 +1794,7 @@ namespace ts {
// into an actual .ConstructorDeclaration.
const methodDeclaration = <MethodDeclaration>node;
const nameIsConstructor = methodDeclaration.name.kind === SyntaxKind.Identifier &&
(<Identifier>methodDeclaration.name).originalKeywordKind === SyntaxKind.ConstructorKeyword;
methodDeclaration.name.originalKeywordKind === SyntaxKind.ConstructorKeyword;
return !nameIsConstructor;
}
@@ -3175,7 +3175,7 @@ namespace ts {
// Note: we call reScanGreaterToken so that we get an appropriately merged token
// for cases like `> > =` becoming `>>=`
if (isLeftHandSideExpression(expr) && isAssignmentOperator(reScanGreaterToken())) {
return makeBinaryExpression(expr, <BinaryOperatorToken>parseTokenNode(), parseAssignmentExpressionOrHigher());
return makeBinaryExpression(expr, parseTokenNode(), parseAssignmentExpressionOrHigher());
}
// It wasn't an assignment or a lambda. This is a conditional expression:
@@ -3624,7 +3624,7 @@ namespace ts {
}
}
else {
leftOperand = makeBinaryExpression(leftOperand, <BinaryOperatorToken>parseTokenNode(), parseBinaryExpressionOrHigher(newPrecedence));
leftOperand = makeBinaryExpression(leftOperand, parseTokenNode(), parseBinaryExpressionOrHigher(newPrecedence));
}
}
@@ -4079,7 +4079,7 @@ namespace ts {
else {
Debug.assert(opening.kind === SyntaxKind.JsxSelfClosingElement);
// Nothing else to do for self-closing elements
result = <JsxSelfClosingElement>opening;
result = opening;
}
// If the user writes the invalid code '<div></div><div></div>' in an expression context (i.e. not wrapped in
@@ -4097,7 +4097,7 @@ namespace ts {
badNode.end = invalidElement.end;
badNode.left = result;
badNode.right = invalidElement;
badNode.operatorToken = <BinaryOperatorToken>createMissingNode(SyntaxKind.CommaToken, /*reportAtCurrentPosition*/ false, /*diagnosticMessage*/ undefined);
badNode.operatorToken = createMissingNode(SyntaxKind.CommaToken, /*reportAtCurrentPosition*/ false, /*diagnosticMessage*/ undefined);
badNode.operatorToken.pos = badNode.operatorToken.end = badNode.right.pos;
return <JsxElement><Node>badNode;
}
@@ -5253,7 +5253,7 @@ namespace ts {
if (node.decorators || node.modifiers) {
// We reached this point because we encountered decorators and/or modifiers and assumed a declaration
// would follow. For recovery and error reporting purposes, return an incomplete declaration.
const missing = <Statement>createMissingNode(SyntaxKind.MissingDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected);
const missing = createMissingNode<Statement>(SyntaxKind.MissingDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected);
missing.pos = node.pos;
missing.decorators = node.decorators;
missing.modifiers = node.modifiers;
+1 -1
View File
@@ -812,7 +812,7 @@ namespace ts {
if (!result) {
// There were no unresolved/ambient resolutions.
Debug.assert(resolutions.length === moduleNames.length);
return <ResolvedModuleFull[]>resolutions;
return resolutions;
}
let j = 0;
+10 -10
View File
@@ -1995,7 +1995,7 @@ namespace ts {
// If we are here it is because this is a destructuring assignment.
if (isDestructuringAssignment(node)) {
return flattenDestructuringAssignment(
<DestructuringAssignment>node,
node,
visitor,
context,
FlattenLevel.All,
@@ -2023,7 +2023,7 @@ namespace ts {
);
}
else {
assignment = createBinary(<Identifier>decl.name, SyntaxKind.EqualsToken, visitNode(decl.initializer, visitor, isExpression));
assignment = createBinary(decl.name, SyntaxKind.EqualsToken, visitNode(decl.initializer, visitor, isExpression));
setTextRange(assignment, decl);
}
@@ -2632,10 +2632,10 @@ namespace ts {
function visit(node: Identifier | BindingPattern) {
if (node.kind === SyntaxKind.Identifier) {
state.hoistedLocalVariables.push((<Identifier>node));
state.hoistedLocalVariables.push(node);
}
else {
for (const element of (<BindingPattern>node).elements) {
for (const element of node.elements) {
if (!isOmittedExpression(element)) {
visit(element.name);
}
@@ -2716,7 +2716,7 @@ namespace ts {
convertedLoopState = outerConvertedLoopState;
if (loopOutParameters.length || lexicalEnvironment) {
const statements = isBlock(loopBody) ? (<Block>loopBody).statements.slice() : [loopBody];
const statements = isBlock(loopBody) ? loopBody.statements.slice() : [loopBody];
if (loopOutParameters.length) {
copyOutParameters(loopOutParameters, CopyDirection.ToOutParameter, statements);
}
@@ -2856,7 +2856,7 @@ namespace ts {
loop = convert(node, outermostLabeledStatement, convertedLoopBodyStatements);
}
else {
let clone = <IterationStatement>getMutableClone(node);
let clone = getMutableClone(node);
// clean statement part
clone.statement = undefined;
// visit childnodes to transform initializer/condition/incrementor parts
@@ -3039,7 +3039,7 @@ namespace ts {
switch (property.kind) {
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
const accessors = getAllAccessorDeclarations(node.properties, <AccessorDeclaration>property);
const accessors = getAllAccessorDeclarations(node.properties, property);
if (property === accessors.firstAccessor) {
expressions.push(transformAccessorsToExpression(receiver, accessors, node, node.multiLine));
}
@@ -3047,15 +3047,15 @@ namespace ts {
break;
case SyntaxKind.MethodDeclaration:
expressions.push(transformObjectLiteralMethodDeclarationToExpression(<MethodDeclaration>property, receiver, node, node.multiLine));
expressions.push(transformObjectLiteralMethodDeclarationToExpression(property, receiver, node, node.multiLine));
break;
case SyntaxKind.PropertyAssignment:
expressions.push(transformPropertyAssignmentToExpression(<PropertyAssignment>property, receiver, node.multiLine));
expressions.push(transformPropertyAssignmentToExpression(property, receiver, node.multiLine));
break;
case SyntaxKind.ShorthandPropertyAssignment:
expressions.push(transformShorthandPropertyAssignmentToExpression(<ShorthandPropertyAssignment>property, receiver, node.multiLine));
expressions.push(transformShorthandPropertyAssignmentToExpression(property, receiver, node.multiLine));
break;
default:
+1 -1
View File
@@ -183,7 +183,7 @@ namespace ts {
: visitNode(node.initializer, visitor, isForInitializer),
visitNode(node.condition, visitor, isExpression),
visitNode(node.incrementor, visitor, isExpression),
visitNode((<ForStatement>node).statement, asyncBodyVisitor, isStatement, liftToBlock)
visitNode(node.statement, asyncBodyVisitor, isStatement, liftToBlock)
);
}
+2 -3
View File
@@ -167,7 +167,7 @@ namespace ts {
objects.push(createObjectLiteral(chunkObject));
chunkObject = undefined;
}
const target = (e as SpreadAssignment).expression;
const target = e.expression;
objects.push(visitNode(target, visitor, isExpression));
}
else {
@@ -175,8 +175,7 @@ namespace ts {
chunkObject = [];
}
if (e.kind === SyntaxKind.PropertyAssignment) {
const p = e as PropertyAssignment;
chunkObject.push(createPropertyAssignment(p.name, visitNode(p.initializer, visitor, isExpression)));
chunkObject.push(createPropertyAssignment(e.name, visitNode(e.initializer, visitor, isExpression)));
}
else {
chunkObject.push(visitNode(e, visitor, isObjectLiteralElementLike));
+3 -4
View File
@@ -1771,16 +1771,15 @@ namespace ts {
for (let i = clausesWritten; i < numClauses; i++) {
const clause = caseBlock.clauses[i];
if (clause.kind === SyntaxKind.CaseClause) {
const caseClause = <CaseClause>clause;
if (containsYield(caseClause.expression) && pendingClauses.length > 0) {
if (containsYield(clause.expression) && pendingClauses.length > 0) {
break;
}
pendingClauses.push(
createCaseClause(
visitNode(caseClause.expression, visitor, isExpression),
visitNode(clause.expression, visitor, isExpression),
[
createInlineBreak(clauseLabels[i], /*location*/ caseClause.expression)
createInlineBreak(clauseLabels[i], /*location*/ clause.expression)
]
)
);
+10 -10
View File
@@ -57,19 +57,19 @@ namespace ts {
function transformJsxChildToExpression(node: JsxChild): Expression {
switch (node.kind) {
case SyntaxKind.JsxText:
return visitJsxText(<JsxText>node);
return visitJsxText(node);
case SyntaxKind.JsxExpression:
return visitJsxExpression(<JsxExpression>node);
return visitJsxExpression(node);
case SyntaxKind.JsxElement:
return visitJsxElement(<JsxElement>node, /*isChild*/ true);
return visitJsxElement(node, /*isChild*/ true);
case SyntaxKind.JsxSelfClosingElement:
return visitJsxSelfClosingElement(<JsxSelfClosingElement>node, /*isChild*/ true);
return visitJsxSelfClosingElement(node, /*isChild*/ true);
case SyntaxKind.JsxFragment:
return visitJsxFragment(<JsxFragment>node, /*isChild*/ true);
return visitJsxFragment(node, /*isChild*/ true);
default:
Debug.failBadSyntaxKind(node);
@@ -171,15 +171,15 @@ namespace ts {
else if (node.kind === SyntaxKind.StringLiteral) {
// Always recreate the literal to escape any escape sequences or newlines which may be in the original jsx string and which
// Need to be escaped to be handled correctly in a normal string
const literal = createLiteral(tryDecodeEntities((<StringLiteral>node).text) || (<StringLiteral>node).text);
literal.singleQuote = (node as StringLiteral).singleQuote !== undefined ? (node as StringLiteral).singleQuote : !isStringDoubleQuoted(node as StringLiteral, currentSourceFile);
const literal = createLiteral(tryDecodeEntities(node.text) || node.text);
literal.singleQuote = node.singleQuote !== undefined ? node.singleQuote : !isStringDoubleQuoted(node, currentSourceFile);
return setTextRange(literal, node);
}
else if (node.kind === SyntaxKind.JsxExpression) {
if (node.expression === undefined) {
return createTrue();
}
return visitJsxExpression(<JsxExpression>node);
return visitJsxExpression(node);
}
else {
Debug.failBadSyntaxKind(node);
@@ -279,10 +279,10 @@ namespace ts {
function getTagName(node: JsxElement | JsxOpeningLikeElement): Expression {
if (node.kind === SyntaxKind.JsxElement) {
return getTagName((<JsxElement>node).openingElement);
return getTagName(node.openingElement);
}
else {
const name = (<JsxOpeningLikeElement>node).tagName;
const name = node.tagName;
if (isIdentifier(name) && isIntrinsicJsxName(name.escapedText)) {
return createLiteral(idText(name));
}
+1 -1
View File
@@ -533,7 +533,7 @@ namespace ts {
}
if (isImportCall(node)) {
return visitImportCallExpression(<ImportCall>node);
return visitImportCallExpression(node);
}
else {
return visitEachChild(node, importCallExpressionVisitor, context);
+5 -6
View File
@@ -343,13 +343,12 @@ namespace ts {
continue;
}
const exportDecl = <ExportDeclaration>externalImport;
if (!exportDecl.exportClause) {
if (!externalImport.exportClause) {
// export * from ...
continue;
}
for (const element of exportDecl.exportClause.elements) {
for (const element of externalImport.exportClause.elements) {
// write name of indirectly exported entry, i.e. 'export {x} from ...'
exportedNames.push(
createPropertyAssignment(
@@ -472,7 +471,7 @@ namespace ts {
const importVariableName = getLocalNameForExternalImport(entry, currentSourceFile);
switch (entry.kind) {
case SyntaxKind.ImportDeclaration:
if (!(<ImportDeclaration>entry).importClause) {
if (!entry.importClause) {
// 'import "..."' case
// module is imported only for side-effects, no emit required
break;
@@ -491,7 +490,7 @@ namespace ts {
case SyntaxKind.ExportDeclaration:
Debug.assert(importVariableName !== undefined);
if ((<ExportDeclaration>entry).exportClause) {
if (entry.exportClause) {
// export {a, b as c} from 'foo'
//
// emit as:
@@ -501,7 +500,7 @@ namespace ts {
// "c": _["b"]
// });
const properties: PropertyAssignment[] = [];
for (const e of (<ExportDeclaration>entry).exportClause.elements) {
for (const e of entry.exportClause.elements) {
properties.push(
createPropertyAssignment(
createLiteral(idText(e.name)),
+10 -12
View File
@@ -242,13 +242,13 @@ namespace ts {
}
switch (node.kind) {
case SyntaxKind.ImportDeclaration:
return visitImportDeclaration(<ImportDeclaration>node);
return visitImportDeclaration(node);
case SyntaxKind.ImportEqualsDeclaration:
return visitImportEqualsDeclaration(<ImportEqualsDeclaration>node);
return visitImportEqualsDeclaration(node);
case SyntaxKind.ExportAssignment:
return visitExportAssignment(<ExportAssignment>node);
return visitExportAssignment(node);
case SyntaxKind.ExportDeclaration:
return visitExportDeclaration(<ExportDeclaration>node);
return visitExportDeclaration(node);
default:
Debug.fail("Unhandled ellided statement");
}
@@ -2010,7 +2010,7 @@ namespace ts {
case SyntaxKind.Identifier:
// Create a clone of the name with a new parent, and treat it as if it were
// a source tree node for the purposes of the checker.
const name = getMutableClone(<Identifier>node);
const name = getMutableClone(node);
name.flags &= ~NodeFlags.Synthesized;
name.original = undefined;
name.parent = getParseTreeNode(currentScope); // ensure the parent is set to a parse tree node.
@@ -2027,7 +2027,7 @@ namespace ts {
return name;
case SyntaxKind.QualifiedName:
return serializeQualifiedNameAsExpression(<QualifiedName>node, useFallback);
return serializeQualifiedNameAsExpression(node, useFallback);
}
}
@@ -2091,9 +2091,9 @@ namespace ts {
function getExpressionForPropertyName(member: ClassElement | EnumMember, generateNameForComputedPropertyName: boolean): Expression {
const name = member.name;
if (isComputedPropertyName(name)) {
return generateNameForComputedPropertyName && !isSimpleInlineableExpression((<ComputedPropertyName>name).expression)
return generateNameForComputedPropertyName && !isSimpleInlineableExpression(name.expression)
? getGeneratedNameForNode(name)
: (<ComputedPropertyName>name).expression;
: name.expression;
}
else if (isIdentifier(name)) {
return createLiteral(idText(name));
@@ -2961,7 +2961,7 @@ namespace ts {
const body = node.body;
if (body.kind === SyntaxKind.ModuleBlock) {
saveStateAndInvoke(body, body => addRange(statements, visitNodes((<ModuleBlock>body).statements, namespaceElementVisitor, isStatement)));
statementsLocation = (<ModuleBlock>body).statements;
statementsLocation = body.statements;
blockLocation = body;
}
else {
@@ -3547,9 +3547,7 @@ namespace ts {
return undefined;
}
return isPropertyAccessExpression(node) || isElementAccessExpression(node)
? resolver.getConstantValue(<PropertyAccessExpression | ElementAccessExpression>node)
: undefined;
return isPropertyAccessExpression(node) || isElementAccessExpression(node) ? resolver.getConstantValue(node) : undefined;
}
}
+3 -1
View File
@@ -2835,6 +2835,8 @@ namespace ts {
getAugmentedPropertiesOfType(type: Type): Symbol[];
getRootSymbols(symbol: Symbol): Symbol[];
getContextualType(node: Expression): Type | undefined;
/* @internal */ getContextualTypeForArgumentAtIndex(call: CallLikeExpression, argIndex: number): Type;
/* @internal */ getContextualTypeForJsxAttribute(attribute: JsxAttribute | JsxSpreadAttribute): Type | undefined;
/* @internal */ isContextSensitive(node: Expression | MethodDeclaration | ObjectLiteralElementLike | JsxAttributeLike): boolean;
/**
@@ -3307,7 +3309,7 @@ namespace ts {
/* @internal */ parent?: Symbol; // Parent symbol
/* @internal */ exportSymbol?: Symbol; // Exported symbol associated with this symbol
/* @internal */ constEnumOnlyModule?: boolean; // True if module contains only const enums or other modules with only const enums
/* @internal */ isReferenced?: boolean; // True if the symbol is referenced elsewhere
/* @internal */ isReferenced?: SymbolFlags; // True if the symbol is referenced elsewhere. Keeps track of the meaning of a reference in case a symbol is both a type parameter and parameter.
/* @internal */ isReplaceableByMethod?: boolean; // Can this Javascript class property be replaced by a method symbol?
/* @internal */ isAssigned?: boolean; // True if the symbol is a parameter with assignments
}
+35 -39
View File
@@ -570,17 +570,15 @@ namespace ts {
export function getTextOfPropertyName(name: PropertyName): __String {
switch (name.kind) {
case SyntaxKind.Identifier:
return (<Identifier>name).escapedText;
return name.escapedText;
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
return escapeLeadingUnderscores((<LiteralExpression>name).text);
return escapeLeadingUnderscores(name.text);
case SyntaxKind.ComputedPropertyName:
if (isStringOrNumericLiteral((<ComputedPropertyName>name).expression)) {
return escapeLeadingUnderscores((<LiteralExpression>(<ComputedPropertyName>name).expression).text);
}
return isStringOrNumericLiteral(name.expression) ? escapeLeadingUnderscores(name.expression.text) : undefined;
default:
Debug.assertNever(name);
}
return undefined;
}
export function entityNameToString(name: EntityNameOrEntityNameExpression): string {
@@ -906,11 +904,10 @@ namespace ts {
return;
default:
if (isFunctionLike(node)) {
const name = (<FunctionLikeDeclaration>node).name;
if (name && name.kind === SyntaxKind.ComputedPropertyName) {
if (node.name && node.name.kind === SyntaxKind.ComputedPropertyName) {
// Note that we will not include methods/accessors of a class because they would require
// first descending into the class. This is by design.
traverse((<ComputedPropertyName>name).expression);
traverse(node.name.expression);
return;
}
}
@@ -1221,15 +1218,15 @@ namespace ts {
}
export function getInvokedExpression(node: CallLikeExpression): Expression {
if (node.kind === SyntaxKind.TaggedTemplateExpression) {
return (<TaggedTemplateExpression>node).tag;
switch (node.kind) {
case SyntaxKind.TaggedTemplateExpression:
return node.tag;
case SyntaxKind.JsxOpeningElement:
case SyntaxKind.JsxSelfClosingElement:
return node.tagName;
default:
return node.expression;
}
else if (isJsxOpeningLikeElement(node)) {
return node.tagName;
}
// Will either be a CallExpression, NewExpression, or Decorator.
return (<CallExpression | Decorator>node).expression;
}
export function nodeCanBeDecorated(node: ClassDeclaration): true;
@@ -1628,7 +1625,7 @@ namespace ts {
if (node.kind === SyntaxKind.ImportEqualsDeclaration) {
const reference = (<ImportEqualsDeclaration>node).moduleReference;
if (reference.kind === SyntaxKind.ExternalModuleReference) {
return (<ExternalModuleReference>reference).expression;
return reference.expression;
}
}
if (node.kind === SyntaxKind.ExportDeclaration) {
@@ -1640,20 +1637,20 @@ namespace ts {
}
export function getNamespaceDeclarationNode(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): ImportEqualsDeclaration | NamespaceImport {
if (node.kind === SyntaxKind.ImportEqualsDeclaration) {
return <ImportEqualsDeclaration>node;
}
const importClause = (<ImportDeclaration>node).importClause;
if (importClause && importClause.namedBindings && importClause.namedBindings.kind === SyntaxKind.NamespaceImport) {
return <NamespaceImport>importClause.namedBindings;
switch (node.kind) {
case SyntaxKind.ImportDeclaration:
return node.importClause && tryCast(node.importClause.namedBindings, isNamespaceImport);
case SyntaxKind.ImportEqualsDeclaration:
return node;
case SyntaxKind.ExportDeclaration:
return undefined;
default:
return Debug.assertNever(node);
}
}
export function isDefaultImport(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration) {
return node.kind === SyntaxKind.ImportDeclaration
&& (<ImportDeclaration>node).importClause
&& !!(<ImportDeclaration>node).importClause.name;
return node.kind === SyntaxKind.ImportDeclaration && node.importClause && !!node.importClause.name;
}
export function hasQuestionToken(node: Node) {
@@ -2217,8 +2214,8 @@ namespace ts {
export function isDynamicName(name: DeclarationName): boolean {
return name.kind === SyntaxKind.ComputedPropertyName &&
!isStringOrNumericLiteral((<ComputedPropertyName>name).expression) &&
!isWellKnownSymbolSyntactically((<ComputedPropertyName>name).expression);
!isStringOrNumericLiteral(name.expression) &&
!isWellKnownSymbolSyntactically(name.expression);
}
/**
@@ -2258,7 +2255,7 @@ namespace ts {
if (node.kind === SyntaxKind.StringLiteral ||
node.kind === SyntaxKind.NumericLiteral) {
return (node as LiteralLikeNode).text;
return node.text;
}
}
@@ -2273,7 +2270,7 @@ namespace ts {
if (node.kind === SyntaxKind.StringLiteral ||
node.kind === SyntaxKind.NumericLiteral) {
return escapeLeadingUnderscores((node as LiteralLikeNode).text);
return escapeLeadingUnderscores(node.text);
}
}
@@ -4348,13 +4345,12 @@ namespace ts {
// Covers remaining cases
switch (hostNode.kind) {
case SyntaxKind.VariableStatement:
if ((hostNode as VariableStatement).declarationList &&
(hostNode as VariableStatement).declarationList.declarations[0]) {
return getDeclarationIdentifier((hostNode as VariableStatement).declarationList.declarations[0]);
if (hostNode.declarationList && hostNode.declarationList.declarations[0]) {
return getDeclarationIdentifier(hostNode.declarationList.declarations[0]);
}
return undefined;
case SyntaxKind.ExpressionStatement:
const expr = (hostNode as ExpressionStatement).expression;
const expr = hostNode.expression;
switch (expr.kind) {
case SyntaxKind.PropertyAccessExpression:
return (expr as PropertyAccessExpression).name;
@@ -4387,7 +4383,7 @@ namespace ts {
}
export function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined {
return declaration.name || nameForNamelessJSDocTypedef(declaration as JSDocTypedefTag);
return declaration.name || nameForNamelessJSDocTypedef(declaration);
}
export function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName | undefined {
@@ -4443,7 +4439,7 @@ namespace ts {
export function getJSDocParameterTags(param: ParameterDeclaration): ReadonlyArray<JSDocParameterTag> | undefined {
if (param.name && isIdentifier(param.name)) {
const name = param.name.escapedText;
return getJSDocTags(param.parent).filter((tag): tag is JSDocParameterTag => isJSDocParameterTag(tag) && isIdentifier(tag.name) && tag.name.escapedText === name) as JSDocParameterTag[];
return getJSDocTags(param.parent).filter((tag): tag is JSDocParameterTag => isJSDocParameterTag(tag) && isIdentifier(tag.name) && tag.name.escapedText === name);
}
// a binding pattern doesn't have a name, so it's not possible to match it a JSDoc parameter, which is identified by name
return undefined;
+7 -9
View File
@@ -1621,7 +1621,7 @@ Actual: ${stringify(fullActual)}`);
const diagnostics = ts.getPreEmitDiagnostics(this.languageService.getProgram());
for (const diagnostic of diagnostics) {
if (!ts.isString(diagnostic.messageText)) {
let chainedMessage = <ts.DiagnosticMessageChain>diagnostic.messageText;
let chainedMessage = diagnostic.messageText;
let indentation = " ";
while (chainedMessage) {
resultString += indentation + chainedMessage.messageText + Harness.IO.newLine();
@@ -3170,24 +3170,23 @@ Actual: ${stringify(fullActual)}`);
}
private findFile(indexOrName: string | number) {
let result: FourSlashFile;
if (typeof indexOrName === "number") {
const index = <number>indexOrName;
const index = indexOrName;
if (index >= this.testData.files.length) {
throw new Error(`File index (${index}) in openFile was out of range. There are only ${this.testData.files.length} files in this test.`);
}
else {
result = this.testData.files[index];
return this.testData.files[index];
}
}
else if (ts.isString(indexOrName)) {
let name = <string>indexOrName;
let name = indexOrName;
// names are stored in the compiler with this relative path, this allows people to use goTo.file on just the fileName
name = name.indexOf("/") === -1 ? (this.basePath + "/" + name) : name;
const availableNames: string[] = [];
result = ts.forEach(this.testData.files, file => {
const result = ts.forEach(this.testData.files, file => {
const fn = file.fileName;
if (fn) {
if (fn === name) {
@@ -3200,12 +3199,11 @@ Actual: ${stringify(fullActual)}`);
if (!result) {
throw new Error(`No test file named "${name}" exists. Available file names are: ${availableNames.join(", ")}`);
}
return result;
}
else {
throw new Error("Unknown argument type");
return ts.Debug.assertNever(indexOrName);
}
return result;
}
private getLineColStringAtPosition(position: number) {
+3 -4
View File
@@ -57,7 +57,7 @@ var assert: typeof _chai.assert = _chai.assert;
}
declare var __dirname: string; // Node-specific
var global: NodeJS.Global = <any>Function("return this").call(undefined);
var global: NodeJS.Global = Function("return this").call(undefined);
declare var window: {};
declare var XMLHttpRequest: {
@@ -767,10 +767,9 @@ namespace Harness {
return ts.matchFiles(path, extension, exclude, include, useCaseSensitiveFileNames(), getCurrentDirectory(), depth, path => {
const entry = fs.traversePath(path);
if (entry && entry.isDirectory()) {
const directory = <Utils.VirtualDirectory>entry;
return {
files: ts.map(directory.getFiles(), f => f.name),
directories: ts.map(directory.getDirectories(), d => d.name)
files: ts.map(entry.getFiles(), f => f.name),
directories: ts.map(entry.getDirectories(), d => d.name)
};
}
return { files: [], directories: [] };
+4 -1
View File
@@ -143,7 +143,7 @@ namespace Harness.LanguageService {
public getScriptInfo(fileName: string): ScriptInfo {
const fileEntry = this.virtualFileSystem.traversePath(fileName);
return fileEntry && fileEntry.isFile() ? (<Utils.VirtualFile>fileEntry).content : undefined;
return fileEntry && fileEntry.isFile() ? fileEntry.content : undefined;
}
public addScript(fileName: string, content: string, isRootFile: boolean): void {
@@ -522,6 +522,9 @@ namespace Harness.LanguageService {
getApplicableRefactors(): ts.ApplicableRefactorInfo[] {
throw new Error("Not supported on the shim.");
}
organizeImports(_scope: ts.OrganizeImportsScope, _formatOptions: ts.FormatCodeSettings): ReadonlyArray<ts.FileTextChanges> {
throw new Error("Not supported on the shim.");
}
getEmitOutput(fileName: string): ts.EmitOutput {
return unwrapJSONCallResult(this.shim.getEmitOutput(fileName));
}
+1
View File
@@ -117,6 +117,7 @@
"./unittests/tsserverProjectSystem.ts",
"./unittests/tscWatchMode.ts",
"./unittests/matchFiles.ts",
"./unittests/organizeImports.ts",
"./unittests/initializeTSConfig.ts",
"./unittests/compileOnSave.ts",
"./unittests/typingsInstaller.ts",
+384
View File
@@ -0,0 +1,384 @@
/// <reference path="..\..\..\src\harness\harness.ts" />
/// <reference path="..\..\..\src\harness\virtualFileSystem.ts" />
namespace ts {
describe("Organize imports", () => {
describe("Sort imports", () => {
it("Sort - non-relative vs non-relative", () => {
assertSortsBefore(
`import y from "lib1";`,
`import x from "lib2";`);
});
it("Sort - relative vs relative", () => {
assertSortsBefore(
`import y from "./lib1";`,
`import x from "./lib2";`);
});
it("Sort - relative vs non-relative", () => {
assertSortsBefore(
`import y from "lib";`,
`import x from "./lib";`);
});
function assertSortsBefore(importString1: string, importString2: string) {
const [{moduleSpecifier: moduleSpecifier1}, {moduleSpecifier: moduleSpecifier2}] = parseImports(importString1, importString2);
assert.equal(OrganizeImports.compareModuleSpecifiers(moduleSpecifier1, moduleSpecifier2), Comparison.LessThan);
assert.equal(OrganizeImports.compareModuleSpecifiers(moduleSpecifier2, moduleSpecifier1), Comparison.GreaterThan);
}
});
describe("Coalesce imports", () => {
it("No imports", () => {
assert.isEmpty(OrganizeImports.coalesceImports([]));
});
it("Sort specifiers", () => {
const sortedImports = parseImports(`import { default as m, a as n, b, y, z as o } from "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = parseImports(`import { a as n, b, default as m, y, z as o } from "lib";`);
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});
it("Combine side-effect-only imports", () => {
const sortedImports = parseImports(
`import "lib";`,
`import "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = parseImports(`import "lib";`);
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});
it("Combine namespace imports", () => {
const sortedImports = parseImports(
`import * as x from "lib";`,
`import * as y from "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = sortedImports;
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});
it("Combine default imports", () => {
const sortedImports = parseImports(
`import x from "lib";`,
`import y from "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = parseImports(`import { default as x, default as y } from "lib";`);
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});
it("Combine property imports", () => {
const sortedImports = parseImports(
`import { x } from "lib";`,
`import { y as z } from "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = parseImports(`import { x, y as z } from "lib";`);
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});
it("Combine side-effect-only import with namespace import", () => {
const sortedImports = parseImports(
`import "lib";`,
`import * as x from "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = sortedImports;
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});
it("Combine side-effect-only import with default import", () => {
const sortedImports = parseImports(
`import "lib";`,
`import x from "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = sortedImports;
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});
it("Combine side-effect-only import with property import", () => {
const sortedImports = parseImports(
`import "lib";`,
`import { x } from "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = sortedImports;
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});
it("Combine namespace import with default import", () => {
const sortedImports = parseImports(
`import * as x from "lib";`,
`import y from "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = parseImports(
`import y, * as x from "lib";`);
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});
it("Combine namespace import with property import", () => {
const sortedImports = parseImports(
`import * as x from "lib";`,
`import { y } from "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = sortedImports;
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});
it("Combine default import with property import", () => {
const sortedImports = parseImports(
`import x from "lib";`,
`import { y } from "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = parseImports(
`import x, { y } from "lib";`);
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});
it("Combine many imports", () => {
const sortedImports = parseImports(
`import "lib";`,
`import * as y from "lib";`,
`import w from "lib";`,
`import { b } from "lib";`,
`import "lib";`,
`import * as x from "lib";`,
`import z from "lib";`,
`import { a } from "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = parseImports(
`import "lib";`,
`import * as x from "lib";`,
`import * as y from "lib";`,
`import { a, b, default as w, default as z } from "lib";`);
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});
// This is descriptive, rather than normative
it("Combine two namespace imports with one default import", () => {
const sortedImports = parseImports(
`import * as x from "lib";`,
`import * as y from "lib";`,
`import z from "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = sortedImports;
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});
});
describe("Baselines", () => {
const libFile = {
path: "/lib.ts",
content: `
export function F1();
export default function F2();
`,
};
// Don't bother to actually emit a baseline for this.
it("NoImports", () => {
const testFile = {
path: "/a.ts",
content: "function F() { }",
};
const languageService = makeLanguageService(testFile);
const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, testFormatOptions);
assert.isEmpty(changes);
});
testOrganizeImports("Simple",
{
path: "/test.ts",
content: `
import { F1, F2 } from "lib";
import * as NS from "lib";
import D from "lib";
NS.F1();
D();
F1();
F2();
`,
},
libFile);
testOrganizeImports("MoveToTop",
{
path: "/test.ts",
content: `
import { F1, F2 } from "lib";
F1();
F2();
import * as NS from "lib";
NS.F1();
import D from "lib";
D();
`,
},
libFile);
// tslint:disable no-invalid-template-strings
testOrganizeImports("MoveToTop_Invalid",
{
path: "/test.ts",
content: `
import { F1, F2 } from "lib";
F1();
F2();
import * as NS from "lib";
NS.F1();
import b from ${"`${'lib'}`"};
import a from ${"`${'lib'}`"};
import D from "lib";
D();
`,
},
libFile);
// tslint:enable no-invalid-template-strings
testOrganizeImports("CoalesceMultipleModules",
{
path: "/test.ts",
content: `
import { d } from "lib1";
import { b } from "lib1";
import { c } from "lib2";
import { a } from "lib2";
`,
},
{ path: "/lib1.ts", content: "" },
{ path: "/lib2.ts", content: "" });
testOrganizeImports("CoalesceTrivia",
{
path: "/test.ts",
content: `
/*A*/import /*B*/ { /*C*/ F2 /*D*/ } /*E*/ from /*F*/ "lib" /*G*/;/*H*/ //I
/*J*/import /*K*/ { /*L*/ F1 /*M*/ } /*N*/ from /*O*/ "lib" /*P*/;/*Q*/ //R
F1();
F2();
`,
},
libFile);
testOrganizeImports("SortTrivia",
{
path: "/test.ts",
content: `
/*A*/import /*B*/ "lib2" /*C*/;/*D*/ //E
/*F*/import /*G*/ "lib1" /*H*/;/*I*/ //J
`,
},
{ path: "/lib1.ts", content: "" },
{ path: "/lib2.ts", content: "" });
function testOrganizeImports(testName: string, testFile: TestFSWithWatch.FileOrFolder, ...otherFiles: TestFSWithWatch.FileOrFolder[]) {
it(testName, () => runBaseline(`organizeImports/${testName}.ts`, testFile, ...otherFiles));
}
function runBaseline(baselinePath: string, testFile: TestFSWithWatch.FileOrFolder, ...otherFiles: TestFSWithWatch.FileOrFolder[]) {
const { path: testPath, content: testContent } = testFile;
const languageService = makeLanguageService(testFile, ...otherFiles);
const changes = languageService.organizeImports({ type: "file", fileName: testPath }, testFormatOptions);
assert.equal(changes.length, 1);
assert.equal(changes[0].fileName, testPath);
Harness.Baseline.runBaseline(baselinePath, () => {
const newText = textChanges.applyChanges(testContent, changes[0].textChanges);
return [
"// ==ORIGINAL==",
testContent,
"// ==ORGANIZED==",
newText,
].join(newLineCharacter);
});
}
function makeLanguageService(...files: TestFSWithWatch.FileOrFolder[]) {
const host = projectSystem.createServerHost(files);
const projectService = projectSystem.createProjectService(host, { useSingleInferredProject: true });
files.forEach(f => projectService.openClientFile(f.path));
return projectService.inferredProjects[0].getLanguageService();
}
});
function parseImports(...importStrings: string[]): ReadonlyArray<ImportDeclaration> {
const sourceFile = createSourceFile("a.ts", importStrings.join("\n"), ScriptTarget.ES2015, /*setParentNodes*/ true, ScriptKind.TS);
const imports = filter(sourceFile.statements, isImportDeclaration);
assert.equal(imports.length, importStrings.length);
return imports;
}
function assertEqual(node1?: Node, node2?: Node) {
if (node1 === undefined) {
assert.isUndefined(node2);
return;
}
else if (node2 === undefined) {
assert.isUndefined(node1); // Guaranteed to fail
return;
}
assert.equal(node1.kind, node2.kind);
switch (node1.kind) {
case SyntaxKind.ImportDeclaration:
const decl1 = node1 as ImportDeclaration;
const decl2 = node2 as ImportDeclaration;
assertEqual(decl1.importClause, decl2.importClause);
assertEqual(decl1.moduleSpecifier, decl2.moduleSpecifier);
break;
case SyntaxKind.ImportClause:
const clause1 = node1 as ImportClause;
const clause2 = node2 as ImportClause;
assertEqual(clause1.name, clause2.name);
assertEqual(clause1.namedBindings, clause2.namedBindings);
break;
case SyntaxKind.NamespaceImport:
const nsi1 = node1 as NamespaceImport;
const nsi2 = node2 as NamespaceImport;
assertEqual(nsi1.name, nsi2.name);
break;
case SyntaxKind.NamedImports:
const ni1 = node1 as NamedImports;
const ni2 = node2 as NamedImports;
assertListEqual(ni1.elements, ni2.elements);
break;
case SyntaxKind.ImportSpecifier:
const is1 = node1 as ImportSpecifier;
const is2 = node2 as ImportSpecifier;
assertEqual(is1.name, is2.name);
assertEqual(is1.propertyName, is2.propertyName);
break;
case SyntaxKind.Identifier:
const id1 = node1 as Identifier;
const id2 = node2 as Identifier;
assert.equal(id1.text, id2.text);
break;
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
const sl1 = node1 as LiteralLikeNode;
const sl2 = node2 as LiteralLikeNode;
assert.equal(sl1.text, sl2.text);
break;
default:
assert.equal(node1.getText(), node2.getText());
break;
}
}
function assertListEqual(list1: ReadonlyArray<Node>, list2: ReadonlyArray<Node>) {
if (list1 === undefined || list2 === undefined) {
assert.isUndefined(list1);
assert.isUndefined(list2);
return;
}
assert.equal(list1.length, list2.length);
for (let i = 0; i < list1.length; i++) {
assertEqual(list1[i], list2[i]);
}
}
});
}
@@ -165,7 +165,7 @@ namespace ts {
export function updateProgram(oldProgram: ProgramWithSourceTexts, rootNames: ReadonlyArray<string>, options: CompilerOptions, updater: (files: NamedSourceText[]) => void, newTexts?: NamedSourceText[]) {
if (!newTexts) {
newTexts = (<ProgramWithSourceTexts>oldProgram).sourceTexts.slice(0);
newTexts = oldProgram.sourceTexts.slice(0);
}
updater(newTexts);
const host = createTestCompilerHost(newTexts, options.target, oldProgram);
+2
View File
@@ -262,6 +262,8 @@ namespace ts.server {
CommandNames.GetApplicableRefactors,
CommandNames.GetEditsForRefactor,
CommandNames.GetEditsForRefactorFull,
CommandNames.OrganizeImports,
CommandNames.OrganizeImportsFull,
];
it("should not throw when commands are executed with invalid arguments", () => {
+2 -2
View File
@@ -57,7 +57,7 @@ namespace ts {
Harness.Baseline.runBaseline(`textChanges/${caption}.js`, () => {
const sourceFile = createSourceFile("source.ts", text, ScriptTarget.ES2015, /*setParentNodes*/ true);
const rulesProvider = getRuleProvider(placeOpenBraceOnNewLineForFunctions);
const changeTracker = new textChanges.ChangeTracker(printerOptions.newLine, rulesProvider, validateNodes ? verifyPositions : undefined);
const changeTracker = new textChanges.ChangeTracker(newLineCharacter, rulesProvider, validateNodes ? verifyPositions : undefined);
testBlock(sourceFile, changeTracker);
const changes = changeTracker.getChanges();
assert.equal(changes.length, 1);
@@ -91,7 +91,7 @@ namespace M
}
}`;
runSingleFileTest("extractMethodLike", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => {
const statements = (<Block>(<FunctionDeclaration>findChild("foo", sourceFile)).body).statements.slice(1);
const statements = (<FunctionDeclaration>findChild("foo", sourceFile)).body.statements.slice(1);
const newFunction = createFunctionDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
@@ -2560,7 +2560,7 @@ namespace ts.projectSystem {
}
assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent);
assert.equal(e.data.project.getProjectName(), config.path, "project name");
lastEvent = <server.ProjectLanguageServiceStateEvent>e;
lastEvent = e;
}
});
session.executeCommand(<protocol.OpenRequest>{
+6 -7
View File
@@ -42,12 +42,12 @@ namespace Utils {
getDirectory(name: string): VirtualDirectory {
const entry = this.getFileSystemEntry(name);
return entry.isDirectory() ? <VirtualDirectory>entry : undefined;
return entry.isDirectory() ? entry : undefined;
}
getFile(name: string): VirtualFile {
const entry = this.getFileSystemEntry(name);
return entry.isFile() ? <VirtualFile>entry : undefined;
return entry.isFile() ? entry : undefined;
}
}
@@ -66,7 +66,7 @@ namespace Utils {
return directory;
}
else if (entry.isDirectory()) {
return <VirtualDirectory>entry;
return entry;
}
else {
return undefined;
@@ -149,7 +149,7 @@ namespace Utils {
return undefined;
}
else if (entry.isDirectory()) {
directory = <VirtualDirectory>entry;
directory = entry;
}
else {
return entry;
@@ -167,10 +167,9 @@ namespace Utils {
getAccessibleFileSystemEntries(path: string) {
const entry = this.traversePath(path);
if (entry && entry.isDirectory()) {
const directory = <VirtualDirectory>entry;
return {
files: ts.map(directory.getFiles(), f => f.name),
directories: ts.map(directory.getDirectories(), d => d.name)
files: ts.map(entry.getFiles(), f => f.name),
directories: ts.map(entry.getDirectories(), d => d.name)
};
}
return { files: [], directories: [] };
+409 -393
View File
File diff suppressed because it is too large Load Diff
+53 -45
View File
@@ -128,7 +128,9 @@ interface SyncEventInit extends ExtendableEventInit {
lastChance?: boolean;
}
type EventListener = (evt: Event) => void | { handleEvent(evt: Event): void; };
interface EventListener {
(evt: Event): void;
}
interface AudioBuffer {
readonly duration: number;
@@ -390,9 +392,9 @@ declare var Event: {
};
interface EventTarget {
addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
dispatchEvent(evt: Event): boolean;
removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
declare var EventTarget: {
@@ -430,9 +432,9 @@ interface FileReader extends EventTarget, MSBaseReader {
readAsDataURL(blob: Blob): void;
readAsText(blob: Blob, encoding?: string): void;
addEventListener<K extends keyof MSBaseReaderEventMap>(type: K, listener: (this: FileReader, ev: MSBaseReaderEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof MSBaseReaderEventMap>(type: K, listener: (this: FileReader, ev: MSBaseReaderEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
declare var FileReader: {
@@ -515,9 +517,9 @@ interface IDBDatabase extends EventTarget {
addEventListener(type: "versionchange", listener: (this: IDBDatabase, ev: IDBVersionChangeEvent) => any, options?: boolean | AddEventListenerOptions): void;
removeEventListener(type: "versionchange", listener: (this: IDBDatabase, ev: IDBVersionChangeEvent) => any, options?: boolean | EventListenerOptions): void;
addEventListener<K extends keyof IDBDatabaseEventMap>(type: K, listener: (this: IDBDatabase, ev: IDBDatabaseEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof IDBDatabaseEventMap>(type: K, listener: (this: IDBDatabase, ev: IDBDatabaseEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
declare var IDBDatabase: {
@@ -602,9 +604,9 @@ interface IDBOpenDBRequest extends IDBRequest {
onblocked: (this: IDBOpenDBRequest, ev: Event) => any;
onupgradeneeded: (this: IDBOpenDBRequest, ev: IDBVersionChangeEvent) => any;
addEventListener<K extends keyof IDBOpenDBRequestEventMap>(type: K, listener: (this: IDBOpenDBRequest, ev: IDBOpenDBRequestEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof IDBOpenDBRequestEventMap>(type: K, listener: (this: IDBOpenDBRequest, ev: IDBOpenDBRequestEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
declare var IDBOpenDBRequest: {
@@ -626,9 +628,9 @@ interface IDBRequest extends EventTarget {
source: IDBObjectStore | IDBIndex | IDBCursor;
readonly transaction: IDBTransaction;
addEventListener<K extends keyof IDBRequestEventMap>(type: K, listener: (this: IDBRequest, ev: IDBRequestEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof IDBRequestEventMap>(type: K, listener: (this: IDBRequest, ev: IDBRequestEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
declare var IDBRequest: {
@@ -655,9 +657,9 @@ interface IDBTransaction extends EventTarget {
readonly READ_WRITE: string;
readonly VERSION_CHANGE: string;
addEventListener<K extends keyof IDBTransactionEventMap>(type: K, listener: (this: IDBTransaction, ev: IDBTransactionEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof IDBTransactionEventMap>(type: K, listener: (this: IDBTransaction, ev: IDBTransactionEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
declare var IDBTransaction: {
@@ -723,9 +725,9 @@ interface MessagePort extends EventTarget {
postMessage(message?: any, transfer?: any[]): void;
start(): void;
addEventListener<K extends keyof MessagePortEventMap>(type: K, listener: (this: MessagePort, ev: MessagePortEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof MessagePortEventMap>(type: K, listener: (this: MessagePort, ev: MessagePortEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
declare var MessagePort: {
@@ -754,9 +756,9 @@ interface Notification extends EventTarget {
readonly title: string;
close(): void;
addEventListener<K extends keyof NotificationEventMap>(type: K, listener: (this: Notification, ev: NotificationEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof NotificationEventMap>(type: K, listener: (this: Notification, ev: NotificationEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
declare var Notification: {
@@ -985,9 +987,9 @@ interface ServiceWorker extends EventTarget, AbstractWorker {
readonly state: ServiceWorkerState;
postMessage(message: any, transfer?: any[]): void;
addEventListener<K extends keyof ServiceWorkerEventMap>(type: K, listener: (this: ServiceWorker, ev: ServiceWorkerEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof ServiceWorkerEventMap>(type: K, listener: (this: ServiceWorker, ev: ServiceWorkerEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
declare var ServiceWorker: {
@@ -1012,9 +1014,9 @@ interface ServiceWorkerRegistration extends EventTarget {
unregister(): Promise<boolean>;
update(): Promise<void>;
addEventListener<K extends keyof ServiceWorkerRegistrationEventMap>(type: K, listener: (this: ServiceWorkerRegistration, ev: ServiceWorkerRegistrationEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof ServiceWorkerRegistrationEventMap>(type: K, listener: (this: ServiceWorkerRegistration, ev: ServiceWorkerRegistrationEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
declare var ServiceWorkerRegistration: {
@@ -1080,9 +1082,9 @@ interface WebSocket extends EventTarget {
readonly CONNECTING: number;
readonly OPEN: number;
addEventListener<K extends keyof WebSocketEventMap>(type: K, listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof WebSocketEventMap>(type: K, listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
declare var WebSocket: {
@@ -1103,9 +1105,9 @@ interface Worker extends EventTarget, AbstractWorker {
postMessage(message: any, transfer?: any[]): void;
terminate(): void;
addEventListener<K extends keyof WorkerEventMap>(type: K, listener: (this: Worker, ev: WorkerEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof WorkerEventMap>(type: K, listener: (this: Worker, ev: WorkerEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
declare var Worker: {
@@ -1146,9 +1148,9 @@ interface XMLHttpRequest extends EventTarget, XMLHttpRequestEventTarget {
readonly OPENED: number;
readonly UNSENT: number;
addEventListener<K extends keyof XMLHttpRequestEventMap>(type: K, listener: (this: XMLHttpRequest, ev: XMLHttpRequestEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof XMLHttpRequestEventMap>(type: K, listener: (this: XMLHttpRequest, ev: XMLHttpRequestEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
declare var XMLHttpRequest: {
@@ -1163,9 +1165,9 @@ declare var XMLHttpRequest: {
interface XMLHttpRequestUpload extends EventTarget, XMLHttpRequestEventTarget {
addEventListener<K extends keyof XMLHttpRequestEventTargetEventMap>(type: K, listener: (this: XMLHttpRequestUpload, ev: XMLHttpRequestEventTargetEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof XMLHttpRequestEventTargetEventMap>(type: K, listener: (this: XMLHttpRequestUpload, ev: XMLHttpRequestEventTargetEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
declare var XMLHttpRequestUpload: {
@@ -1180,9 +1182,9 @@ interface AbstractWorkerEventMap {
interface AbstractWorker {
onerror: (this: AbstractWorker, ev: ErrorEvent) => any;
addEventListener<K extends keyof AbstractWorkerEventMap>(type: K, listener: (this: AbstractWorker, ev: AbstractWorkerEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof AbstractWorkerEventMap>(type: K, listener: (this: AbstractWorker, ev: AbstractWorkerEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
interface Body {
@@ -1220,9 +1222,9 @@ interface MSBaseReader {
readonly EMPTY: number;
readonly LOADING: number;
addEventListener<K extends keyof MSBaseReaderEventMap>(type: K, listener: (this: MSBaseReader, ev: MSBaseReaderEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof MSBaseReaderEventMap>(type: K, listener: (this: MSBaseReader, ev: MSBaseReaderEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
interface NavigatorBeacon {
@@ -1277,9 +1279,9 @@ interface XMLHttpRequestEventTarget {
onprogress: (this: XMLHttpRequest, ev: ProgressEvent) => any;
ontimeout: (this: XMLHttpRequest, ev: ProgressEvent) => any;
addEventListener<K extends keyof XMLHttpRequestEventTargetEventMap>(type: K, listener: (this: XMLHttpRequestEventTarget, ev: XMLHttpRequestEventTargetEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof XMLHttpRequestEventTargetEventMap>(type: K, listener: (this: XMLHttpRequestEventTarget, ev: XMLHttpRequestEventTargetEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
interface Client {
@@ -1315,9 +1317,9 @@ interface DedicatedWorkerGlobalScope extends WorkerGlobalScope {
close(): void;
postMessage(message: any, transfer?: any[]): void;
addEventListener<K extends keyof DedicatedWorkerGlobalScopeEventMap>(type: K, listener: (this: DedicatedWorkerGlobalScope, ev: DedicatedWorkerGlobalScopeEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof DedicatedWorkerGlobalScopeEventMap>(type: K, listener: (this: DedicatedWorkerGlobalScope, ev: DedicatedWorkerGlobalScopeEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
declare var DedicatedWorkerGlobalScope: {
@@ -1428,9 +1430,9 @@ interface ServiceWorkerGlobalScope extends WorkerGlobalScope {
readonly registration: ServiceWorkerRegistration;
skipWaiting(): Promise<void>;
addEventListener<K extends keyof ServiceWorkerGlobalScopeEventMap>(type: K, listener: (this: ServiceWorkerGlobalScope, ev: ServiceWorkerGlobalScopeEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof ServiceWorkerGlobalScopeEventMap>(type: K, listener: (this: ServiceWorkerGlobalScope, ev: ServiceWorkerGlobalScopeEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
declare var ServiceWorkerGlobalScope: {
@@ -1475,9 +1477,9 @@ interface WorkerGlobalScope extends EventTarget, WorkerUtils, WindowConsole, Glo
createImageBitmap(image: ImageBitmap | ImageData | Blob, options?: ImageBitmapOptions): Promise<ImageBitmap>;
createImageBitmap(image: ImageBitmap | ImageData | Blob, sx: number, sy: number, sw: number, sh: number, options?: ImageBitmapOptions): Promise<ImageBitmap>;
addEventListener<K extends keyof WorkerGlobalScopeEventMap>(type: K, listener: (this: WorkerGlobalScope, ev: WorkerGlobalScopeEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof WorkerGlobalScopeEventMap>(type: K, listener: (this: WorkerGlobalScope, ev: WorkerGlobalScopeEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
declare var WorkerGlobalScope: {
@@ -1535,9 +1537,9 @@ interface BroadcastChannel extends EventTarget {
close(): void;
postMessage(message: any): void;
addEventListener<K extends keyof BroadcastChannelEventMap>(type: K, listener: (this: BroadcastChannel, ev: BroadcastChannelEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof BroadcastChannelEventMap>(type: K, listener: (this: BroadcastChannel, ev: BroadcastChannelEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
declare var BroadcastChannel: {
@@ -1617,6 +1619,10 @@ interface FilePropertyBag extends BlobPropertyBag {
lastModified?: number;
}
interface EventListenerObject {
handleEvent(evt: Event): void;
}
interface ProgressEventInit extends EventInit {
lengthComputable?: boolean;
loaded?: number;
@@ -1843,6 +1849,8 @@ interface EventSourceInit {
readonly withCredentials: boolean;
}
declare type EventListenerOrEventListenerObject = EventListener | EventListenerObject;
interface DecodeErrorCallback {
(error: DOMException): void;
}
@@ -1899,9 +1907,9 @@ declare var console: Console;
declare function fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;
declare function dispatchEvent(evt: Event): boolean;
declare function addEventListener<K extends keyof DedicatedWorkerGlobalScopeEventMap>(type: K, listener: (this: DedicatedWorkerGlobalScope, ev: DedicatedWorkerGlobalScopeEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
declare function addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void;
declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
declare function removeEventListener<K extends keyof DedicatedWorkerGlobalScopeEventMap>(type: K, listener: (this: DedicatedWorkerGlobalScope, ev: DedicatedWorkerGlobalScopeEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
declare function removeEventListener(type: string, listener: EventListener, options?: boolean | EventListenerOptions): void;
declare function removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
type AlgorithmIdentifier = string | Algorithm;
type BodyInit = Blob | BufferSource | FormData | string;
type IDBKeyPath = string;
@@ -3021,6 +3021,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations_2567" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Enum declarations can only merge with namespace or other enum declarations.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[È possibile unire dichiarazioni di enumerazione solo con lo spazio dei nomi o altre dichiarazioni di enumerazione.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Enum_declarations_must_all_be_const_or_non_const_2473" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Enum declarations must all be const or non-const.]]></Val>
@@ -3011,6 +3011,15 @@
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations_2567" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Enum declarations can only merge with namespace or other enum declarations.]]></Val>
<Tgt Cat="Text" Stat="Loc" Orig="New">
<Val><![CDATA[Deklaracje wyliczeń można scalać tylko z przestrzeniami nazw lub innymi deklaracjami wyliczeń.]]></Val>
</Tgt>
</Str>
<Disp Icon="Str" />
</Item>
<Item ItemId=";Enum_declarations_must_all_be_const_or_non_const_2473" ItemType="0" PsrId="306" Leaf="true">
<Str Cat="Text">
<Val><![CDATA[Enum declarations must all be const or non-const.]]></Val>
+4
View File
@@ -629,6 +629,10 @@ namespace ts.server {
};
}
organizeImports(_scope: OrganizeImportsScope, _formatOptions: FormatCodeSettings): ReadonlyArray<FileTextChanges> {
return notImplemented();
}
private convertCodeEditsToTextChanges(edits: protocol.FileCodeEdits[]): FileTextChanges[] {
return edits.map(edit => {
const fileName = edit.fileName;
+1 -1
View File
@@ -2026,7 +2026,7 @@ namespace ts.server {
}
else {
configFileErrors = project.getAllProjectErrors();
this.sendConfigFileDiagEvent(project as ConfiguredProject, fileName);
this.sendConfigFileDiagEvent(project, fileName);
}
}
else {
+25
View File
@@ -113,6 +113,10 @@ namespace ts.server.protocol {
/* @internal */
GetEditsForRefactorFull = "getEditsForRefactor-full",
OrganizeImports = "organizeImports",
/* @internal */
OrganizeImportsFull = "organizeImports-full",
// NOTE: If updating this, be sure to also update `allCommandNames` in `harness/unittests/session.ts`.
}
@@ -547,6 +551,27 @@ namespace ts.server.protocol {
renameFilename?: string;
}
/**
* Organize imports by:
* 1) Removing unused imports
* 2) Coalescing imports from the same module
* 3) Sorting imports
*/
export interface OrganizeImportsRequest extends Request {
command: CommandTypes.OrganizeImports;
arguments: OrganizeImportsRequestArgs;
}
export type OrganizeImportsScope = GetCombinedCodeFixScope;
export interface OrganizeImportsRequestArgs {
scope: OrganizeImportsScope;
}
export interface OrganizeImportsResponse extends Response {
edits: ReadonlyArray<FileCodeEdits>;
}
/**
* Request for the available codefixes at a specific position.
*/
+4 -4
View File
@@ -680,7 +680,7 @@ namespace ts.server {
// Skipped all children
const { leaf } = this.lineNumberToInfo(this.lineCount(), 0);
return { oneBasedLine: this.lineCount(), zeroBasedColumn: leaf.charCount(), lineText: undefined };
return { oneBasedLine: this.lineCount(), zeroBasedColumn: leaf ? leaf.charCount() : 0, lineText: undefined };
}
/**
@@ -765,13 +765,13 @@ namespace ts.server {
for (let i = 0; i < splitNodeCount; i++) {
splitNodes[i] = new LineNode();
}
let splitNode = <LineNode>splitNodes[0];
let splitNode = splitNodes[0];
while (nodeIndex < nodeCount) {
splitNode.add(nodes[nodeIndex]);
nodeIndex++;
if (splitNode.children.length === lineCollectionCapacity) {
splitNodeIndex++;
splitNode = <LineNode>splitNodes[splitNodeIndex];
splitNode = splitNodes[splitNodeIndex];
}
}
for (let i = splitNodes.length - 1; i >= 0; i--) {
@@ -785,7 +785,7 @@ namespace ts.server {
}
this.updateCounts();
for (let i = 0; i < splitNodeCount; i++) {
(<LineNode>splitNodes[i]).updateCounts();
splitNodes[i].updateCounts();
}
return splitNodes;
}
+19
View File
@@ -1597,6 +1597,19 @@ namespace ts.server {
}
}
private organizeImports({ scope }: protocol.OrganizeImportsRequestArgs, simplifiedResult: boolean): ReadonlyArray<protocol.FileCodeEdits> | ReadonlyArray<FileTextChanges> {
Debug.assert(scope.type === "file");
const { file, project } = this.getFileAndProject(scope.args);
const formatOptions = this.projectService.getFormatCodeOptions(file);
const changes = project.getLanguageService().organizeImports({ type: "file", fileName: file }, formatOptions);
if (simplifiedResult) {
return this.mapTextChangesToCodeEdits(project, changes);
}
else {
return changes;
}
}
private getCodeFixes(args: protocol.CodeFixRequestArgs, simplifiedResult: boolean): ReadonlyArray<protocol.CodeAction> | ReadonlyArray<CodeAction> {
if (args.errorCodes.length === 0) {
return undefined;
@@ -2041,6 +2054,12 @@ namespace ts.server {
},
[CommandNames.GetEditsForRefactorFull]: (request: protocol.GetEditsForRefactorRequest) => {
return this.requiredResponse(this.getEditsForRefactor(request.arguments, /*simplifiedResult*/ false));
},
[CommandNames.OrganizeImports]: (request: protocol.OrganizeImportsRequest) => {
return this.requiredResponse(this.organizeImports(request.arguments, /*simplifiedResult*/ true));
},
[CommandNames.OrganizeImportsFull]: (request: protocol.OrganizeImportsRequest) => {
return this.requiredResponse(this.organizeImports(request.arguments, /*simplifiedResult*/ false));
}
});
@@ -1,4 +1,3 @@
/// <reference path="typingsInstaller.ts"/>
/// <reference types="node" />
namespace ts.server.typingsInstaller {
+12
View File
@@ -12,6 +12,18 @@
]
},
"files": [
"../../compiler/types.ts",
"../../compiler/performance.ts",
"../../compiler/core.ts",
"../../compiler/sys.ts",
"../../compiler/diagnosticInformationMap.generated.ts",
"../../compiler/utilities.ts",
"../../compiler/scanner.ts",
"../../compiler/parser.ts",
"../../compiler/commandLineParser.ts",
"../../compiler/moduleNameResolver.ts",
"../../services/semver.ts",
"../../services/jsTyping.ts",
"../types.ts",
"../shared.ts",
"typingsInstaller.ts",
@@ -1,10 +1,3 @@
/// <reference path="../../compiler/core.ts" />
/// <reference path="../../compiler/moduleNameResolver.ts" />
/// <reference path="../../services/jsTyping.ts"/>
/// <reference path="../../services/semver.ts"/>
/// <reference path="../types.ts"/>
/// <reference path="../shared.ts"/>
namespace ts.server.typingsInstaller {
interface NpmConfig {
devDependencies: MapLike<any>;
@@ -413,4 +406,4 @@ namespace ts.server.typingsInstaller {
}
const latestDistTag = "latest";
}
}
+3 -6
View File
@@ -390,7 +390,7 @@ namespace ts.BreakpointResolver {
// If this is a destructuring pattern, set breakpoint in binding pattern
if (isBindingPattern(variableDeclaration.name)) {
return spanInBindingPattern(<BindingPattern>variableDeclaration.name);
return spanInBindingPattern(variableDeclaration.name);
}
// Breakpoint is possible in variableDeclaration only if there is initialization
@@ -420,7 +420,7 @@ namespace ts.BreakpointResolver {
function spanInParameterDeclaration(parameter: ParameterDeclaration): TextSpan {
if (isBindingPattern(parameter.name)) {
// Set breakpoint in binding pattern
return spanInBindingPattern(<BindingPattern>parameter.name);
return spanInBindingPattern(parameter.name);
}
else if (canHaveSpanInParameterDeclaration(parameter)) {
return textSpan(parameter);
@@ -540,10 +540,7 @@ namespace ts.BreakpointResolver {
function spanInArrayLiteralOrObjectLiteralDestructuringPattern(node: DestructuringPattern): TextSpan {
Debug.assert(node.kind !== SyntaxKind.ArrayBindingPattern && node.kind !== SyntaxKind.ObjectBindingPattern);
const elements: NodeArray<Expression | ObjectLiteralElement> =
node.kind === SyntaxKind.ArrayLiteralExpression ?
(<ArrayLiteralExpression>node).elements :
(<ObjectLiteralExpression>node).properties;
const elements: NodeArray<Expression | ObjectLiteralElement> = node.kind === SyntaxKind.ArrayLiteralExpression ? node.elements : (node as ObjectLiteralExpression).properties;
const firstBindingElement = forEach(elements,
element => element.kind !== SyntaxKind.OmittedExpression ? element : undefined);
@@ -195,7 +195,7 @@ namespace ts.codefix {
}
function tryDeleteNamedImportBinding(changes: textChanges.ChangeTracker, sourceFile: SourceFile, namedBindings: NamedImportBindings): void {
if ((<ImportClause>namedBindings.parent).name) {
if (namedBindings.parent.name) {
// Delete named imports while preserving the default import
// import d|, * as ns| from './file'
// import d|, { a }| from './file'
@@ -229,7 +229,7 @@ namespace ts.codefix {
}
case SyntaxKind.ForOfStatement:
const forOfStatement = <ForOfStatement>varDecl.parent.parent;
const forOfStatement = varDecl.parent.parent;
Debug.assert(forOfStatement.initializer.kind === SyntaxKind.VariableDeclarationList);
const forOfInitializer = <VariableDeclarationList>forOfStatement.initializer;
changes.replaceNode(sourceFile, forOfInitializer.declarations[0], createObjectLiteral());
@@ -240,7 +240,7 @@ namespace ts.codefix {
break;
default:
const variableStatement = <VariableStatement>varDecl.parent.parent;
const variableStatement = varDecl.parent.parent;
if (variableStatement.declarationList.declarations.length === 1) {
changes.deleteNode(sourceFile, variableStatement);
}
+1 -1
View File
@@ -24,7 +24,7 @@ namespace ts.codefix {
return undefined;
}
const declaration = declarations[0] as Declaration;
const declaration = declarations[0];
// Clone name to remove leading trivia.
const name = getSynthesizedDeepClone(getNameOfDeclaration(declaration)) as PropertyName;
const visibilityModifier = createVisibilityModifier(getModifierFlags(declaration));
+2 -2
View File
@@ -140,7 +140,7 @@ namespace ts.codefix {
case SyntaxKind.Constructor:
return true;
case SyntaxKind.FunctionExpression:
return !!(declaration as FunctionExpression).name;
return !!declaration.name;
}
return false;
}
@@ -497,7 +497,7 @@ namespace ts.codefix {
}
function inferTypeFromSwitchStatementLabelContext(parent: CaseOrDefaultClause, checker: TypeChecker, usageContext: UsageContext): void {
addCandidateType(usageContext, checker.getTypeAtLocation((<SwitchStatement>parent.parent.parent).expression));
addCandidateType(usageContext, checker.getTypeAtLocation(parent.parent.parent.expression));
}
function inferTypeFromCallExpressionContext(parent: CallExpression | NewExpression, checker: TypeChecker, usageContext: UsageContext): void {
+35 -21
View File
@@ -657,8 +657,8 @@ namespace ts.Completions {
None,
}
function getRecommendedCompletion(currentToken: Node, checker: TypeChecker): Symbol | undefined {
const ty = getContextualType(currentToken, checker);
function getRecommendedCompletion(currentToken: Node, position: number, sourceFile: SourceFile, checker: TypeChecker): Symbol | undefined {
const ty = getContextualType(currentToken, position, sourceFile, checker);
const symbol = ty && ty.symbol;
// Don't include make a recommended completion for an abstract class
return symbol && (symbol.flags & SymbolFlags.Enum || symbol.flags & SymbolFlags.Class && !isAbstractConstructorSymbol(symbol))
@@ -666,23 +666,37 @@ namespace ts.Completions {
: undefined;
}
function getContextualType(currentToken: Node, checker: ts.TypeChecker): Type | undefined {
function getContextualType(currentToken: Node, position: number, sourceFile: SourceFile, checker: TypeChecker): Type | undefined {
const { parent } = currentToken;
switch (currentToken.kind) {
case ts.SyntaxKind.Identifier:
return getContextualTypeFromParent(currentToken as ts.Identifier, checker);
case ts.SyntaxKind.EqualsToken:
return ts.isVariableDeclaration(parent) ? checker.getContextualType(parent.initializer) :
ts.isBinaryExpression(parent) ? checker.getTypeAtLocation(parent.left) : undefined;
case ts.SyntaxKind.NewKeyword:
return checker.getContextualType(parent as ts.Expression);
case ts.SyntaxKind.CaseKeyword:
return getSwitchedType(cast(currentToken.parent, isCaseClause), checker);
case SyntaxKind.Identifier:
return getContextualTypeFromParent(currentToken as Identifier, checker);
case SyntaxKind.EqualsToken:
switch (parent.kind) {
case ts.SyntaxKind.VariableDeclaration:
return checker.getContextualType((parent as VariableDeclaration).initializer);
case ts.SyntaxKind.BinaryExpression:
return checker.getTypeAtLocation((parent as BinaryExpression).left);
case ts.SyntaxKind.JsxAttribute:
return checker.getContextualTypeForJsxAttribute(parent as JsxAttribute);
default:
return undefined;
}
case SyntaxKind.NewKeyword:
return checker.getContextualType(parent as Expression);
case SyntaxKind.CaseKeyword:
return getSwitchedType(cast(parent, isCaseClause), checker);
case SyntaxKind.OpenBraceToken:
return isJsxExpression(parent) && parent.parent.kind !== SyntaxKind.JsxElement ? checker.getContextualTypeForJsxAttribute(parent.parent) : undefined;
default:
return isEqualityOperatorKind(currentToken.kind) && ts.isBinaryExpression(parent) && isEqualityOperatorKind(parent.operatorToken.kind)
const argInfo = SignatureHelp.getImmediatelyContainingArgumentInfo(currentToken, position, sourceFile);
return argInfo
// At `,`, treat this as the next argument after the comma.
? checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex + (currentToken.kind === SyntaxKind.CommaToken ? 1 : 0))
: isEqualityOperatorKind(currentToken.kind) && isBinaryExpression(parent) && isEqualityOperatorKind(parent.operatorToken.kind)
// completion at `x ===/**/` should be for the right side
? checker.getTypeAtLocation(parent.left)
: checker.getContextualType(currentToken as ts.Expression);
: checker.getContextualType(currentToken as Expression);
}
}
@@ -956,7 +970,7 @@ namespace ts.Completions {
log("getCompletionData: Semantic work: " + (timestamp() - semanticStart));
const recommendedCompletion = previousToken && getRecommendedCompletion(previousToken, typeChecker);
const recommendedCompletion = previousToken && getRecommendedCompletion(previousToken, position, sourceFile, typeChecker);
return { kind: CompletionDataKind.Data, symbols, completionKind, propertyAccessToConvert, isNewIdentifierLocation, location, keywordFilters, symbolToOriginInfoMap, recommendedCompletion, previousToken, isJsxInitializer };
type JSDocTagWithTypeExpression = JSDocParameterTag | JSDocPropertyTag | JSDocReturnTag | JSDocTypeTag | JSDocTypedefTag;
@@ -1068,10 +1082,10 @@ namespace ts.Completions {
let attrsType: Type;
if ((jsxContainer.kind === SyntaxKind.JsxSelfClosingElement) || (jsxContainer.kind === SyntaxKind.JsxOpeningElement)) {
// Cursor is inside a JSX self-closing element or opening element
attrsType = typeChecker.getAllAttributesTypeFromJsxOpeningLikeElement(<JsxOpeningLikeElement>jsxContainer);
attrsType = typeChecker.getAllAttributesTypeFromJsxOpeningLikeElement(jsxContainer);
if (attrsType) {
symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), (<JsxOpeningLikeElement>jsxContainer).attributes.properties);
symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), jsxContainer.attributes.properties);
completionKind = CompletionKind.MemberLike;
isNewIdentifierLocation = false;
return true;
@@ -1429,10 +1443,10 @@ namespace ts.Completions {
// We are completing on contextual types, but may also include properties
// other than those within the declared type.
isNewIdentifierLocation = true;
const typeForObject = typeChecker.getContextualType(<ObjectLiteralExpression>objectLikeContainer);
const typeForObject = typeChecker.getContextualType(objectLikeContainer);
if (!typeForObject) return false;
typeMembers = getPropertiesForCompletion(typeForObject, typeChecker, /*isForAccess*/ false);
existingMembers = (<ObjectLiteralExpression>objectLikeContainer).properties;
existingMembers = objectLikeContainer.properties;
}
else {
Debug.assert(objectLikeContainer.kind === SyntaxKind.ObjectBindingPattern);
@@ -1461,7 +1475,7 @@ namespace ts.Completions {
if (!typeForObject) return false;
// In a binding pattern, get only known properties. Everywhere else we will get all possible properties.
typeMembers = typeChecker.getPropertiesOfType(typeForObject).filter((symbol) => !(getDeclarationModifierFlagsFromSymbol(symbol) & ModifierFlags.NonPublicAccessibilityModifier));
existingMembers = (<ObjectBindingPattern>objectLikeContainer).elements;
existingMembers = objectLikeContainer.elements;
}
}
@@ -2073,7 +2087,7 @@ namespace ts.Completions {
}
if (attr.kind === SyntaxKind.JsxAttribute) {
seenNames.set((<JsxAttribute>attr).name.escapedText, true);
seenNames.set(attr.name.escapedText, true);
}
}
+8 -8
View File
@@ -356,7 +356,7 @@ namespace ts.FindAllReferences.Core {
/** Core find-all-references algorithm for a normal symbol. */
function getReferencedSymbolsForSymbol(symbol: Symbol, node: Node, sourceFiles: ReadonlyArray<SourceFile>, checker: TypeChecker, cancellationToken: CancellationToken, options: Options): SymbolAndEntries[] {
symbol = skipPastExportOrImportSpecifierOrUnion(symbol, node, checker);
symbol = skipPastExportOrImportSpecifierOrUnion(symbol, node, checker) || symbol;
// Compute the meaning from the location and the symbol it references
const searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), symbol.declarations);
@@ -405,7 +405,7 @@ namespace ts.FindAllReferences.Core {
}
/** Handle a few special cases relating to export/import specifiers. */
function skipPastExportOrImportSpecifierOrUnion(symbol: Symbol, node: Node, checker: TypeChecker): Symbol {
function skipPastExportOrImportSpecifierOrUnion(symbol: Symbol, node: Node, checker: TypeChecker): Symbol | undefined {
const { parent } = node;
if (isExportSpecifier(parent)) {
return getLocalSymbolForExportSpecifier(node as Identifier, symbol, parent, checker);
@@ -425,7 +425,7 @@ namespace ts.FindAllReferences.Core {
return isTypeLiteralNode(decl.parent) && isUnionTypeNode(decl.parent.parent)
? checker.getPropertyOfType(checker.getTypeFromTypeNode(decl.parent.parent), symbol.name)
: undefined;
}) || symbol;
});
}
/**
@@ -912,7 +912,7 @@ namespace ts.FindAllReferences.Core {
// For `export { foo as bar }`, rename `foo`, but not `bar`.
if (!(referenceLocation === propertyName && state.options.isForRename)) {
const exportKind = (referenceLocation as Identifier).originalKeywordKind === ts.SyntaxKind.DefaultKeyword ? ExportKind.Default : ExportKind.Named;
const exportKind = referenceLocation.originalKeywordKind === ts.SyntaxKind.DefaultKeyword ? ExportKind.Default : ExportKind.Named;
const exportInfo = getExportInfo(referenceSymbol, exportKind, state.checker);
Debug.assert(!!exportInfo);
searchForImportsOfExport(referenceLocation, referenceSymbol, exportInfo, state);
@@ -1125,7 +1125,7 @@ namespace ts.FindAllReferences.Core {
}
});
}
else if (isImplementationExpression(<Expression>body)) {
else if (isImplementationExpression(body)) {
addReference(body);
}
}
@@ -1647,10 +1647,10 @@ namespace ts.FindAllReferences.Core {
function getNameFromObjectLiteralElement(node: ObjectLiteralElement): string {
if (node.name.kind === SyntaxKind.ComputedPropertyName) {
const nameExpression = (<ComputedPropertyName>node.name).expression;
const nameExpression = node.name.expression;
// treat computed property names where expression is string/numeric literal as just string/numeric literal
if (isStringOrNumericLiteral(nameExpression)) {
return (<LiteralExpression>nameExpression).text;
return nameExpression.text;
}
return undefined;
}
@@ -1728,7 +1728,7 @@ namespace ts.FindAllReferences.Core {
function getParentStatementOfVariableDeclaration(node: VariableDeclaration): VariableStatement {
if (node.parent && node.parent.parent && node.parent.parent.kind === SyntaxKind.VariableStatement) {
Debug.assert(node.parent.kind === SyntaxKind.VariableDeclarationList);
return <VariableStatement>node.parent.parent;
return node.parent.parent;
}
}
+1 -1
View File
@@ -200,7 +200,7 @@ namespace ts.formatting {
return rangeContainsRange((<InterfaceDeclaration>parent).members, node);
case SyntaxKind.ModuleDeclaration:
const body = (<ModuleDeclaration>parent).body;
return body && body.kind === SyntaxKind.ModuleBlock && rangeContainsRange((<ModuleBlock>body).statements, node);
return body && body.kind === SyntaxKind.ModuleBlock && rangeContainsRange(body.statements, node);
case SyntaxKind.SourceFile:
case SyntaxKind.Block:
case SyntaxKind.ModuleBlock:
+2 -3
View File
@@ -383,9 +383,8 @@ namespace ts.formatting {
return Value.Unknown;
}
if (node.parent && isCallOrNewExpression(node.parent) && (<CallExpression>node.parent).expression !== node) {
const fullCallOrNewExpression = (<CallExpression | NewExpression>node.parent).expression;
if (node.parent && isCallOrNewExpression(node.parent) && node.parent.expression !== node) {
const fullCallOrNewExpression = node.parent.expression;
const startingExpression = getStartingExpression(fullCallOrNewExpression);
if (fullCallOrNewExpression === startingExpression) {
+1 -1
View File
@@ -629,7 +629,7 @@ namespace ts.FindAllReferences {
// For `export { foo } from './bar", there's nothing to skip, because it does not create a new alias. But `export { foo } does.
if (symbol.declarations) {
for (const declaration of symbol.declarations) {
if (isExportSpecifier(declaration) && !(declaration as ExportSpecifier).propertyName && !(declaration as ExportSpecifier).parent.parent.moduleSpecifier) {
if (isExportSpecifier(declaration) && !declaration.propertyName && !declaration.parent.parent.moduleSpecifier) {
return checker.getExportSpecifierLocalTargetSymbol(declaration);
}
}
+2 -3
View File
@@ -37,6 +37,7 @@ namespace ts.JsDoc {
"see",
"since",
"static",
"template",
"throws",
"type",
"typedef",
@@ -268,9 +269,7 @@ namespace ts.JsDoc {
let docParams = "";
for (let i = 0; i < parameters.length; i++) {
const currentName = parameters[i].name;
const paramName = currentName.kind === SyntaxKind.Identifier ?
(<Identifier>currentName).escapedText :
"param" + i;
const paramName = currentName.kind === SyntaxKind.Identifier ? currentName.escapedText : "param" + i;
if (isJavaScriptFile) {
docParams += `${indentationStr} * @param {any} ${paramName}${newLine}`;
}
+3 -3
View File
@@ -97,7 +97,7 @@ namespace ts.NavigateTo {
containers.unshift(text);
}
else if (name.kind === SyntaxKind.ComputedPropertyName) {
return tryAddComputedPropertyName((<ComputedPropertyName>name).expression, containers, /*includeLastPortion*/ true);
return tryAddComputedPropertyName(name.expression, containers, /*includeLastPortion*/ true);
}
else {
// Don't know how to add this.
@@ -140,7 +140,7 @@ namespace ts.NavigateTo {
// portion into the container array.
const name = getNameOfDeclaration(declaration);
if (name.kind === SyntaxKind.ComputedPropertyName) {
if (!tryAddComputedPropertyName((<ComputedPropertyName>name).expression, containers, /*includeLastPortion*/ false)) {
if (!tryAddComputedPropertyName(name.expression, containers, /*includeLastPortion*/ false)) {
return undefined;
}
}
@@ -181,7 +181,7 @@ namespace ts.NavigateTo {
function createNavigateToItem(rawItem: RawNavigateToItem): NavigateToItem {
const declaration = rawItem.declaration;
const container = <Declaration>getContainerNode(declaration);
const container = getContainerNode(declaration);
const containerName = container && getNameOfDeclaration(container);
return {
name: rawItem.name,
+4 -4
View File
@@ -197,10 +197,10 @@ namespace ts.NavigationBar {
const {namedBindings} = importClause;
if (namedBindings) {
if (namedBindings.kind === SyntaxKind.NamespaceImport) {
addLeafNode(<NamespaceImport>namedBindings);
addLeafNode(namedBindings);
}
else {
for (const element of (<NamedImports>namedBindings).elements) {
for (const element of namedBindings.elements) {
addLeafNode(element);
}
}
@@ -475,8 +475,8 @@ namespace ts.NavigationBar {
else {
const parentNode = node.parent && node.parent.parent;
if (parentNode && parentNode.kind === SyntaxKind.VariableStatement) {
if ((<VariableStatement>parentNode).declarationList.declarations.length > 0) {
const nameIdentifier = (<VariableStatement>parentNode).declarationList.declarations[0].name;
if (parentNode.declarationList.declarations.length > 0) {
const nameIdentifier = parentNode.declarationList.declarations[0].name;
if (nameIdentifier.kind === SyntaxKind.Identifier) {
return nameIdentifier.text;
}
+198
View File
@@ -0,0 +1,198 @@
/* @internal */
namespace ts.OrganizeImports {
export function organizeImports(
sourceFile: SourceFile,
formatContext: formatting.FormatContext,
host: LanguageServiceHost) {
// TODO (https://github.com/Microsoft/TypeScript/issues/10020): sort *within* ambient modules (find using isAmbientModule)
// All of the old ImportDeclarations in the file, in syntactic order.
const oldImportDecls = sourceFile.statements.filter(isImportDeclaration);
if (oldImportDecls.length === 0) {
return [];
}
const oldImportGroups = group(oldImportDecls, importDecl => getExternalModuleName(importDecl.moduleSpecifier));
const sortedImportGroups = stableSort(oldImportGroups, (group1, group2) =>
compareModuleSpecifiers(group1[0].moduleSpecifier, group2[0].moduleSpecifier));
const newImportDecls = flatMap(sortedImportGroups, importGroup =>
getExternalModuleName(importGroup[0].moduleSpecifier)
? coalesceImports(removeUnusedImports(importGroup))
: importGroup);
const changeTracker = textChanges.ChangeTracker.fromContext({ host, formatContext });
// Delete or replace the first import.
if (newImportDecls.length === 0) {
changeTracker.deleteNode(sourceFile, oldImportDecls[0]);
}
else {
// Note: Delete the surrounding trivia because it will have been retained in newImportDecls.
changeTracker.replaceNodeWithNodes(sourceFile, oldImportDecls[0], newImportDecls, {
useNonAdjustedStartPosition: false,
useNonAdjustedEndPosition: false,
suffix: getNewLineOrDefaultFromHost(host, formatContext.options),
});
}
// Delete any subsequent imports.
for (let i = 1; i < oldImportDecls.length; i++) {
changeTracker.deleteNode(sourceFile, oldImportDecls[i]);
}
return changeTracker.getChanges();
}
function removeUnusedImports(oldImports: ReadonlyArray<ImportDeclaration>) {
return oldImports; // TODO (https://github.com/Microsoft/TypeScript/issues/10020)
}
function getExternalModuleName(specifier: Expression) {
return isStringLiteral(specifier) || isNoSubstitutionTemplateLiteral(specifier)
? specifier.text
: undefined;
}
/* @internal */ // Internal for testing
/**
* @param importGroup a list of ImportDeclarations, all with the same module name.
*/
export function coalesceImports(importGroup: ReadonlyArray<ImportDeclaration>) {
if (importGroup.length === 0) {
return importGroup;
}
const { importWithoutClause, defaultImports, namespaceImports, namedImports } = getImportParts(importGroup);
const coalescedImports: ImportDeclaration[] = [];
if (importWithoutClause) {
coalescedImports.push(importWithoutClause);
}
// Normally, we don't combine default and namespace imports, but it would be silly to
// produce two import declarations in this special case.
if (defaultImports.length === 1 && namespaceImports.length === 1 && namedImports.length === 0) {
// Add the namespace import to the existing default ImportDeclaration.
const defaultImportClause = defaultImports[0].parent as ImportClause;
coalescedImports.push(
updateImportDeclarationAndClause(defaultImportClause, defaultImportClause.name, namespaceImports[0]));
return coalescedImports;
}
const sortedNamespaceImports = stableSort(namespaceImports, (n1, n2) => compareIdentifiers(n1.name, n2.name));
for (const namespaceImport of sortedNamespaceImports) {
// Drop the name, if any
coalescedImports.push(
updateImportDeclarationAndClause(namespaceImport.parent, /*name*/ undefined, namespaceImport));
}
if (defaultImports.length === 0 && namedImports.length === 0) {
return coalescedImports;
}
let newDefaultImport: Identifier | undefined;
const newImportSpecifiers: ImportSpecifier[] = [];
if (defaultImports.length === 1) {
newDefaultImport = defaultImports[0];
}
else {
for (const defaultImport of defaultImports) {
newImportSpecifiers.push(
createImportSpecifier(createIdentifier("default"), defaultImport));
}
}
newImportSpecifiers.push(...flatMap(namedImports, n => n.elements));
const sortedImportSpecifiers = stableSort(newImportSpecifiers, (s1, s2) =>
compareIdentifiers(s1.propertyName || s1.name, s2.propertyName || s2.name) ||
compareIdentifiers(s1.name, s2.name));
const importClause = defaultImports.length > 0
? defaultImports[0].parent as ImportClause
: namedImports[0].parent;
const newNamedImports = sortedImportSpecifiers.length === 0
? undefined
: namedImports.length === 0
? createNamedImports(sortedImportSpecifiers)
: updateNamedImports(namedImports[0], sortedImportSpecifiers);
coalescedImports.push(
updateImportDeclarationAndClause(importClause, newDefaultImport, newNamedImports));
return coalescedImports;
function getImportParts(importGroup: ReadonlyArray<ImportDeclaration>) {
let importWithoutClause: ImportDeclaration | undefined;
const defaultImports: Identifier[] = [];
const namespaceImports: NamespaceImport[] = [];
const namedImports: NamedImports[] = [];
for (const importDeclaration of importGroup) {
if (importDeclaration.importClause === undefined) {
// Only the first such import is interesting - the others are redundant.
// Note: Unfortunately, we will lose trivia that was on this node.
importWithoutClause = importWithoutClause || importDeclaration;
continue;
}
const { name, namedBindings } = importDeclaration.importClause;
if (name) {
defaultImports.push(name);
}
if (namedBindings) {
if (isNamespaceImport(namedBindings)) {
namespaceImports.push(namedBindings);
}
else {
namedImports.push(namedBindings);
}
}
}
return {
importWithoutClause,
defaultImports,
namespaceImports,
namedImports,
};
}
function compareIdentifiers(s1: Identifier, s2: Identifier) {
return compareStringsCaseSensitive(s1.text, s2.text);
}
function updateImportDeclarationAndClause(
importClause: ImportClause,
name: Identifier | undefined,
namedBindings: NamedImportBindings | undefined) {
const importDeclaration = importClause.parent;
return updateImportDeclaration(
importDeclaration,
importDeclaration.decorators,
importDeclaration.modifiers,
updateImportClause(importClause, name, namedBindings),
importDeclaration.moduleSpecifier);
}
}
/* internal */ // Exported for testing
export function compareModuleSpecifiers(m1: Expression, m2: Expression) {
const name1 = getExternalModuleName(m1);
const name2 = getExternalModuleName(m2);
return compareBooleans(name1 === undefined, name2 === undefined) ||
compareBooleans(isExternalModuleNameRelative(name1), isExternalModuleNameRelative(name2)) ||
compareStringsCaseSensitive(name1, name2);
}
}
@@ -118,7 +118,7 @@ namespace ts.refactor.annotateWithTypeFromJSDoc {
case SyntaxKind.Constructor:
return createConstructor(decl.decorators, decl.modifiers, parameters, decl.body);
case SyntaxKind.FunctionExpression:
return createFunctionExpression(decl.modifiers, decl.asteriskToken, (decl as FunctionExpression).name, typeParameters, parameters, returnType, decl.body);
return createFunctionExpression(decl.modifiers, decl.asteriskToken, decl.name, typeParameters, parameters, returnType, decl.body);
case SyntaxKind.ArrowFunction:
return createArrowFunction(decl.modifiers, typeParameters, parameters, returnType, decl.equalsGreaterThanToken, decl.body);
case SyntaxKind.MethodDeclaration:
@@ -180,8 +180,7 @@ namespace ts.refactor.convertFunctionToES6Class {
}
// case 2: () => [1,2,3]
else {
const expression = arrowFunctionBody as Expression;
bodyBlock = createBlock([createReturn(expression)]);
bodyBlock = createBlock([createReturn(arrowFunctionBody)]);
}
const fullModifiers = concatenate(modifiers, getModifierKindFromSource(arrowFunction, SyntaxKind.AsyncKeyword));
const method = createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined,
+5 -9
View File
@@ -194,7 +194,7 @@ namespace ts.refactor {
}
function convertVariableStatement(sourceFile: SourceFile, statement: VariableStatement, changes: textChanges.ChangeTracker, checker: TypeChecker, identifiers: Identifiers, target: ScriptTarget): void {
const { declarationList } = statement as VariableStatement;
const { declarationList } = statement;
let foundImport = false;
const newNodes = flatMap(declarationList.declarations, decl => {
const { name, initializer } = decl;
@@ -290,14 +290,10 @@ namespace ts.refactor {
case SyntaxKind.ShorthandPropertyAssignment:
case SyntaxKind.SpreadAssignment:
return undefined;
case SyntaxKind.PropertyAssignment: {
const { name, initializer } = prop as PropertyAssignment;
return !isIdentifier(name) ? undefined : convertExportsDotXEquals(name.text, initializer);
}
case SyntaxKind.MethodDeclaration: {
const m = prop as MethodDeclaration;
return !isIdentifier(m.name) ? undefined : functionExpressionToDeclaration(m.name.text, [createToken(SyntaxKind.ExportKeyword)], m);
}
case SyntaxKind.PropertyAssignment:
return !isIdentifier(prop.name) ? undefined : convertExportsDotXEquals(prop.name.text, prop.initializer);
case SyntaxKind.MethodDeclaration:
return !isIdentifier(prop.name) ? undefined : functionExpressionToDeclaration(prop.name.text, [createToken(SyntaxKind.ExportKeyword)], prop);
default:
Debug.assertNever(prop);
}
+5 -5
View File
@@ -223,7 +223,7 @@ namespace ts.refactor.extractSymbol {
return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] };
}
const statements: Statement[] = [];
for (const statement of (<BlockLike>start.parent).statements) {
for (const statement of start.parent.statements) {
if (statement === start || statements.length) {
const errors = checkNode(statement);
if (errors) {
@@ -1476,7 +1476,7 @@ namespace ts.refactor.extractSymbol {
}
const seenUsages = createMap<Usage>();
const target = isReadonlyArray(targetRange.range) ? createBlock(<Statement[]>targetRange.range) : targetRange.range;
const target = isReadonlyArray(targetRange.range) ? createBlock(targetRange.range) : targetRange.range;
const unmodifiedNode = isReadonlyArray(targetRange.range) ? first(targetRange.range) : targetRange.range;
const inGenericContext = isInGenericContext(unmodifiedNode);
@@ -1681,9 +1681,9 @@ namespace ts.refactor.extractSymbol {
// if we get here this means that we are trying to handle 'write' and 'read' was already processed
// walk scopes and update existing records.
for (const perScope of usagesPerScope) {
const prevEntry = perScope.usages.get(identifier.text as string);
const prevEntry = perScope.usages.get(identifier.text);
if (prevEntry) {
perScope.usages.set(identifier.text as string, { usage, symbol, node: identifier });
perScope.usages.set(identifier.text, { usage, symbol, node: identifier });
}
}
return symbolId;
@@ -1730,7 +1730,7 @@ namespace ts.refactor.extractSymbol {
}
}
else {
usagesPerScope[i].usages.set(identifier.text as string, { usage, symbol, node: identifier });
usagesPerScope[i].usages.set(identifier.text, { usage, symbol, node: identifier });
}
}
}
+39 -87
View File
@@ -14,6 +14,7 @@
/// <reference path='jsTyping.ts' />
/// <reference path='navigateTo.ts' />
/// <reference path='navigationBar.ts' />
/// <reference path='organizeImports.ts' />
/// <reference path='outliningElementsCollector.ts' />
/// <reference path='patternMatcher.ts' />
/// <reference path='preProcess.ts' />
@@ -727,7 +728,7 @@ namespace ts {
}
if (name.kind === SyntaxKind.ComputedPropertyName) {
const expr = (<ComputedPropertyName>name).expression;
const expr = name.expression;
if (expr.kind === SyntaxKind.PropertyAccessExpression) {
return (<PropertyAccessExpression>expr).name.text;
}
@@ -831,10 +832,10 @@ namespace ts {
// import {a, b as B} from "mod";
if (importClause.namedBindings) {
if (importClause.namedBindings.kind === SyntaxKind.NamespaceImport) {
addDeclaration(<NamespaceImport>importClause.namedBindings);
addDeclaration(importClause.namedBindings);
}
else {
forEach((<NamedImports>importClause.namedBindings).elements, visit);
forEach(importClause.namedBindings.elements, visit);
}
}
}
@@ -1567,17 +1568,17 @@ namespace ts {
/// References and Occurrences
function getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[] {
let results = getOccurrencesAtPositionCore(fileName, position);
if (results) {
const sourceFile = getCanonicalFileName(normalizeSlashes(fileName));
// Get occurrences only supports reporting occurrences for the file queried. So
// filter down to that list.
results = filter(results, r => getCanonicalFileName(ts.normalizeSlashes(r.fileName)) === sourceFile);
}
return results;
const canonicalFileName = getCanonicalFileName(normalizeSlashes(fileName));
return flatMap(getDocumentHighlights(fileName, position, [fileName]), entry => entry.highlightSpans.map<ReferenceEntry>(highlightSpan => {
Debug.assert(getCanonicalFileName(normalizeSlashes(entry.fileName)) === canonicalFileName); // Get occurrences only supports reporting occurrences for the file queried.
return {
fileName: entry.fileName,
textSpan: highlightSpan.textSpan,
isWriteAccess: highlightSpan.kind === HighlightSpanKind.writtenReference,
isDefinition: false,
isInString: highlightSpan.isInString,
};
}));
}
function getDocumentHighlights(fileName: string, position: number, filesToSearch: ReadonlyArray<string>): DocumentHighlights[] {
@@ -1587,31 +1588,6 @@ namespace ts {
return DocumentHighlights.getDocumentHighlights(program, cancellationToken, sourceFile, position, sourceFilesToSearch);
}
function getOccurrencesAtPositionCore(fileName: string, position: number): ReferenceEntry[] {
return convertDocumentHighlights(getDocumentHighlights(fileName, position, [fileName]));
function convertDocumentHighlights(documentHighlights: DocumentHighlights[]): ReferenceEntry[] {
if (!documentHighlights) {
return undefined;
}
const result: ReferenceEntry[] = [];
for (const entry of documentHighlights) {
for (const highlightSpan of entry.highlightSpans) {
result.push({
fileName: entry.fileName,
textSpan: highlightSpan.textSpan,
isWriteAccess: highlightSpan.kind === HighlightSpanKind.writtenReference,
isDefinition: false,
isInString: highlightSpan.isInString,
});
}
}
return result;
}
}
function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] {
return getReferences(fileName, position, { findInStrings, findInComments, isForRename: true });
}
@@ -1792,55 +1768,21 @@ namespace ts {
return OutliningElementsCollector.collectElements(sourceFile, cancellationToken);
}
function getBraceMatchingAtPosition(fileName: string, position: number) {
const braceMatching = createMapFromTemplate({
[SyntaxKind.OpenBraceToken]: SyntaxKind.CloseBraceToken,
[SyntaxKind.OpenParenToken]: SyntaxKind.CloseParenToken,
[SyntaxKind.OpenBracketToken]: SyntaxKind.CloseBracketToken,
[SyntaxKind.GreaterThanToken]: SyntaxKind.LessThanToken,
});
braceMatching.forEach((value, key) => braceMatching.set(value.toString(), Number(key) as SyntaxKind));
function getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[] {
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
const result: TextSpan[] = [];
const token = getTouchingToken(sourceFile, position, /*includeJsDocComment*/ false);
if (token.getStart(sourceFile) === position) {
const matchKind = getMatchingTokenKind(token);
// Ensure that there is a corresponding token to match ours.
if (matchKind) {
const parentElement = token.parent;
const childNodes = parentElement.getChildren(sourceFile);
for (const current of childNodes) {
if (current.kind === matchKind) {
const range1 = createTextSpan(token.getStart(sourceFile), token.getWidth(sourceFile));
const range2 = createTextSpan(current.getStart(sourceFile), current.getWidth(sourceFile));
// We want to order the braces when we return the result.
if (range1.start < range2.start) {
result.push(range1, range2);
}
else {
result.push(range2, range1);
}
break;
}
}
}
}
return result;
function getMatchingTokenKind(token: Node): ts.SyntaxKind {
switch (token.kind) {
case ts.SyntaxKind.OpenBraceToken: return ts.SyntaxKind.CloseBraceToken;
case ts.SyntaxKind.OpenParenToken: return ts.SyntaxKind.CloseParenToken;
case ts.SyntaxKind.OpenBracketToken: return ts.SyntaxKind.CloseBracketToken;
case ts.SyntaxKind.LessThanToken: return ts.SyntaxKind.GreaterThanToken;
case ts.SyntaxKind.CloseBraceToken: return ts.SyntaxKind.OpenBraceToken;
case ts.SyntaxKind.CloseParenToken: return ts.SyntaxKind.OpenParenToken;
case ts.SyntaxKind.CloseBracketToken: return ts.SyntaxKind.OpenBracketToken;
case ts.SyntaxKind.GreaterThanToken: return ts.SyntaxKind.LessThanToken;
}
return undefined;
}
const matchKind = token.getStart(sourceFile) === position ? braceMatching.get(token.kind.toString()) : undefined;
const match = matchKind && findChildOfKind(token.parent, matchKind, sourceFile);
// We want to order the braces when we return the result.
return match ? [createTextSpanFromNode(token, sourceFile), createTextSpanFromNode(match, sourceFile)].sort((a, b) => a.start - b.start) : emptyArray;
}
function getIndentationAtPosition(fileName: string, position: number, editorOptions: EditorOptions | EditorSettings) {
@@ -1907,6 +1849,15 @@ namespace ts {
return codefix.getAllFixes({ fixId, sourceFile, program, host, cancellationToken, formatContext });
}
function organizeImports(scope: OrganizeImportsScope, formatOptions: FormatCodeSettings): ReadonlyArray<FileTextChanges> {
synchronizeHostData();
Debug.assert(scope.type === "file");
const sourceFile = getValidSourceFile(scope.fileName);
const formatContext = formatting.getFormatContext(formatOptions);
return OrganizeImports.organizeImports(sourceFile, formatContext, host);
}
function applyCodeActionCommand(action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
function applyCodeActionCommand(action: CodeActionCommand[]): Promise<ApplyCodeActionCommandResult[]>;
function applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
@@ -2202,6 +2153,7 @@ namespace ts {
getCodeFixesAtPosition,
getCombinedCodeFix,
applyCodeActionCommand,
organizeImports,
getEmitOutput,
getNonBoundSourceFile,
getSourceFile,
@@ -2266,7 +2218,7 @@ namespace ts {
case SyntaxKind.Identifier:
return isObjectLiteralElement(node.parent) &&
(node.parent.parent.kind === SyntaxKind.ObjectLiteralExpression || node.parent.parent.kind === SyntaxKind.JsxAttributes) &&
(<ObjectLiteralElement>node.parent).name === node ? node.parent as ObjectLiteralElement : undefined;
node.parent.name === node ? node.parent : undefined;
}
return undefined;
}
+7 -16
View File
@@ -57,14 +57,9 @@ namespace ts.SignatureHelp {
}
// See if we can find some symbol with the call expression name that has call signatures.
const callExpression = <CallExpression>argumentInfo.invocation;
const callExpression = argumentInfo.invocation;
const expression = callExpression.expression;
const name = expression.kind === SyntaxKind.Identifier
? <Identifier>expression
: expression.kind === SyntaxKind.PropertyAccessExpression
? (<PropertyAccessExpression>expression).name
: undefined;
const name = isIdentifier(expression) ? expression : isPropertyAccessExpression(expression) ? expression.name : undefined;
if (!name || !name.escapedText) {
return undefined;
}
@@ -95,7 +90,7 @@ namespace ts.SignatureHelp {
* Returns relevant information for the argument list and the current argument if we are
* in the argument of an invocation; returns undefined otherwise.
*/
export function getImmediatelyContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile): ArgumentListInfo {
export function getImmediatelyContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile): ArgumentListInfo | undefined {
if (isCallOrNewExpression(node.parent)) {
const invocation = node.parent;
let list: Node;
@@ -160,7 +155,7 @@ namespace ts.SignatureHelp {
}
else if (node.parent.kind === SyntaxKind.TemplateSpan && node.parent.parent.parent.kind === SyntaxKind.TaggedTemplateExpression) {
const templateSpan = <TemplateSpan>node.parent;
const templateExpression = <TemplateExpression>templateSpan.parent;
const templateExpression = templateSpan.parent;
const tagExpression = <TaggedTemplateExpression>templateExpression.parent;
Debug.assert(templateExpression.kind === SyntaxKind.TemplateExpression);
@@ -207,8 +202,7 @@ namespace ts.SignatureHelp {
// that trailing comma in the list, and we'll have generated the appropriate
// arg index.
let argumentIndex = 0;
const listChildren = argumentsList.getChildren();
for (const child of listChildren) {
for (const child of argumentsList.getChildren()) {
if (child === node) {
break;
}
@@ -270,10 +264,7 @@ namespace ts.SignatureHelp {
function getArgumentListInfoForTemplate(tagExpression: TaggedTemplateExpression, argumentIndex: number, sourceFile: SourceFile): ArgumentListInfo {
// argumentCount is either 1 or (numSpans + 1) to account for the template strings array argument.
const argumentCount = tagExpression.template.kind === SyntaxKind.NoSubstitutionTemplateLiteral
? 1
: (<TemplateExpression>tagExpression.template).templateSpans.length + 1;
const argumentCount = isNoSubstitutionTemplateLiteral(tagExpression.template) ? 1 : tagExpression.template.templateSpans.length + 1;
if (argumentIndex !== 0) {
Debug.assertLessThan(argumentIndex, argumentCount);
}
@@ -314,7 +305,7 @@ namespace ts.SignatureHelp {
// This is because a Missing node has no width. However, what we actually want is to include trivia
// leading up to the next token in case the user is about to type in a TemplateMiddle or TemplateTail.
if (template.kind === SyntaxKind.TemplateExpression) {
const lastSpan = lastOrUndefined((<TemplateExpression>template).templateSpans);
const lastSpan = lastOrUndefined(template.templateSpans);
if (lastSpan.literal.getFullWidth() === 0) {
applicableSpanEnd = skipTrivia(sourceFile.text, applicableSpanEnd, /*stopAfterLineBreak*/ false);
}
+2 -2
View File
@@ -146,13 +146,13 @@ namespace ts.SymbolDisplay {
// try get the call/construct signature from the type if it matches
let callExpressionLike: CallExpression | NewExpression | JsxOpeningLikeElement;
if (isCallOrNewExpression(location)) {
callExpressionLike = <CallExpression | NewExpression>location;
callExpressionLike = location;
}
else if (isCallExpressionTarget(location) || isNewExpressionTarget(location)) {
callExpressionLike = <CallExpression | NewExpression>location.parent;
}
else if (location.parent && isJsxOpeningLikeElement(location.parent) && isFunctionLike(symbol.valueDeclaration)) {
callExpressionLike = <JsxOpeningLikeElement>location.parent;
callExpressionLike = location.parent;
}
if (callExpressionLike) {
+12 -34
View File
@@ -197,13 +197,12 @@ namespace ts.textChanges {
export class ChangeTracker {
private readonly changes: Change[] = [];
private readonly newLineCharacter: string;
private readonly deletedNodesInLists: true[] = []; // Stores ids of nodes in lists that we already deleted. Used to avoid deleting `, ` twice in `a, b`.
// Map from class id to nodes to insert at the start
private readonly nodesInsertedAtClassStarts = createMap<{ sourceFile: SourceFile, cls: ClassLikeDeclaration, members: ClassElement[] }>();
public static fromContext(context: TextChangesContext): ChangeTracker {
return new ChangeTracker(getNewLineOrDefaultFromHost(context.host, context.formatContext.options) === "\n" ? NewLineKind.LineFeed : NewLineKind.CarriageReturnLineFeed, context.formatContext);
return new ChangeTracker(getNewLineOrDefaultFromHost(context.host, context.formatContext.options), context.formatContext);
}
public static with(context: TextChangesContext, cb: (tracker: ChangeTracker) => void): FileTextChanges[] {
@@ -212,11 +211,11 @@ namespace ts.textChanges {
return tracker.getChanges();
}
/** Public for tests only. Other callers should use `ChangeTracker.with`. */
constructor(
private readonly newLine: NewLineKind,
private readonly newLineCharacter: string,
private readonly formatContext: ts.formatting.FormatContext,
private readonly validator?: (text: NonFormattedText) => void) {
this.newLineCharacter = getNewLineCharacter({ newLine });
}
public deleteRange(sourceFile: SourceFile, range: TextRange) {
@@ -593,32 +592,12 @@ namespace ts.textChanges {
public getChanges(): FileTextChanges[] {
this.finishInsertNodeAtClassStart();
const changesPerFile = createMap<Change[]>();
// group changes per file
for (const c of this.changes) {
let changesInFile = changesPerFile.get(c.sourceFile.path);
if (!changesInFile) {
changesPerFile.set(c.sourceFile.path, changesInFile = []);
}
changesInFile.push(c);
}
// convert changes
const fileChangesList: FileTextChanges[] = [];
changesPerFile.forEach(changesInFile => {
return group(this.changes, c => c.sourceFile.path).map(changesInFile => {
const sourceFile = changesInFile[0].sourceFile;
const fileTextChanges: FileTextChanges = { fileName: sourceFile.fileName, textChanges: [] };
for (const c of ChangeTracker.normalize(changesInFile)) {
fileTextChanges.textChanges.push(createTextChange(this.computeSpan(c, sourceFile), this.computeNewText(c, sourceFile)));
}
fileChangesList.push(fileTextChanges);
const textChanges = ChangeTracker.normalize(changesInFile).map(c =>
createTextChange(createTextSpanFromRange(c.range), this.computeNewText(c, sourceFile)));
return { fileName: sourceFile.fileName, textChanges };
});
return fileChangesList;
}
private computeSpan(change: Change, _sourceFile: SourceFile): TextSpan {
return createTextSpanFromRange(change.range);
}
private computeNewText(change: Change, sourceFile: SourceFile): string {
@@ -651,7 +630,7 @@ namespace ts.textChanges {
}
private getFormattedTextOfNode(node: Node, sourceFile: SourceFile, pos: number, options: ChangeNodeOptions): string {
const nonformattedText = getNonformattedText(node, sourceFile, this.newLine);
const nonformattedText = getNonformattedText(node, sourceFile, this.newLineCharacter);
if (this.validator) {
this.validator(nonformattedText);
}
@@ -675,7 +654,7 @@ namespace ts.textChanges {
return applyFormatting(nonformattedText, sourceFile, initialIndentation, delta, this.formatContext);
}
private static normalize(changes: Change[]): Change[] {
private static normalize(changes: ReadonlyArray<Change>): ReadonlyArray<Change> {
// order changes by start position
const normalized = stableSort(changes, (a, b) => a.range.pos - b.range.pos);
// verify that change intervals do not overlap, except possibly at end points.
@@ -691,10 +670,9 @@ namespace ts.textChanges {
readonly node: Node;
}
function getNonformattedText(node: Node, sourceFile: SourceFile | undefined, newLine: NewLineKind): NonFormattedText {
const options = { newLine, target: sourceFile && sourceFile.languageVersion };
const writer = new Writer(getNewLineCharacter(options));
const printer = createPrinter(options, writer);
function getNonformattedText(node: Node, sourceFile: SourceFile | undefined, newLine: string): NonFormattedText {
const writer = new Writer(newLine);
const printer = createPrinter({ newLine: newLine === "\n" ? NewLineKind.LineFeed : NewLineKind.CarriageReturnLineFeed }, writer);
printer.writeNode(EmitHint.Unspecified, node, sourceFile, writer);
return { text: writer.getText(), node: assignPositionsToNode(node) };
}
+1
View File
@@ -58,6 +58,7 @@
"jsTyping.ts",
"navigateTo.ts",
"navigationBar.ts",
"organizeImports.ts",
"outliningElementsCollector.ts",
"pathCompletions.ts",
"patternMatcher.ts",
+4
View File
@@ -308,6 +308,7 @@ namespace ts {
applyCodeActionCommand(fileName: string, action: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange): ApplicableRefactorInfo[];
getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string): RefactorEditInfo | undefined;
organizeImports(scope: OrganizeImportsScope, formatOptions: FormatCodeSettings): ReadonlyArray<FileTextChanges>;
getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput;
@@ -326,6 +327,8 @@ namespace ts {
export interface CombinedCodeFixScope { type: "file"; fileName: string; }
export type OrganizeImportsScope = CombinedCodeFixScope;
export interface GetCompletionsAtPositionOptions {
includeExternalModuleExports: boolean;
includeInsertTextCompletions: boolean;
@@ -724,6 +727,7 @@ namespace ts {
}
export interface CompletionInfo {
/** Not true for all glboal completions. This will be true if the enclosing scope matches a few syntax kinds. See `isGlobalCompletionScope`. */
isGlobalCompletion: boolean;
isMemberCompletion: boolean;
+1 -1
View File
@@ -131,7 +131,7 @@ namespace ts {
while (node.parent.kind === SyntaxKind.QualifiedName) {
node = node.parent;
}
return isInternalModuleImportEqualsDeclaration(node.parent) && (<ImportEqualsDeclaration>node.parent).moduleReference === node;
return isInternalModuleImportEqualsDeclaration(node.parent) && node.parent.moduleReference === node;
}
function isNamespaceReference(node: Node): boolean {
+22
View File
@@ -4135,6 +4135,7 @@ declare namespace ts {
applyCodeActionCommand(fileName: string, action: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange): ApplicableRefactorInfo[];
getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string): RefactorEditInfo | undefined;
organizeImports(scope: OrganizeImportsScope, formatOptions: FormatCodeSettings): ReadonlyArray<FileTextChanges>;
getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput;
getProgram(): Program;
dispose(): void;
@@ -4143,6 +4144,7 @@ declare namespace ts {
type: "file";
fileName: string;
}
type OrganizeImportsScope = CombinedCodeFixScope;
interface GetCompletionsAtPositionOptions {
includeExternalModuleExports: boolean;
includeInsertTextCompletions: boolean;
@@ -4488,6 +4490,7 @@ declare namespace ts {
argumentCount: number;
}
interface CompletionInfo {
/** Not true for all glboal completions. This will be true if the enclosing scope matches a few syntax kinds. See `isGlobalCompletionScope`. */
isGlobalCompletion: boolean;
isMemberCompletion: boolean;
/**
@@ -5078,6 +5081,7 @@ declare namespace ts.server.protocol {
GetSupportedCodeFixes = "getSupportedCodeFixes",
GetApplicableRefactors = "getApplicableRefactors",
GetEditsForRefactor = "getEditsForRefactor",
OrganizeImports = "organizeImports",
}
/**
* A TypeScript Server message
@@ -5429,6 +5433,23 @@ declare namespace ts.server.protocol {
renameLocation?: Location;
renameFilename?: string;
}
/**
* Organize imports by:
* 1) Removing unused imports
* 2) Coalescing imports from the same module
* 3) Sorting imports
*/
interface OrganizeImportsRequest extends Request {
command: CommandTypes.OrganizeImports;
arguments: OrganizeImportsRequestArgs;
}
type OrganizeImportsScope = GetCombinedCodeFixScope;
interface OrganizeImportsRequestArgs {
scope: OrganizeImportsScope;
}
interface OrganizeImportsResponse extends Response {
edits: ReadonlyArray<FileCodeEdits>;
}
/**
* Request for the available codefixes at a specific position.
*/
@@ -7282,6 +7303,7 @@ declare namespace ts.server {
private extractPositionAndRange(args, scriptInfo);
private getApplicableRefactors(args);
private getEditsForRefactor(args, simplifiedResult);
private organizeImports({scope}, simplifiedResult);
private getCodeFixes(args, simplifiedResult);
private getCombinedCodeFix({scope, fixId}, simplifiedResult);
private applyCodeActionCommand(args);
+3
View File
@@ -4387,6 +4387,7 @@ declare namespace ts {
applyCodeActionCommand(fileName: string, action: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange): ApplicableRefactorInfo[];
getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string): RefactorEditInfo | undefined;
organizeImports(scope: OrganizeImportsScope, formatOptions: FormatCodeSettings): ReadonlyArray<FileTextChanges>;
getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput;
getProgram(): Program;
dispose(): void;
@@ -4395,6 +4396,7 @@ declare namespace ts {
type: "file";
fileName: string;
}
type OrganizeImportsScope = CombinedCodeFixScope;
interface GetCompletionsAtPositionOptions {
includeExternalModuleExports: boolean;
includeInsertTextCompletions: boolean;
@@ -4740,6 +4742,7 @@ declare namespace ts {
argumentCount: number;
}
interface CompletionInfo {
/** Not true for all glboal completions. This will be true if the enclosing scope matches a few syntax kinds. See `isGlobalCompletionScope`. */
isGlobalCompletion: boolean;
isMemberCompletion: boolean;
/**
@@ -447,4 +447,34 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(275,43): error TS
type A = Omit<{ a: void; b: never; }>; // 'a'
type B = Omit2<{ a: void; b: never; }>; // 'a'
}
// Repro from #21862
type OldDiff<T extends string, U extends string> = (
& { [P in T]: P; }
& { [P in U]: never; }
& { [x: string]: never; }
)[T];
type NewDiff<T, U> = T extends U ? never : T;
interface A {
a: 'a';
}
interface B1 extends A {
b: 'b';
c: OldDiff<keyof this, keyof A>;
}
interface B2 extends A {
b: 'b';
c: NewDiff<keyof this, keyof A>;
}
type c1 = B1['c']; // 'c' | 'b'
type c2 = B2['c']; // 'c' | 'b'
// Repro from #21929
type NonFooKeys1<T extends object> = OldDiff<keyof T, 'foo'>;
type NonFooKeys2<T extends object> = Exclude<keyof T, 'foo'>;
type Test1 = NonFooKeys1<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz"
type Test2 = NonFooKeys2<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz"
@@ -285,6 +285,36 @@ function f50() {
type A = Omit<{ a: void; b: never; }>; // 'a'
type B = Omit2<{ a: void; b: never; }>; // 'a'
}
// Repro from #21862
type OldDiff<T extends string, U extends string> = (
& { [P in T]: P; }
& { [P in U]: never; }
& { [x: string]: never; }
)[T];
type NewDiff<T, U> = T extends U ? never : T;
interface A {
a: 'a';
}
interface B1 extends A {
b: 'b';
c: OldDiff<keyof this, keyof A>;
}
interface B2 extends A {
b: 'b';
c: NewDiff<keyof this, keyof A>;
}
type c1 = B1['c']; // 'c' | 'b'
type c2 = B2['c']; // 'c' | 'b'
// Repro from #21929
type NonFooKeys1<T extends object> = OldDiff<keyof T, 'foo'>;
type NonFooKeys2<T extends object> = Exclude<keyof T, 'foo'>;
type Test1 = NonFooKeys1<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz"
type Test2 = NonFooKeys2<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz"
//// [conditionalTypes1.js]
@@ -561,3 +591,36 @@ declare type T95<T> = T extends string ? boolean : number;
declare const f44: <U>(value: T94<U>) => T95<U>;
declare const f45: <U>(value: T95<U>) => T94<U>;
declare function f50(): void;
declare type OldDiff<T extends string, U extends string> = ({
[P in T]: P;
} & {
[P in U]: never;
} & {
[x: string]: never;
})[T];
declare type NewDiff<T, U> = T extends U ? never : T;
interface A {
a: 'a';
}
interface B1 extends A {
b: 'b';
c: OldDiff<keyof this, keyof A>;
}
interface B2 extends A {
b: 'b';
c: NewDiff<keyof this, keyof A>;
}
declare type c1 = B1['c'];
declare type c2 = B2['c'];
declare type NonFooKeys1<T extends object> = OldDiff<keyof T, 'foo'>;
declare type NonFooKeys2<T extends object> = Exclude<keyof T, 'foo'>;
declare type Test1 = NonFooKeys1<{
foo: 1;
bar: 2;
baz: 3;
}>;
declare type Test2 = NonFooKeys2<{
foo: 1;
bar: 2;
baz: 3;
}>;
@@ -1121,3 +1121,99 @@ function f50() {
>b : Symbol(b, Decl(conditionalTypes1.ts, 284, 29))
}
// Repro from #21862
type OldDiff<T extends string, U extends string> = (
>OldDiff : Symbol(OldDiff, Decl(conditionalTypes1.ts, 285, 1))
>T : Symbol(T, Decl(conditionalTypes1.ts, 289, 13))
>U : Symbol(U, Decl(conditionalTypes1.ts, 289, 30))
& { [P in T]: P; }
>P : Symbol(P, Decl(conditionalTypes1.ts, 290, 9))
>T : Symbol(T, Decl(conditionalTypes1.ts, 289, 13))
>P : Symbol(P, Decl(conditionalTypes1.ts, 290, 9))
& { [P in U]: never; }
>P : Symbol(P, Decl(conditionalTypes1.ts, 291, 9))
>U : Symbol(U, Decl(conditionalTypes1.ts, 289, 30))
& { [x: string]: never; }
>x : Symbol(x, Decl(conditionalTypes1.ts, 292, 9))
)[T];
>T : Symbol(T, Decl(conditionalTypes1.ts, 289, 13))
type NewDiff<T, U> = T extends U ? never : T;
>NewDiff : Symbol(NewDiff, Decl(conditionalTypes1.ts, 293, 5))
>T : Symbol(T, Decl(conditionalTypes1.ts, 294, 13))
>U : Symbol(U, Decl(conditionalTypes1.ts, 294, 15))
>T : Symbol(T, Decl(conditionalTypes1.ts, 294, 13))
>U : Symbol(U, Decl(conditionalTypes1.ts, 294, 15))
>T : Symbol(T, Decl(conditionalTypes1.ts, 294, 13))
interface A {
>A : Symbol(A, Decl(conditionalTypes1.ts, 294, 45))
a: 'a';
>a : Symbol(A.a, Decl(conditionalTypes1.ts, 295, 13))
}
interface B1 extends A {
>B1 : Symbol(B1, Decl(conditionalTypes1.ts, 297, 1))
>A : Symbol(A, Decl(conditionalTypes1.ts, 294, 45))
b: 'b';
>b : Symbol(B1.b, Decl(conditionalTypes1.ts, 298, 24))
c: OldDiff<keyof this, keyof A>;
>c : Symbol(B1.c, Decl(conditionalTypes1.ts, 299, 11))
>OldDiff : Symbol(OldDiff, Decl(conditionalTypes1.ts, 285, 1))
>A : Symbol(A, Decl(conditionalTypes1.ts, 294, 45))
}
interface B2 extends A {
>B2 : Symbol(B2, Decl(conditionalTypes1.ts, 301, 1))
>A : Symbol(A, Decl(conditionalTypes1.ts, 294, 45))
b: 'b';
>b : Symbol(B2.b, Decl(conditionalTypes1.ts, 302, 24))
c: NewDiff<keyof this, keyof A>;
>c : Symbol(B2.c, Decl(conditionalTypes1.ts, 303, 11))
>NewDiff : Symbol(NewDiff, Decl(conditionalTypes1.ts, 293, 5))
>A : Symbol(A, Decl(conditionalTypes1.ts, 294, 45))
}
type c1 = B1['c']; // 'c' | 'b'
>c1 : Symbol(c1, Decl(conditionalTypes1.ts, 305, 1))
>B1 : Symbol(B1, Decl(conditionalTypes1.ts, 297, 1))
type c2 = B2['c']; // 'c' | 'b'
>c2 : Symbol(c2, Decl(conditionalTypes1.ts, 306, 18))
>B2 : Symbol(B2, Decl(conditionalTypes1.ts, 301, 1))
// Repro from #21929
type NonFooKeys1<T extends object> = OldDiff<keyof T, 'foo'>;
>NonFooKeys1 : Symbol(NonFooKeys1, Decl(conditionalTypes1.ts, 307, 18))
>T : Symbol(T, Decl(conditionalTypes1.ts, 311, 17))
>OldDiff : Symbol(OldDiff, Decl(conditionalTypes1.ts, 285, 1))
>T : Symbol(T, Decl(conditionalTypes1.ts, 311, 17))
type NonFooKeys2<T extends object> = Exclude<keyof T, 'foo'>;
>NonFooKeys2 : Symbol(NonFooKeys2, Decl(conditionalTypes1.ts, 311, 61))
>T : Symbol(T, Decl(conditionalTypes1.ts, 312, 17))
>Exclude : Symbol(Exclude, Decl(lib.d.ts, --, --))
>T : Symbol(T, Decl(conditionalTypes1.ts, 312, 17))
type Test1 = NonFooKeys1<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz"
>Test1 : Symbol(Test1, Decl(conditionalTypes1.ts, 312, 61))
>NonFooKeys1 : Symbol(NonFooKeys1, Decl(conditionalTypes1.ts, 307, 18))
>foo : Symbol(foo, Decl(conditionalTypes1.ts, 314, 26))
>bar : Symbol(bar, Decl(conditionalTypes1.ts, 314, 33))
>baz : Symbol(baz, Decl(conditionalTypes1.ts, 314, 41))
type Test2 = NonFooKeys2<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz"
>Test2 : Symbol(Test2, Decl(conditionalTypes1.ts, 314, 51))
>NonFooKeys2 : Symbol(NonFooKeys2, Decl(conditionalTypes1.ts, 311, 61))
>foo : Symbol(foo, Decl(conditionalTypes1.ts, 315, 26))
>bar : Symbol(bar, Decl(conditionalTypes1.ts, 315, 33))
>baz : Symbol(baz, Decl(conditionalTypes1.ts, 315, 41))
@@ -1274,3 +1274,99 @@ function f50() {
>b : never
}
// Repro from #21862
type OldDiff<T extends string, U extends string> = (
>OldDiff : ({ [P in T]: P; } & { [P in U]: never; } & { [x: string]: never; })[T]
>T : T
>U : U
& { [P in T]: P; }
>P : P
>T : T
>P : P
& { [P in U]: never; }
>P : P
>U : U
& { [x: string]: never; }
>x : string
)[T];
>T : T
type NewDiff<T, U> = T extends U ? never : T;
>NewDiff : NewDiff<T, U>
>T : T
>U : U
>T : T
>U : U
>T : T
interface A {
>A : A
a: 'a';
>a : "a"
}
interface B1 extends A {
>B1 : B1
>A : A
b: 'b';
>b : "b"
c: OldDiff<keyof this, keyof A>;
>c : ({ [P in keyof this]: P; } & { a: never; } & { [x: string]: never; })[keyof this]
>OldDiff : ({ [P in T]: P; } & { [P in U]: never; } & { [x: string]: never; })[T]
>A : A
}
interface B2 extends A {
>B2 : B2
>A : A
b: 'b';
>b : "b"
c: NewDiff<keyof this, keyof A>;
>c : NewDiff<keyof this, "a">
>NewDiff : NewDiff<T, U>
>A : A
}
type c1 = B1['c']; // 'c' | 'b'
>c1 : "b" | "c"
>B1 : B1
type c2 = B2['c']; // 'c' | 'b'
>c2 : "b" | "c"
>B2 : B2
// Repro from #21929
type NonFooKeys1<T extends object> = OldDiff<keyof T, 'foo'>;
>NonFooKeys1 : ({ [P in keyof T]: P; } & { foo: never; } & { [x: string]: never; })[keyof T]
>T : T
>OldDiff : ({ [P in T]: P; } & { [P in U]: never; } & { [x: string]: never; })[T]
>T : T
type NonFooKeys2<T extends object> = Exclude<keyof T, 'foo'>;
>NonFooKeys2 : Exclude<keyof T, "foo">
>T : T
>Exclude : Exclude<T, U>
>T : T
type Test1 = NonFooKeys1<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz"
>Test1 : "bar" | "baz"
>NonFooKeys1 : ({ [P in keyof T]: P; } & { foo: never; } & { [x: string]: never; })[keyof T]
>foo : 1
>bar : 2
>baz : 3
type Test2 = NonFooKeys2<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz"
>Test2 : "bar" | "baz"
>NonFooKeys2 : Exclude<keyof T, "foo">
>foo : 1
>bar : 2
>baz : 3
@@ -0,0 +1,27 @@
tests/cases/compiler/noUnusedLocals_typeParameterMergedWithParameter.ts(1,18): error TS6133: 'T' is declared but its value is never read.
tests/cases/compiler/noUnusedLocals_typeParameterMergedWithParameter.ts(1,21): error TS6133: 'T' is declared but its value is never read.
tests/cases/compiler/noUnusedLocals_typeParameterMergedWithParameter.ts(3,19): error TS6133: 'T' is declared but its value is never read.
tests/cases/compiler/noUnusedLocals_typeParameterMergedWithParameter.ts(7,26): error TS6133: 'T' is declared but its value is never read.
==== tests/cases/compiler/noUnusedLocals_typeParameterMergedWithParameter.ts (4 errors) ====
function useNone<T>(T: number) {}
~
!!! error TS6133: 'T' is declared but its value is never read.
~
!!! error TS6133: 'T' is declared but its value is never read.
function useParam<T>(T: number) {
~
!!! error TS6133: 'T' is declared but its value is never read.
return T;
}
function useTypeParam<T>(T: T) {}
~
!!! error TS6133: 'T' is declared but its value is never read.
function useBoth<T>(T: T) {
return T;
}
@@ -0,0 +1,23 @@
//// [noUnusedLocals_typeParameterMergedWithParameter.ts]
function useNone<T>(T: number) {}
function useParam<T>(T: number) {
return T;
}
function useTypeParam<T>(T: T) {}
function useBoth<T>(T: T) {
return T;
}
//// [noUnusedLocals_typeParameterMergedWithParameter.js]
function useNone(T) { }
function useParam(T) {
return T;
}
function useTypeParam(T) { }
function useBoth(T) {
return T;
}
@@ -0,0 +1,31 @@
=== tests/cases/compiler/noUnusedLocals_typeParameterMergedWithParameter.ts ===
function useNone<T>(T: number) {}
>useNone : Symbol(useNone, Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 0, 0))
>T : Symbol(T, Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 0, 17), Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 0, 20))
>T : Symbol(T, Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 0, 17), Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 0, 20))
function useParam<T>(T: number) {
>useParam : Symbol(useParam, Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 0, 33))
>T : Symbol(T, Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 2, 18), Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 2, 21))
>T : Symbol(T, Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 2, 18), Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 2, 21))
return T;
>T : Symbol(T, Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 2, 18), Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 2, 21))
}
function useTypeParam<T>(T: T) {}
>useTypeParam : Symbol(useTypeParam, Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 4, 1))
>T : Symbol(T, Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 6, 22), Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 6, 25))
>T : Symbol(T, Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 6, 22), Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 6, 25))
>T : Symbol(T, Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 6, 22), Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 6, 25))
function useBoth<T>(T: T) {
>useBoth : Symbol(useBoth, Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 6, 33))
>T : Symbol(T, Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 8, 17), Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 8, 20))
>T : Symbol(T, Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 8, 17), Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 8, 20))
>T : Symbol(T, Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 8, 17), Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 8, 20))
return T;
>T : Symbol(T, Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 8, 17), Decl(noUnusedLocals_typeParameterMergedWithParameter.ts, 8, 20))
}
@@ -0,0 +1,31 @@
=== tests/cases/compiler/noUnusedLocals_typeParameterMergedWithParameter.ts ===
function useNone<T>(T: number) {}
>useNone : <T>(T: number) => void
>T : T
>T : number
function useParam<T>(T: number) {
>useParam : <T>(T: number) => number
>T : T
>T : number
return T;
>T : number
}
function useTypeParam<T>(T: T) {}
>useTypeParam : <T>(T: T) => void
>T : T
>T : T
>T : T
function useBoth<T>(T: T) {
>useBoth : <T>(T: T) => T
>T : T
>T : T
>T : T
return T;
>T : T
}
@@ -0,0 +1,11 @@
// ==ORIGINAL==
import { d } from "lib1";
import { b } from "lib1";
import { c } from "lib2";
import { a } from "lib2";
// ==ORGANIZED==
import { b, d } from "lib1";
import { a, c } from "lib2";
@@ -0,0 +1,15 @@
// ==ORIGINAL==
/*A*/import /*B*/ { /*C*/ F2 /*D*/ } /*E*/ from /*F*/ "lib" /*G*/;/*H*/ //I
/*J*/import /*K*/ { /*L*/ F1 /*M*/ } /*N*/ from /*O*/ "lib" /*P*/;/*Q*/ //R
F1();
F2();
// ==ORGANIZED==
/*A*/ import { /*L*/ F1 /*M*/, /*C*/ F2 /*D*/ } /*E*/ from "lib" /*G*/; /*H*/ //I
F1();
F2();
@@ -0,0 +1,18 @@
// ==ORIGINAL==
import { F1, F2 } from "lib";
F1();
F2();
import * as NS from "lib";
NS.F1();
import D from "lib";
D();
// ==ORGANIZED==
import * as NS from "lib";
import D, { F1, F2 } from "lib";
F1();
F2();
NS.F1();
D();
@@ -0,0 +1,22 @@
// ==ORIGINAL==
import { F1, F2 } from "lib";
F1();
F2();
import * as NS from "lib";
NS.F1();
import b from `${'lib'}`;
import a from `${'lib'}`;
import D from "lib";
D();
// ==ORGANIZED==
import * as NS from "lib";
import D, { F1, F2 } from "lib";
import b from `${'lib'}`;
import a from `${'lib'}`;
F1();
F2();
NS.F1();
D();
@@ -0,0 +1,20 @@
// ==ORIGINAL==
import { F1, F2 } from "lib";
import * as NS from "lib";
import D from "lib";
NS.F1();
D();
F1();
F2();
// ==ORGANIZED==
import * as NS from "lib";
import D, { F1, F2 } from "lib";
NS.F1();
D();
F1();
F2();
@@ -0,0 +1,10 @@
// ==ORIGINAL==
/*A*/import /*B*/ "lib2" /*C*/;/*D*/ //E
/*F*/import /*G*/ "lib1" /*H*/;/*I*/ //J
// ==ORGANIZED==
/*F*/ import "lib1" /*H*/; /*I*/ //J
/*A*/ import "lib2" /*C*/; /*D*/ //E
@@ -0,0 +1,14 @@
// @noUnusedLocals: true
// @noUnusedParameters: true
function useNone<T>(T: number) {}
function useParam<T>(T: number) {
return T;
}
function useTypeParam<T>(T: T) {}
function useBoth<T>(T: T) {
return T;
}
@@ -287,3 +287,33 @@ function f50() {
type A = Omit<{ a: void; b: never; }>; // 'a'
type B = Omit2<{ a: void; b: never; }>; // 'a'
}
// Repro from #21862
type OldDiff<T extends string, U extends string> = (
& { [P in T]: P; }
& { [P in U]: never; }
& { [x: string]: never; }
)[T];
type NewDiff<T, U> = T extends U ? never : T;
interface A {
a: 'a';
}
interface B1 extends A {
b: 'b';
c: OldDiff<keyof this, keyof A>;
}
interface B2 extends A {
b: 'b';
c: NewDiff<keyof this, keyof A>;
}
type c1 = B1['c']; // 'c' | 'b'
type c2 = B2['c']; // 'c' | 'b'
// Repro from #21929
type NonFooKeys1<T extends object> = OldDiff<keyof T, 'foo'>;
type NonFooKeys2<T extends object> = Exclude<keyof T, 'foo'>;
type Test1 = NonFooKeys1<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz"
type Test2 = NonFooKeys2<{foo: 1, bar: 2, baz: 3}>; // "bar" | "baz"
@@ -59,6 +59,7 @@ verify.completionListContains("constructor");
verify.completionListContains("param");
verify.completionListContains("type");
verify.completionListContains("method");
verify.completionListContains("template");
goTo.marker('2');
verify.completionListContains("constructor");
@@ -0,0 +1,27 @@
/// <reference path="fourslash.ts" />
// @jsx: preserve
// @Filename: /a.tsx
////enum E {}
////enum F {}
////function f(e: E, f: F) {}
////f(/*arg0*/, /*arg1*/);
////
////function tag(arr: TemplateStringsArray, x: E) {}
////tag`${/*tag*/}`;
////
////declare function MainButton(props: { e: E }): any;
////<MainButton e={/*jsx*/} />
////<MainButton e=/*jsx2*/ />
recommended("arg0");
recommended("arg1", "F");
recommended("tag");
recommended("jsx");
recommended("jsx2");
function recommended(markerName: string, enumName = "E") {
goTo.marker(markerName);
verify.completionListContains(enumName, `enum ${enumName}`, "", "enum", undefined, undefined , { isRecommended: true });
}
@@ -0,0 +1,7 @@
/// <reference path='fourslash.ts'/>
////import { [|ab|] as [|cd|] } from "doesNotExist";
const [r0, r1] = test.ranges();
verify.referencesOf(r0, [r1]);
verify.referencesOf(r1, [r1]);
@@ -27,5 +27,5 @@ verify.currentSignatureParameterCountIs(2);
verify.currentSignatureHelpIs("f3(n: number, s: string): string");
verify.currentParameterHelpArgumentNameIs("s");
verify.currentParameterSpanIs("s: string");
verify.currentParameterSpanIs("s: string");
+2
View File
@@ -2,6 +2,8 @@
"extends": "tslint:latest",
"rulesDirectory": "built/local/tslint/rules",
"rules": {
"no-unnecessary-type-assertion-2": true,
"array-type": [true, "array"],
"ban-types": {
"options": [