Merge branch 'master' into out-module-concat

This commit is contained in:
Wesley Wigham 2015-11-09 12:38:23 -08:00
commit cadf54334b
62 changed files with 4444 additions and 3478 deletions

View file

@ -1,5 +1,6 @@
built built
doc doc
lib/README.md
scripts scripts
src src
tests tests

View file

@ -1,6 +1,7 @@
language: node_js language: node_js
node_js: node_js:
- 'stable'
- '4' - '4'
- '0.10' - '0.10'

View file

@ -32,6 +32,19 @@ Your pull request should:
* Follow the code conventions descriped in [Coding guidelines](https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines) * Follow the code conventions descriped in [Coding guidelines](https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines)
* To avoid line ending issues, set `autocrlf = input` and `whitespace = cr-at-eol` in your git configuration * To avoid line ending issues, set `autocrlf = input` and `whitespace = cr-at-eol` in your git configuration
## Contributing `lib.d.ts` fixes
The library sources are in: [src/lib](https://github.com/Microsoft/TypeScript/tree/master/src/lib)
To build the library files, run
```Shell
jake lib
```
#### `src/lib/dom.generated.d.ts` and `src/lib/webworker.generated.d.ts`
These two files represent the DOM typings and are auto-generated. To make any modifications to them, please submit a PR to https://github.com/Microsoft/TSJS-lib-generator
## Running the Tests ## Running the Tests
To run all tests, invoke the `runtests` target using jake: To run all tests, invoke the `runtests` target using jake:

View file

@ -862,6 +862,7 @@ var tslintRuleDir = "scripts/tslint";
var tslintRules = ([ var tslintRules = ([
"nextLineRule", "nextLineRule",
"noNullRule", "noNullRule",
"preferConstRule",
"booleanTriviaRule", "booleanTriviaRule",
"typeOperatorSpacingRule" "typeOperatorSpacingRule"
]); ]);

4
lib/README.md Normal file
View file

@ -0,0 +1,4 @@
# Read this!
These files are not meant to be edited by hand.
If you need to make modifications, the respective files should be changed within the repository's top-level `src` directory.

View file

@ -0,0 +1,228 @@
/// <reference path="../../node_modules/tslint/typings/typescriptServices.d.ts" />
/// <reference path="../../node_modules/tslint/lib/tslint.d.ts" />
export class Rule extends Lint.Rules.AbstractRule {
public static FAILURE_STRING_FACTORY = (identifier: string) => `Identifier '${identifier}' never appears on the LHS of an assignment - use const instead of let for its declaration.`;
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(new PreferConstWalker(sourceFile, this.getOptions()));
}
}
function isBindingPattern(node: ts.Node): node is ts.BindingPattern {
return !!node && (node.kind === ts.SyntaxKind.ArrayBindingPattern || node.kind === ts.SyntaxKind.ObjectBindingPattern);
}
function walkUpBindingElementsAndPatterns(node: ts.Node): ts.Node {
while (node && (node.kind === ts.SyntaxKind.BindingElement || isBindingPattern(node))) {
node = node.parent;
}
return node;
}
function getCombinedNodeFlags(node: ts.Node): ts.NodeFlags {
node = walkUpBindingElementsAndPatterns(node);
let flags = node.flags;
if (node.kind === ts.SyntaxKind.VariableDeclaration) {
node = node.parent;
}
if (node && node.kind === ts.SyntaxKind.VariableDeclarationList) {
flags |= node.flags;
node = node.parent;
}
if (node && node.kind === ts.SyntaxKind.VariableStatement) {
flags |= node.flags;
}
return flags;
}
function isLet(node: ts.Node) {
return !!(getCombinedNodeFlags(node) & ts.NodeFlags.Let);
}
function isExported(node: ts.Node) {
return !!(getCombinedNodeFlags(node) & ts.NodeFlags.Export);
}
function isAssignmentOperator(token: ts.SyntaxKind): boolean {
return token >= ts.SyntaxKind.FirstAssignment && token <= ts.SyntaxKind.LastAssignment;
}
function isBindingLiteralExpression(node: ts.Node): node is (ts.ArrayLiteralExpression | ts.ObjectLiteralExpression) {
return (!!node) && (node.kind === ts.SyntaxKind.ObjectLiteralExpression || node.kind === ts.SyntaxKind.ArrayLiteralExpression);
}
interface DeclarationUsages {
declaration: ts.VariableDeclaration;
usages: number;
}
class PreferConstWalker extends Lint.RuleWalker {
private inScopeLetDeclarations: ts.Map<DeclarationUsages>[] = [];
private errors: Lint.RuleFailure[] = [];
private markAssignment(identifier: ts.Identifier) {
const name = identifier.text;
for (let i = this.inScopeLetDeclarations.length - 1; i >= 0; i--) {
const declarations = this.inScopeLetDeclarations[i];
if (declarations[name]) {
declarations[name].usages++;
break;
}
}
}
visitSourceFile(node: ts.SourceFile) {
super.visitSourceFile(node);
// Sort errors by position because tslint doesn't
this.errors.sort((a, b) => a.getStartPosition().getPosition() - b.getStartPosition().getPosition()).forEach(e => this.addFailure(e));
}
visitBinaryExpression(node: ts.BinaryExpression) {
if (isAssignmentOperator(node.operatorToken.kind)) {
this.visitLHSExpressions(node.left);
}
super.visitBinaryExpression(node);
}
private visitLHSExpressions(node: ts.Expression) {
while (node.kind === ts.SyntaxKind.ParenthesizedExpression) {
node = (node as ts.ParenthesizedExpression).expression;
}
if (node.kind === ts.SyntaxKind.Identifier) {
this.markAssignment(node as ts.Identifier);
}
else if (isBindingLiteralExpression(node)) {
this.visitBindingLiteralExpression(node as (ts.ArrayLiteralExpression | ts.ObjectLiteralExpression));
}
}
private visitBindingLiteralExpression(node: ts.ArrayLiteralExpression | ts.ObjectLiteralExpression) {
if (node.kind === ts.SyntaxKind.ObjectLiteralExpression) {
const pattern = node as ts.ObjectLiteralExpression;
for (const element of pattern.properties) {
if (element.name.kind === ts.SyntaxKind.Identifier) {
this.markAssignment(element.name as ts.Identifier)
}
else if (isBindingPattern(element.name)) {
this.visitBindingPatternIdentifiers(element.name as ts.BindingPattern);
}
}
}
else if (node.kind === ts.SyntaxKind.ArrayLiteralExpression) {
const pattern = node as ts.ArrayLiteralExpression;
for (const element of pattern.elements) {
this.visitLHSExpressions(element);
}
}
}
private visitBindingPatternIdentifiers(pattern: ts.BindingPattern) {
for (const element of pattern.elements) {
if (element.name.kind === ts.SyntaxKind.Identifier) {
this.markAssignment(element.name as ts.Identifier);
}
else {
this.visitBindingPatternIdentifiers(element.name as ts.BindingPattern);
}
}
}
visitPrefixUnaryExpression(node: ts.PrefixUnaryExpression) {
this.visitAnyUnaryExpression(node);
super.visitPrefixUnaryExpression(node);
}
visitPostfixUnaryExpression(node: ts.PostfixUnaryExpression) {
this.visitAnyUnaryExpression(node);
super.visitPostfixUnaryExpression(node);
}
private visitAnyUnaryExpression(node: ts.PrefixUnaryExpression | ts.PostfixUnaryExpression) {
if (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator === ts.SyntaxKind.MinusMinusToken) {
this.visitLHSExpressions(node.operand);
}
}
visitModuleDeclaration(node: ts.ModuleDeclaration) {
if (node.body.kind === ts.SyntaxKind.ModuleBlock) {
// For some reason module blocks are left out of the visit block traversal
this.visitBlock(node.body as ts.ModuleBlock);
}
super.visitModuleDeclaration(node);
}
visitForOfStatement(node: ts.ForOfStatement) {
this.visitAnyForStatement(node);
super.visitForOfStatement(node);
this.popDeclarations();
}
visitForInStatement(node: ts.ForInStatement) {
this.visitAnyForStatement(node);
super.visitForInStatement(node);
this.popDeclarations();
}
private visitAnyForStatement(node: ts.ForOfStatement | ts.ForInStatement) {
const names: ts.Map<DeclarationUsages> = {};
if (isLet(node.initializer)) {
if (node.initializer.kind === ts.SyntaxKind.VariableDeclarationList) {
this.collectLetIdentifiers(node.initializer as ts.VariableDeclarationList, names);
}
}
this.inScopeLetDeclarations.push(names);
}
private popDeclarations() {
const completed = this.inScopeLetDeclarations.pop();
for (const name in completed) {
if (Object.hasOwnProperty.call(completed, name)) {
const element = completed[name];
if (element.usages === 0) {
this.errors.push(this.createFailure(element.declaration.getStart(this.getSourceFile()), element.declaration.getWidth(this.getSourceFile()), Rule.FAILURE_STRING_FACTORY(name)));
}
}
}
}
visitBlock(node: ts.Block) {
const names: ts.Map<DeclarationUsages> = {};
for (const statement of node.statements) {
if (statement.kind === ts.SyntaxKind.VariableStatement) {
this.collectLetIdentifiers((statement as ts.VariableStatement).declarationList, names);
}
}
this.inScopeLetDeclarations.push(names);
super.visitBlock(node);
this.popDeclarations();
}
private collectLetIdentifiers(list: ts.VariableDeclarationList, ret: ts.Map<DeclarationUsages>) {
for (const node of list.declarations) {
if (isLet(node) && !isExported(node)) {
this.collectNameIdentifiers(node, node.name, ret);
}
}
}
private collectNameIdentifiers(value: ts.VariableDeclaration, node: ts.Identifier | ts.BindingPattern, table: ts.Map<DeclarationUsages>) {
if (node.kind === ts.SyntaxKind.Identifier) {
table[(node as ts.Identifier).text] = {declaration: value, usages: 0};
}
else {
this.collectBindingPatternIdentifiers(value, node as ts.BindingPattern, table);
}
}
private collectBindingPatternIdentifiers(value: ts.VariableDeclaration, pattern: ts.BindingPattern, table: ts.Map<DeclarationUsages>) {
for (const element of pattern.elements) {
this.collectNameIdentifiers(value, element.name, table);
}
}
}

View file

@ -95,7 +95,7 @@ namespace ts {
const binder = createBinder(); const binder = createBinder();
export function bindSourceFile(file: SourceFile, options: CompilerOptions) { export function bindSourceFile(file: SourceFile, options: CompilerOptions) {
let start = new Date().getTime(); const start = new Date().getTime();
binder(file, options); binder(file, options);
bindTime += new Date().getTime() - start; bindTime += new Date().getTime() - start;
} }
@ -187,7 +187,7 @@ namespace ts {
return `"${(<LiteralExpression>node.name).text}"`; return `"${(<LiteralExpression>node.name).text}"`;
} }
if (node.name.kind === SyntaxKind.ComputedPropertyName) { if (node.name.kind === SyntaxKind.ComputedPropertyName) {
let nameExpression = (<ComputedPropertyName>node.name).expression; const nameExpression = (<ComputedPropertyName>node.name).expression;
Debug.assert(isWellKnownSymbolSyntactically(nameExpression)); Debug.assert(isWellKnownSymbolSyntactically(nameExpression));
return getPropertyNameForKnownSymbolName((<PropertyAccessExpression>nameExpression).name.text); return getPropertyNameForKnownSymbolName((<PropertyAccessExpression>nameExpression).name.text);
} }
@ -229,9 +229,9 @@ namespace ts {
function declareSymbol(symbolTable: SymbolTable, parent: Symbol, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags): Symbol { function declareSymbol(symbolTable: SymbolTable, parent: Symbol, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags): Symbol {
Debug.assert(!hasDynamicName(node)); Debug.assert(!hasDynamicName(node));
let isDefaultExport = node.flags & NodeFlags.Default; const isDefaultExport = node.flags & NodeFlags.Default;
// The exported symbol for an export default function/class node is always named "default" // The exported symbol for an export default function/class node is always named "default"
let name = isDefaultExport && parent ? "default" : getDeclarationName(node); const name = isDefaultExport && parent ? "default" : getDeclarationName(node);
let symbol: Symbol; let symbol: Symbol;
if (name !== undefined) { if (name !== undefined) {
@ -298,7 +298,7 @@ namespace ts {
} }
function declareModuleMember(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags): Symbol { function declareModuleMember(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags): Symbol {
let hasExportModifier = getCombinedNodeFlags(node) & NodeFlags.Export; const hasExportModifier = getCombinedNodeFlags(node) & NodeFlags.Export;
if (symbolFlags & SymbolFlags.Alias) { if (symbolFlags & SymbolFlags.Alias) {
if (node.kind === SyntaxKind.ExportSpecifier || (node.kind === SyntaxKind.ImportEqualsDeclaration && hasExportModifier)) { if (node.kind === SyntaxKind.ExportSpecifier || (node.kind === SyntaxKind.ImportEqualsDeclaration && hasExportModifier)) {
return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes);
@ -320,11 +320,11 @@ namespace ts {
// but return the export symbol (by calling getExportSymbolOfValueSymbolIfExported). That way // but return the export symbol (by calling getExportSymbolOfValueSymbolIfExported). That way
// when the emitter comes back to it, it knows not to qualify the name if it was found in a containing scope. // when the emitter comes back to it, it knows not to qualify the name if it was found in a containing scope.
if (hasExportModifier || container.flags & NodeFlags.ExportContext) { if (hasExportModifier || container.flags & NodeFlags.ExportContext) {
let exportKind = const exportKind =
(symbolFlags & SymbolFlags.Value ? SymbolFlags.ExportValue : 0) | (symbolFlags & SymbolFlags.Value ? SymbolFlags.ExportValue : 0) |
(symbolFlags & SymbolFlags.Type ? SymbolFlags.ExportType : 0) | (symbolFlags & SymbolFlags.Type ? SymbolFlags.ExportType : 0) |
(symbolFlags & SymbolFlags.Namespace ? SymbolFlags.ExportNamespace : 0); (symbolFlags & SymbolFlags.Namespace ? SymbolFlags.ExportNamespace : 0);
let local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes); const local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes);
local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes);
node.localSymbol = local; node.localSymbol = local;
return local; return local;
@ -342,9 +342,9 @@ namespace ts {
// Before we recurse into a node's chilren, we first save the existing parent, container // Before we recurse into a node's chilren, we first save the existing parent, container
// and block-container. Then after we pop out of processing the children, we restore // and block-container. Then after we pop out of processing the children, we restore
// these saved values. // these saved values.
let saveParent = parent; const saveParent = parent;
let saveContainer = container; const saveContainer = container;
let savedBlockScopeContainer = blockScopeContainer; const savedBlockScopeContainer = blockScopeContainer;
// This node will now be set as the parent of all of its children as we recurse into them. // This node will now be set as the parent of all of its children as we recurse into them.
parent = node; parent = node;
@ -366,7 +366,7 @@ namespace ts {
// reusing a node from a previous compilation, that node may have had 'locals' created // reusing a node from a previous compilation, that node may have had 'locals' created
// for it. We must clear this so we don't accidently move any stale data forward from // for it. We must clear this so we don't accidently move any stale data forward from
// a previous compilation. // a previous compilation.
let containerFlags = getContainerFlags(node); const containerFlags = getContainerFlags(node);
if (containerFlags & ContainerFlags.IsContainer) { if (containerFlags & ContainerFlags.IsContainer) {
container = blockScopeContainer = node; container = blockScopeContainer = node;
@ -398,7 +398,7 @@ namespace ts {
seenThisKeyword = false; seenThisKeyword = false;
} }
let saveState = kind === SyntaxKind.SourceFile || kind === SyntaxKind.ModuleBlock || isFunctionLikeKind(kind); const saveState = kind === SyntaxKind.SourceFile || kind === SyntaxKind.ModuleBlock || isFunctionLikeKind(kind);
if (saveState) { if (saveState) {
savedReachabilityState = currentReachabilityState; savedReachabilityState = currentReachabilityState;
savedLabelStack = labelStack; savedLabelStack = labelStack;
@ -633,7 +633,7 @@ namespace ts {
function bindCaseBlock(n: CaseBlock): void { function bindCaseBlock(n: CaseBlock): void {
const startState = currentReachabilityState; const startState = currentReachabilityState;
for (let clause of n.clauses) { for (const clause of n.clauses) {
currentReachabilityState = startState; currentReachabilityState = startState;
bind(clause); bind(clause);
if (clause.statements.length && currentReachabilityState === Reachability.Reachable && options.noFallthroughCasesInSwitch) { if (clause.statements.length && currentReachabilityState === Reachability.Reachable && options.noFallthroughCasesInSwitch) {
@ -790,9 +790,9 @@ namespace ts {
} }
function hasExportDeclarations(node: ModuleDeclaration | SourceFile): boolean { function hasExportDeclarations(node: ModuleDeclaration | SourceFile): boolean {
let body = node.kind === SyntaxKind.SourceFile ? node : (<ModuleDeclaration>node).body; const body = node.kind === SyntaxKind.SourceFile ? node : (<ModuleDeclaration>node).body;
if (body.kind === SyntaxKind.SourceFile || body.kind === SyntaxKind.ModuleBlock) { if (body.kind === SyntaxKind.SourceFile || body.kind === SyntaxKind.ModuleBlock) {
for (let stat of (<Block>body).statements) { for (const stat of (<Block>body).statements) {
if (stat.kind === SyntaxKind.ExportDeclaration || stat.kind === SyntaxKind.ExportAssignment) { if (stat.kind === SyntaxKind.ExportDeclaration || stat.kind === SyntaxKind.ExportAssignment) {
return true; return true;
} }
@ -818,7 +818,7 @@ namespace ts {
declareSymbolAndAddToSymbolTable(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes); declareSymbolAndAddToSymbolTable(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes);
} }
else { else {
let state = getModuleInstanceState(node); const state = getModuleInstanceState(node);
if (state === ModuleInstanceState.NonInstantiated) { if (state === ModuleInstanceState.NonInstantiated) {
declareSymbolAndAddToSymbolTable(node, SymbolFlags.NamespaceModule, SymbolFlags.NamespaceModuleExcludes); declareSymbolAndAddToSymbolTable(node, SymbolFlags.NamespaceModule, SymbolFlags.NamespaceModuleExcludes);
} }
@ -830,7 +830,7 @@ namespace ts {
node.symbol.constEnumOnlyModule = false; node.symbol.constEnumOnlyModule = false;
} }
else { else {
let currentModuleIsConstEnumOnly = state === ModuleInstanceState.ConstEnumOnly; const currentModuleIsConstEnumOnly = state === ModuleInstanceState.ConstEnumOnly;
if (node.symbol.constEnumOnlyModule === undefined) { if (node.symbol.constEnumOnlyModule === undefined) {
// non-merged case - use the current state // non-merged case - use the current state
node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly; node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly;
@ -851,10 +851,10 @@ namespace ts {
// We do that by making an anonymous type literal symbol, and then setting the function // We do that by making an anonymous type literal symbol, and then setting the function
// symbol as its sole member. To the rest of the system, this symbol will be indistinguishable // symbol as its sole member. To the rest of the system, this symbol will be indistinguishable
// from an actual type literal symbol you would have gotten had you used the long form. // from an actual type literal symbol you would have gotten had you used the long form.
let symbol = createSymbol(SymbolFlags.Signature, getDeclarationName(node)); const symbol = createSymbol(SymbolFlags.Signature, getDeclarationName(node));
addDeclarationToSymbol(symbol, node, SymbolFlags.Signature); addDeclarationToSymbol(symbol, node, SymbolFlags.Signature);
let typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type"); const typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type");
addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral); addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral);
typeLiteralSymbol.members = { [symbol.name]: symbol }; typeLiteralSymbol.members = { [symbol.name]: symbol };
} }
@ -866,14 +866,14 @@ namespace ts {
} }
if (inStrictMode) { if (inStrictMode) {
let seen: Map<ElementKind> = {}; const seen: Map<ElementKind> = {};
for (let prop of node.properties) { for (const prop of node.properties) {
if (prop.name.kind !== SyntaxKind.Identifier) { if (prop.name.kind !== SyntaxKind.Identifier) {
continue; continue;
} }
let identifier = <Identifier>prop.name; const identifier = <Identifier>prop.name;
// ECMA-262 11.1.5 Object Initialiser // ECMA-262 11.1.5 Object Initialiser
// If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true
@ -883,18 +883,18 @@ namespace ts {
// c.IsAccessorDescriptor(previous) is true and IsDataDescriptor(propId.descriptor) is true. // c.IsAccessorDescriptor(previous) is true and IsDataDescriptor(propId.descriptor) is true.
// d.IsAccessorDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true // d.IsAccessorDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true
// and either both previous and propId.descriptor have[[Get]] fields or both previous and propId.descriptor have[[Set]] fields // and either both previous and propId.descriptor have[[Get]] fields or both previous and propId.descriptor have[[Set]] fields
let currentKind = prop.kind === SyntaxKind.PropertyAssignment || prop.kind === SyntaxKind.ShorthandPropertyAssignment || prop.kind === SyntaxKind.MethodDeclaration const currentKind = prop.kind === SyntaxKind.PropertyAssignment || prop.kind === SyntaxKind.ShorthandPropertyAssignment || prop.kind === SyntaxKind.MethodDeclaration
? ElementKind.Property ? ElementKind.Property
: ElementKind.Accessor; : ElementKind.Accessor;
let existingKind = seen[identifier.text]; const existingKind = seen[identifier.text];
if (!existingKind) { if (!existingKind) {
seen[identifier.text] = currentKind; seen[identifier.text] = currentKind;
continue; continue;
} }
if (currentKind === ElementKind.Property && existingKind === ElementKind.Property) { if (currentKind === ElementKind.Property && existingKind === ElementKind.Property) {
let span = getErrorSpanForNode(file, identifier); const span = getErrorSpanForNode(file, identifier);
file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length,
Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode)); Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode));
} }
@ -905,7 +905,7 @@ namespace ts {
} }
function bindAnonymousDeclaration(node: Declaration, symbolFlags: SymbolFlags, name: string) { function bindAnonymousDeclaration(node: Declaration, symbolFlags: SymbolFlags, name: string) {
let symbol = createSymbol(symbolFlags, name); const symbol = createSymbol(symbolFlags, name);
addDeclarationToSymbol(symbol, node, symbolFlags); addDeclarationToSymbol(symbol, node, symbolFlags);
} }
@ -984,7 +984,7 @@ namespace ts {
if (inStrictMode && node.expression.kind === SyntaxKind.Identifier) { if (inStrictMode && node.expression.kind === SyntaxKind.Identifier) {
// When a delete operator occurs within strict mode code, a SyntaxError is thrown if its // When a delete operator occurs within strict mode code, a SyntaxError is thrown if its
// UnaryExpression is a direct reference to a variable, function argument, or function name // UnaryExpression is a direct reference to a variable, function argument, or function name
let span = getErrorSpanForNode(file, node.expression); const span = getErrorSpanForNode(file, node.expression);
file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode)); file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode));
} }
} }
@ -996,11 +996,11 @@ namespace ts {
function checkStrictModeEvalOrArguments(contextNode: Node, name: Node) { function checkStrictModeEvalOrArguments(contextNode: Node, name: Node) {
if (name && name.kind === SyntaxKind.Identifier) { if (name && name.kind === SyntaxKind.Identifier) {
let identifier = <Identifier>name; const identifier = <Identifier>name;
if (isEvalOrArgumentsIdentifier(identifier)) { if (isEvalOrArgumentsIdentifier(identifier)) {
// We check first if the name is inside class declaration or class expression; if so give explicit message // We check first if the name is inside class declaration or class expression; if so give explicit message
// otherwise report generic error message. // otherwise report generic error message.
let span = getErrorSpanForNode(file, name); const span = getErrorSpanForNode(file, name);
file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length,
getStrictModeEvalOrArgumentsMessage(contextNode), identifier.text)); getStrictModeEvalOrArgumentsMessage(contextNode), identifier.text));
} }
@ -1061,7 +1061,7 @@ namespace ts {
} }
function errorOnFirstToken(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any) { function errorOnFirstToken(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any) {
let span = getSpanOfTokenAtPosition(file, node.pos); const span = getSpanOfTokenAtPosition(file, node.pos);
file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2)); file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2));
} }
@ -1076,7 +1076,7 @@ namespace ts {
node.parent = parent; node.parent = parent;
let savedInStrictMode = inStrictMode; const savedInStrictMode = inStrictMode;
if (!savedInStrictMode) { if (!savedInStrictMode) {
updateStrictMode(node); updateStrictMode(node);
} }
@ -1122,7 +1122,7 @@ namespace ts {
} }
function updateStrictModeStatementList(statements: NodeArray<Statement>) { function updateStrictModeStatementList(statements: NodeArray<Statement>) {
for (let statement of statements) { for (const statement of statements) {
if (!isPrologueDirective(statement)) { if (!isPrologueDirective(statement)) {
return; return;
} }
@ -1136,7 +1136,7 @@ namespace ts {
/// Should be called only on prologue directives (isPrologueDirective(node) should be true) /// Should be called only on prologue directives (isPrologueDirective(node) should be true)
function isUseStrictPrologueDirective(node: ExpressionStatement): boolean { function isUseStrictPrologueDirective(node: ExpressionStatement): boolean {
let nodeText = getTextOfNodeFromSourceText(file.text, node.expression); const nodeText = getTextOfNodeFromSourceText(file.text, node.expression);
// Note: the node text must be exactly "use strict" or 'use strict'. It is not ok for the // Note: the node text must be exactly "use strict" or 'use strict'. It is not ok for the
// string to contain unicode escapes (as per ES5). // string to contain unicode escapes (as per ES5).
@ -1211,7 +1211,7 @@ namespace ts {
case SyntaxKind.FunctionExpression: case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction: case SyntaxKind.ArrowFunction:
checkStrictModeFunctionName(<FunctionExpression>node); checkStrictModeFunctionName(<FunctionExpression>node);
let bindingName = (<FunctionExpression>node).name ? (<FunctionExpression>node).name.text : "__function"; const bindingName = (<FunctionExpression>node).name ? (<FunctionExpression>node).name.text : "__function";
return bindAnonymousDeclaration(<FunctionExpression>node, SymbolFlags.Function, bindingName); return bindAnonymousDeclaration(<FunctionExpression>node, SymbolFlags.Function, bindingName);
case SyntaxKind.ClassExpression: case SyntaxKind.ClassExpression:
case SyntaxKind.ClassDeclaration: case SyntaxKind.ClassDeclaration:
@ -1284,7 +1284,7 @@ namespace ts {
bindBlockScopedDeclaration(node, SymbolFlags.Class, SymbolFlags.ClassExcludes); bindBlockScopedDeclaration(node, SymbolFlags.Class, SymbolFlags.ClassExcludes);
} }
else { else {
let bindingName = node.name ? node.name.text : "__class"; const bindingName = node.name ? node.name.text : "__class";
bindAnonymousDeclaration(node, SymbolFlags.Class, bindingName); bindAnonymousDeclaration(node, SymbolFlags.Class, bindingName);
// Add name of class expression into the map for semantic classifier // Add name of class expression into the map for semantic classifier
if (node.name) { if (node.name) {
@ -1292,7 +1292,7 @@ namespace ts {
} }
} }
let symbol = node.symbol; const symbol = node.symbol;
// TypeScript 1.0 spec (April 2014): 8.4 // TypeScript 1.0 spec (April 2014): 8.4
// Every class automatically contains a static property member named 'prototype', the // Every class automatically contains a static property member named 'prototype', the
@ -1303,7 +1303,7 @@ namespace ts {
// Note: we check for this here because this class may be merging into a module. The // Note: we check for this here because this class may be merging into a module. The
// module might have an exported variable called 'prototype'. We can't allow that as // module might have an exported variable called 'prototype'. We can't allow that as
// that would clash with the built-in 'prototype' for the class. // that would clash with the built-in 'prototype' for the class.
let prototypeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Prototype, "prototype"); const prototypeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Prototype, "prototype");
if (hasProperty(symbol.exports, prototypeSymbol.name)) { if (hasProperty(symbol.exports, prototypeSymbol.name)) {
if (node.name) { if (node.name) {
node.name.parent = node; node.name.parent = node;
@ -1368,7 +1368,7 @@ namespace ts {
node.parent.kind === SyntaxKind.Constructor && node.parent.kind === SyntaxKind.Constructor &&
isClassLike(node.parent.parent)) { isClassLike(node.parent.parent)) {
let classDeclaration = <ClassLikeDeclaration>node.parent.parent; const classDeclaration = <ClassLikeDeclaration>node.parent.parent;
declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes); declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
} }
} }
@ -1394,13 +1394,13 @@ namespace ts {
function pushImplicitLabel(): number { function pushImplicitLabel(): number {
initializeReachabilityStateIfNecessary(); initializeReachabilityStateIfNecessary();
let index = labelStack.push(Reachability.Unintialized) - 1; const index = labelStack.push(Reachability.Unintialized) - 1;
implicitLabels.push(index); implicitLabels.push(index);
return index; return index;
} }
function popNamedLabel(label: Identifier, outerState: Reachability): void { function popNamedLabel(label: Identifier, outerState: Reachability): void {
let index = labelIndexMap[label.text]; const index = labelIndexMap[label.text];
Debug.assert(index !== undefined); Debug.assert(index !== undefined);
Debug.assert(labelStack.length == index + 1); Debug.assert(labelStack.length == index + 1);
@ -1414,7 +1414,7 @@ namespace ts {
Debug.assert(false, `Label stack: ${labelStack.length}, index:${implicitLabelIndex}`); Debug.assert(false, `Label stack: ${labelStack.length}, index:${implicitLabelIndex}`);
} }
let i = implicitLabels.pop(); const i = implicitLabels.pop();
if (implicitLabelIndex !== i) { if (implicitLabelIndex !== i) {
Debug.assert(false, `i: ${i}, index: ${implicitLabelIndex}`); Debug.assert(false, `i: ${i}, index: ${implicitLabelIndex}`);
@ -1453,8 +1453,8 @@ namespace ts {
switch (currentReachabilityState) { switch (currentReachabilityState) {
case Reachability.Unreachable: case Reachability.Unreachable:
const reportError = const reportError =
// report error on all statements // report error on all statements except empty ones
isStatement(node) || (isStatement(node) && node.kind !== SyntaxKind.EmptyStatement) ||
// report error on class declarations // report error on class declarations
node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassDeclaration ||
// report error on instantiated modules or const-enums only modules if preserveConstEnums is set // report error on instantiated modules or const-enums only modules if preserveConstEnums is set

File diff suppressed because it is too large Load diff

View file

@ -295,8 +295,8 @@ namespace ts {
return optionNameMapCache; return optionNameMapCache;
} }
let optionNameMap: Map<CommandLineOption> = {}; const optionNameMap: Map<CommandLineOption> = {};
let shortOptionNames: Map<string> = {}; const shortOptionNames: Map<string> = {};
forEach(optionDeclarations, option => { forEach(optionDeclarations, option => {
optionNameMap[option.name.toLowerCase()] = option; optionNameMap[option.name.toLowerCase()] = option;
if (option.shortName) { if (option.shortName) {
@ -309,10 +309,10 @@ namespace ts {
} }
export function parseCommandLine(commandLine: string[], readFile?: (path: string) => string): ParsedCommandLine { export function parseCommandLine(commandLine: string[], readFile?: (path: string) => string): ParsedCommandLine {
let options: CompilerOptions = {}; const options: CompilerOptions = {};
let fileNames: string[] = []; const fileNames: string[] = [];
let errors: Diagnostic[] = []; const errors: Diagnostic[] = [];
let { optionNameMap, shortOptionNames } = getOptionNameMap(); const { optionNameMap, shortOptionNames } = getOptionNameMap();
parseStrings(commandLine); parseStrings(commandLine);
return { return {
@ -337,7 +337,7 @@ namespace ts {
} }
if (hasProperty(optionNameMap, s)) { if (hasProperty(optionNameMap, s)) {
let opt = optionNameMap[s]; const opt = optionNameMap[s];
// Check to see if no argument was provided (e.g. "--locale" is the last command-line argument). // Check to see if no argument was provided (e.g. "--locale" is the last command-line argument).
if (!args[i] && opt.type !== "boolean") { if (!args[i] && opt.type !== "boolean") {
@ -377,19 +377,19 @@ namespace ts {
} }
function parseResponseFile(fileName: string) { function parseResponseFile(fileName: string) {
let text = readFile ? readFile(fileName) : sys.readFile(fileName); const text = readFile ? readFile(fileName) : sys.readFile(fileName);
if (!text) { if (!text) {
errors.push(createCompilerDiagnostic(Diagnostics.File_0_not_found, fileName)); errors.push(createCompilerDiagnostic(Diagnostics.File_0_not_found, fileName));
return; return;
} }
let args: string[] = []; const args: string[] = [];
let pos = 0; let pos = 0;
while (true) { while (true) {
while (pos < text.length && text.charCodeAt(pos) <= CharacterCodes.space) pos++; while (pos < text.length && text.charCodeAt(pos) <= CharacterCodes.space) pos++;
if (pos >= text.length) break; if (pos >= text.length) break;
let start = pos; const start = pos;
if (text.charCodeAt(start) === CharacterCodes.doubleQuote) { if (text.charCodeAt(start) === CharacterCodes.doubleQuote) {
pos++; pos++;
while (pos < text.length && text.charCodeAt(pos) !== CharacterCodes.doubleQuote) pos++; while (pos < text.length && text.charCodeAt(pos) !== CharacterCodes.doubleQuote) pos++;
@ -432,7 +432,7 @@ namespace ts {
*/ */
export function parseConfigFileTextToJson(fileName: string, jsonText: string): { config?: any; error?: Diagnostic } { export function parseConfigFileTextToJson(fileName: string, jsonText: string): { config?: any; error?: Diagnostic } {
try { try {
let jsonTextWithoutComments = removeComments(jsonText); const jsonTextWithoutComments = removeComments(jsonText);
return { config: /\S/.test(jsonTextWithoutComments) ? JSON.parse(jsonTextWithoutComments) : {} }; return { config: /\S/.test(jsonTextWithoutComments) ? JSON.parse(jsonTextWithoutComments) : {} };
} }
catch (e) { catch (e) {
@ -449,7 +449,7 @@ namespace ts {
*/ */
function removeComments(jsonText: string): string { function removeComments(jsonText: string): string {
let output = ""; let output = "";
let scanner = createScanner(ScriptTarget.ES5, /* skipTrivia */ false, LanguageVariant.Standard, jsonText); const scanner = createScanner(ScriptTarget.ES5, /* skipTrivia */ false, LanguageVariant.Standard, jsonText);
let token: SyntaxKind; let token: SyntaxKind;
while ((token = scanner.scan()) !== SyntaxKind.EndOfFileToken) { while ((token = scanner.scan()) !== SyntaxKind.EndOfFileToken) {
switch (token) { switch (token) {
@ -475,7 +475,7 @@ namespace ts {
* file to. e.g. outDir * file to. e.g. outDir
*/ */
export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string): ParsedCommandLine { export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string): ParsedCommandLine {
let { options, errors } = convertCompilerOptionsFromJson(json["compilerOptions"], basePath); const { options, errors } = convertCompilerOptionsFromJson(json["compilerOptions"], basePath);
return { return {
options, options,
@ -494,12 +494,12 @@ namespace ts {
} }
} }
else { else {
let exclude = json["exclude"] instanceof Array ? map(<string[]>json["exclude"], normalizeSlashes) : undefined; const exclude = json["exclude"] instanceof Array ? map(<string[]>json["exclude"], normalizeSlashes) : undefined;
let sysFiles = host.readDirectory(basePath, ".ts", exclude).concat(host.readDirectory(basePath, ".tsx", exclude)); const sysFiles = host.readDirectory(basePath, ".ts", exclude).concat(host.readDirectory(basePath, ".tsx", exclude));
for (let i = 0; i < sysFiles.length; i++) { for (let i = 0; i < sysFiles.length; i++) {
let name = sysFiles[i]; const name = sysFiles[i];
if (fileExtensionIs(name, ".d.ts")) { if (fileExtensionIs(name, ".d.ts")) {
let baseName = name.substr(0, name.length - ".d.ts".length); const baseName = name.substr(0, name.length - ".d.ts".length);
if (!contains(sysFiles, baseName + ".tsx") && !contains(sysFiles, baseName + ".ts")) { if (!contains(sysFiles, baseName + ".tsx") && !contains(sysFiles, baseName + ".ts")) {
fileNames.push(name); fileNames.push(name);
} }
@ -519,24 +519,24 @@ namespace ts {
} }
export function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string): { options: CompilerOptions, errors: Diagnostic[] } { export function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string): { options: CompilerOptions, errors: Diagnostic[] } {
let options: CompilerOptions = {}; const options: CompilerOptions = {};
let errors: Diagnostic[] = []; const errors: Diagnostic[] = [];
if (!jsonOptions) { if (!jsonOptions) {
return { options, errors }; return { options, errors };
} }
let optionNameMap = arrayToMap(optionDeclarations, opt => opt.name); const optionNameMap = arrayToMap(optionDeclarations, opt => opt.name);
for (let id in jsonOptions) { for (const id in jsonOptions) {
if (hasProperty(optionNameMap, id)) { if (hasProperty(optionNameMap, id)) {
let opt = optionNameMap[id]; const opt = optionNameMap[id];
let optType = opt.type; const optType = opt.type;
let value = jsonOptions[id]; let value = jsonOptions[id];
let expectedType = typeof optType === "string" ? optType : "string"; const expectedType = typeof optType === "string" ? optType : "string";
if (typeof value === expectedType) { if (typeof value === expectedType) {
if (typeof optType !== "string") { if (typeof optType !== "string") {
let key = value.toLowerCase(); const key = value.toLowerCase();
if (hasProperty(optType, key)) { if (hasProperty(optType, key)) {
value = optType[key]; value = optType[key];
} }

View file

@ -29,7 +29,7 @@ namespace ts {
}; };
function forEachValueInMap(f: (key: Path, value: T) => void) { function forEachValueInMap(f: (key: Path, value: T) => void) {
for (let key in files) { for (const key in files) {
f(<Path>key, files[key]); f(<Path>key, files[key]);
} }
} }
@ -84,7 +84,7 @@ namespace ts {
export function forEach<T, U>(array: T[], callback: (element: T, index: number) => U): U { export function forEach<T, U>(array: T[], callback: (element: T, index: number) => U): U {
if (array) { if (array) {
for (let i = 0, len = array.length; i < len; i++) { for (let i = 0, len = array.length; i < len; i++) {
let result = callback(array[i], i); const result = callback(array[i], i);
if (result) { if (result) {
return result; return result;
} }
@ -95,7 +95,7 @@ namespace ts {
export function contains<T>(array: T[], value: T): boolean { export function contains<T>(array: T[], value: T): boolean {
if (array) { if (array) {
for (let v of array) { for (const v of array) {
if (v === value) { if (v === value) {
return true; return true;
} }
@ -118,7 +118,7 @@ namespace ts {
export function countWhere<T>(array: T[], predicate: (x: T) => boolean): number { export function countWhere<T>(array: T[], predicate: (x: T) => boolean): number {
let count = 0; let count = 0;
if (array) { if (array) {
for (let v of array) { for (const v of array) {
if (predicate(v)) { if (predicate(v)) {
count++; count++;
} }
@ -131,7 +131,7 @@ namespace ts {
let result: T[]; let result: T[];
if (array) { if (array) {
result = []; result = [];
for (let item of array) { for (const item of array) {
if (f(item)) { if (f(item)) {
result.push(item); result.push(item);
} }
@ -144,7 +144,7 @@ namespace ts {
let result: U[]; let result: U[];
if (array) { if (array) {
result = []; result = [];
for (let v of array) { for (const v of array) {
result.push(f(v)); result.push(f(v));
} }
} }
@ -162,7 +162,7 @@ namespace ts {
let result: T[]; let result: T[];
if (array) { if (array) {
result = []; result = [];
for (let item of array) { for (const item of array) {
if (!contains(result, item)) { if (!contains(result, item)) {
result.push(item); result.push(item);
} }
@ -173,7 +173,7 @@ namespace ts {
export function sum(array: any[], prop: string): number { export function sum(array: any[], prop: string): number {
let result = 0; let result = 0;
for (let v of array) { for (const v of array) {
result += v[prop]; result += v[prop];
} }
return result; return result;
@ -181,7 +181,7 @@ namespace ts {
export function addRange<T>(to: T[], from: T[]): void { export function addRange<T>(to: T[], from: T[]): void {
if (to && from) { if (to && from) {
for (let v of from) { for (const v of from) {
to.push(v); to.push(v);
} }
} }
@ -220,8 +220,8 @@ namespace ts {
let high = array.length - 1; let high = array.length - 1;
while (low <= high) { while (low <= high) {
let middle = low + ((high - low) >> 1); const middle = low + ((high - low) >> 1);
let midValue = array[middle]; const midValue = array[middle];
if (midValue === value) { if (midValue === value) {
return middle; return middle;
@ -270,7 +270,7 @@ namespace ts {
return initial; return initial;
} }
let hasOwnProperty = Object.prototype.hasOwnProperty; const hasOwnProperty = Object.prototype.hasOwnProperty;
export function hasProperty<T>(map: Map<T>, key: string): boolean { export function hasProperty<T>(map: Map<T>, key: string): boolean {
return hasOwnProperty.call(map, key); return hasOwnProperty.call(map, key);
@ -281,7 +281,7 @@ namespace ts {
} }
export function isEmpty<T>(map: Map<T>) { export function isEmpty<T>(map: Map<T>) {
for (let id in map) { for (const id in map) {
if (hasProperty(map, id)) { if (hasProperty(map, id)) {
return false; return false;
} }
@ -290,19 +290,19 @@ namespace ts {
} }
export function clone<T>(object: T): T { export function clone<T>(object: T): T {
let result: any = {}; const result: any = {};
for (let id in object) { for (const id in object) {
result[id] = (<any>object)[id]; result[id] = (<any>object)[id];
} }
return <T>result; return <T>result;
} }
export function extend<T1, T2>(first: Map<T1>, second: Map<T2>): Map<T1 & T2> { export function extend<T1, T2>(first: Map<T1>, second: Map<T2>): Map<T1 & T2> {
let result: Map<T1 & T2> = {}; const result: Map<T1 & T2> = {};
for (let id in first) { for (const id in first) {
(result as any)[id] = first[id]; (result as any)[id] = first[id];
} }
for (let id in second) { for (const id in second) {
if (!hasProperty(result, id)) { if (!hasProperty(result, id)) {
(result as any)[id] = second[id]; (result as any)[id] = second[id];
} }
@ -312,7 +312,7 @@ namespace ts {
export function forEachValue<T, U>(map: Map<T>, callback: (value: T) => U): U { export function forEachValue<T, U>(map: Map<T>, callback: (value: T) => U): U {
let result: U; let result: U;
for (let id in map) { for (const id in map) {
if (result = callback(map[id])) break; if (result = callback(map[id])) break;
} }
return result; return result;
@ -320,7 +320,7 @@ namespace ts {
export function forEachKey<T, U>(map: Map<T>, callback: (key: string) => U): U { export function forEachKey<T, U>(map: Map<T>, callback: (key: string) => U): U {
let result: U; let result: U;
for (let id in map) { for (const id in map) {
if (result = callback(id)) break; if (result = callback(id)) break;
} }
return result; return result;
@ -331,7 +331,7 @@ namespace ts {
} }
export function copyMap<T>(source: Map<T>, target: Map<T>): void { export function copyMap<T>(source: Map<T>, target: Map<T>): void {
for (let p in source) { for (const p in source) {
target[p] = source[p]; target[p] = source[p];
} }
} }
@ -347,7 +347,7 @@ namespace ts {
* index in the array will be the one associated with the produced key. * index in the array will be the one associated with the produced key.
*/ */
export function arrayToMap<T>(array: T[], makeKey: (value: T) => string): Map<T> { export function arrayToMap<T>(array: T[], makeKey: (value: T) => string): Map<T> {
let result: Map<T> = {}; const result: Map<T> = {};
forEach(array, value => { forEach(array, value => {
result[makeKey(value)] = value; result[makeKey(value)] = value;
@ -383,7 +383,7 @@ namespace ts {
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: any[]): Diagnostic; export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: any[]): Diagnostic;
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage): Diagnostic { export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage): Diagnostic {
let end = start + length; const end = start + length;
Debug.assert(start >= 0, "start must be non-negative, is " + start); Debug.assert(start >= 0, "start must be non-negative, is " + start);
Debug.assert(length >= 0, "length must be non-negative, is " + length); Debug.assert(length >= 0, "length must be non-negative, is " + length);
@ -479,10 +479,10 @@ namespace ts {
function compareMessageText(text1: string | DiagnosticMessageChain, text2: string | DiagnosticMessageChain): Comparison { function compareMessageText(text1: string | DiagnosticMessageChain, text2: string | DiagnosticMessageChain): Comparison {
while (text1 && text2) { while (text1 && text2) {
// We still have both chains. // We still have both chains.
let string1 = typeof text1 === "string" ? text1 : text1.messageText; const string1 = typeof text1 === "string" ? text1 : text1.messageText;
let string2 = typeof text2 === "string" ? text2 : text2.messageText; const string2 = typeof text2 === "string" ? text2 : text2.messageText;
let res = compareValues(string1, string2); const res = compareValues(string1, string2);
if (res) { if (res) {
return res; return res;
} }
@ -509,11 +509,11 @@ namespace ts {
return diagnostics; return diagnostics;
} }
let newDiagnostics = [diagnostics[0]]; const newDiagnostics = [diagnostics[0]];
let previousDiagnostic = diagnostics[0]; let previousDiagnostic = diagnostics[0];
for (let i = 1; i < diagnostics.length; i++) { for (let i = 1; i < diagnostics.length; i++) {
let currentDiagnostic = diagnostics[i]; const currentDiagnostic = diagnostics[i];
let isDupe = compareDiagnostics(currentDiagnostic, previousDiagnostic) === Comparison.EqualTo; const isDupe = compareDiagnostics(currentDiagnostic, previousDiagnostic) === Comparison.EqualTo;
if (!isDupe) { if (!isDupe) {
newDiagnostics.push(currentDiagnostic); newDiagnostics.push(currentDiagnostic);
previousDiagnostic = currentDiagnostic; previousDiagnostic = currentDiagnostic;
@ -531,9 +531,9 @@ namespace ts {
export function getRootLength(path: string): number { export function getRootLength(path: string): number {
if (path.charCodeAt(0) === CharacterCodes.slash) { if (path.charCodeAt(0) === CharacterCodes.slash) {
if (path.charCodeAt(1) !== CharacterCodes.slash) return 1; if (path.charCodeAt(1) !== CharacterCodes.slash) return 1;
let p1 = path.indexOf("/", 2); const p1 = path.indexOf("/", 2);
if (p1 < 0) return 2; if (p1 < 0) return 2;
let p2 = path.indexOf("/", p1 + 1); const p2 = path.indexOf("/", p1 + 1);
if (p2 < 0) return p1 + 1; if (p2 < 0) return p1 + 1;
return p2 + 1; return p2 + 1;
} }
@ -549,7 +549,7 @@ namespace ts {
if (path.lastIndexOf("file:///", 0) === 0) { if (path.lastIndexOf("file:///", 0) === 0) {
return "file:///".length; return "file:///".length;
} }
let idx = path.indexOf("://"); const idx = path.indexOf("://");
if (idx !== -1) { if (idx !== -1) {
return idx + "://".length; return idx + "://".length;
} }
@ -558,9 +558,9 @@ namespace ts {
export let directorySeparator = "/"; export let directorySeparator = "/";
function getNormalizedParts(normalizedSlashedPath: string, rootLength: number) { function getNormalizedParts(normalizedSlashedPath: string, rootLength: number) {
let parts = normalizedSlashedPath.substr(rootLength).split(directorySeparator); const parts = normalizedSlashedPath.substr(rootLength).split(directorySeparator);
let normalized: string[] = []; const normalized: string[] = [];
for (let part of parts) { for (const part of parts) {
if (part !== ".") { if (part !== ".") {
if (part === ".." && normalized.length > 0 && lastOrUndefined(normalized) !== "..") { if (part === ".." && normalized.length > 0 && lastOrUndefined(normalized) !== "..") {
normalized.pop(); normalized.pop();
@ -580,8 +580,8 @@ namespace ts {
export function normalizePath(path: string): string { export function normalizePath(path: string): string {
path = normalizeSlashes(path); path = normalizeSlashes(path);
let rootLength = getRootLength(path); const rootLength = getRootLength(path);
let normalized = getNormalizedParts(path, rootLength); const normalized = getNormalizedParts(path, rootLength);
return path.substr(0, rootLength) + normalized.join(directorySeparator); return path.substr(0, rootLength) + normalized.join(directorySeparator);
} }
@ -598,7 +598,7 @@ namespace ts {
} }
function normalizedPathComponents(path: string, rootLength: number) { function normalizedPathComponents(path: string, rootLength: number) {
let normalizedParts = getNormalizedParts(path, rootLength); const normalizedParts = getNormalizedParts(path, rootLength);
return [path.substr(0, rootLength)].concat(normalizedParts); return [path.substr(0, rootLength)].concat(normalizedParts);
} }
@ -629,7 +629,7 @@ namespace ts {
// In this example the root is: http://www.website.com/ // In this example the root is: http://www.website.com/
// normalized path components should be ["http://www.website.com/", "folder1", "folder2"] // normalized path components should be ["http://www.website.com/", "folder1", "folder2"]
let urlLength = url.length; const urlLength = url.length;
// Initial root length is http:// part // Initial root length is http:// part
let rootLength = url.indexOf("://") + "://".length; let rootLength = url.indexOf("://") + "://".length;
while (rootLength < urlLength) { while (rootLength < urlLength) {
@ -650,7 +650,7 @@ namespace ts {
} }
// Find the index of "/" after website.com so the root can be http://www.website.com/ (from existing http://) // Find the index of "/" after website.com so the root can be http://www.website.com/ (from existing http://)
let indexOfNextSlash = url.indexOf(directorySeparator, rootLength); const indexOfNextSlash = url.indexOf(directorySeparator, rootLength);
if (indexOfNextSlash !== -1) { if (indexOfNextSlash !== -1) {
// Found the "/" after the website.com so the root is length of http://www.website.com/ // Found the "/" after the website.com so the root is length of http://www.website.com/
// and get components afetr the root normally like any other folder components // and get components afetr the root normally like any other folder components
@ -676,8 +676,8 @@ namespace ts {
} }
export function getRelativePathToDirectoryOrUrl(directoryPathOrUrl: string, relativeOrAbsolutePath: string, currentDirectory: string, getCanonicalFileName: (fileName: string) => string, isAbsolutePathAnUrl: boolean) { export function getRelativePathToDirectoryOrUrl(directoryPathOrUrl: string, relativeOrAbsolutePath: string, currentDirectory: string, getCanonicalFileName: (fileName: string) => string, isAbsolutePathAnUrl: boolean) {
let pathComponents = getNormalizedPathOrUrlComponents(relativeOrAbsolutePath, currentDirectory); const pathComponents = getNormalizedPathOrUrlComponents(relativeOrAbsolutePath, currentDirectory);
let directoryComponents = getNormalizedPathOrUrlComponents(directoryPathOrUrl, currentDirectory); const directoryComponents = getNormalizedPathOrUrlComponents(directoryPathOrUrl, currentDirectory);
if (directoryComponents.length > 1 && lastOrUndefined(directoryComponents) === "") { if (directoryComponents.length > 1 && lastOrUndefined(directoryComponents) === "") {
// If the directory path given was of type test/cases/ then we really need components of directory to be only till its name // If the directory path given was of type test/cases/ then we really need components of directory to be only till its name
// that is ["test", "cases", ""] needs to be actually ["test", "cases"] // that is ["test", "cases", ""] needs to be actually ["test", "cases"]
@ -694,7 +694,7 @@ namespace ts {
// Get the relative path // Get the relative path
if (joinStartIndex) { if (joinStartIndex) {
let relativePath = ""; let relativePath = "";
let relativePathComponents = pathComponents.slice(joinStartIndex, pathComponents.length); const relativePathComponents = pathComponents.slice(joinStartIndex, pathComponents.length);
for (; joinStartIndex < directoryComponents.length; joinStartIndex++) { for (; joinStartIndex < directoryComponents.length; joinStartIndex++) {
if (directoryComponents[joinStartIndex] !== "") { if (directoryComponents[joinStartIndex] !== "") {
relativePath = relativePath + ".." + directorySeparator; relativePath = relativePath + ".." + directorySeparator;
@ -717,7 +717,7 @@ namespace ts {
if (!path) { if (!path) {
return undefined; return undefined;
} }
let i = path.lastIndexOf(directorySeparator); const i = path.lastIndexOf(directorySeparator);
return i < 0 ? path : path.substring(i + 1); return i < 0 ? path : path.substring(i + 1);
} }
@ -730,8 +730,8 @@ namespace ts {
} }
export function fileExtensionIs(path: string, extension: string): boolean { export function fileExtensionIs(path: string, extension: string): boolean {
let pathLen = path.length; const pathLen = path.length;
let extLen = extension.length; const extLen = extension.length;
return pathLen > extLen && path.substr(pathLen - extLen, extLen) === extension; return pathLen > extLen && path.substr(pathLen - extLen, extLen) === extension;
} }
@ -749,7 +749,7 @@ namespace ts {
export function isSupportedSourceFileName(fileName: string) { export function isSupportedSourceFileName(fileName: string) {
if (!fileName) { return false; } if (!fileName) { return false; }
for (let extension of supportedExtensions) { for (const extension of supportedExtensions) {
if (fileExtensionIs(fileName, extension)) { if (fileExtensionIs(fileName, extension)) {
return true; return true;
} }
@ -759,7 +759,7 @@ namespace ts {
const extensionsToRemove = [".d.ts", ".ts", ".js", ".tsx", ".jsx"]; const extensionsToRemove = [".d.ts", ".ts", ".js", ".tsx", ".jsx"];
export function removeFileExtension(path: string): string { export function removeFileExtension(path: string): string {
for (let ext of extensionsToRemove) { for (const ext of extensionsToRemove) {
if (fileExtensionIs(path, ext)) { if (fileExtensionIs(path, ext)) {
return path.substr(0, path.length - ext.length); return path.substr(0, path.length - ext.length);
} }
@ -767,9 +767,9 @@ namespace ts {
return path; return path;
} }
let backslashOrDoubleQuote = /[\"\\]/g; const backslashOrDoubleQuote = /[\"\\]/g;
let escapedCharsRegExp = /[\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g; const escapedCharsRegExp = /[\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
let escapedCharsMap: Map<string> = { const escapedCharsMap: Map<string> = {
"\0": "\\0", "\0": "\\0",
"\t": "\\t", "\t": "\\t",
"\v": "\\v", "\v": "\\v",
@ -785,7 +785,8 @@ namespace ts {
}; };
export interface ObjectAllocator { export interface ObjectAllocator {
getNodeConstructor(kind: SyntaxKind): new (pos?: number, end?: number) => Node; getNodeConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => Node;
getSourceFileConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => SourceFile;
getSymbolConstructor(): new (flags: SymbolFlags, name: string) => Symbol; getSymbolConstructor(): new (flags: SymbolFlags, name: string) => Symbol;
getTypeConstructor(): new (checker: TypeChecker, flags: TypeFlags) => Type; getTypeConstructor(): new (checker: TypeChecker, flags: TypeFlags) => Type;
getSignatureConstructor(): new (checker: TypeChecker) => Signature; getSignatureConstructor(): new (checker: TypeChecker) => Signature;
@ -804,17 +805,17 @@ namespace ts {
function Signature(checker: TypeChecker) { function Signature(checker: TypeChecker) {
} }
export let objectAllocator: ObjectAllocator = { function Node(kind: SyntaxKind, pos: number, end: number) {
getNodeConstructor: kind => { this.kind = kind;
function Node(pos: number, end: number) {
this.pos = pos; this.pos = pos;
this.end = end; this.end = end;
this.flags = NodeFlags.None; this.flags = NodeFlags.None;
this.parent = undefined; this.parent = undefined;
} }
Node.prototype = { kind };
return <any>Node; export let objectAllocator: ObjectAllocator = {
}, getNodeConstructor: () => <any>Node,
getSourceFileConstructor: () => <any>Node,
getSymbolConstructor: () => <any>Symbol, getSymbolConstructor: () => <any>Symbol,
getTypeConstructor: () => <any>Type, getTypeConstructor: () => <any>Type,
getSignatureConstructor: () => <any>Signature getSignatureConstructor: () => <any>Signature
@ -828,7 +829,7 @@ namespace ts {
} }
export namespace Debug { export namespace Debug {
let currentAssertionLevel = AssertionLevel.None; const currentAssertionLevel = AssertionLevel.None;
export function shouldAssert(level: AssertionLevel): boolean { export function shouldAssert(level: AssertionLevel): boolean {
return currentAssertionLevel >= level; return currentAssertionLevel >= level;
@ -851,8 +852,8 @@ namespace ts {
} }
export function copyListRemovingItem<T>(item: T, list: T[]) { export function copyListRemovingItem<T>(item: T, list: T[]) {
let copiedList: T[] = []; const copiedList: T[] = [];
for (let e of list) { for (const e of list) {
if (e !== item) { if (e !== item) {
copiedList.push(e); copiedList.push(e);
} }

View file

@ -31,30 +31,33 @@ namespace ts {
} }
export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, targetSourceFile: SourceFile): Diagnostic[] { export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, targetSourceFile: SourceFile): Diagnostic[] {
let diagnostics: Diagnostic[] = []; const diagnostics: Diagnostic[] = [];
let jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, host, ".js"); const jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, host, ".js");
emitDeclarations(host, resolver, diagnostics, jsFilePath, targetSourceFile); emitDeclarations(host, resolver, diagnostics, jsFilePath, targetSourceFile);
return diagnostics; return diagnostics;
} }
function emitDeclarations(host: EmitHost, resolver: EmitResolver, diagnostics: Diagnostic[], jsFilePath: string, root?: SourceFile): DeclarationEmit { function emitDeclarations(host: EmitHost, resolver: EmitResolver, diagnostics: Diagnostic[], jsFilePath: string, root?: SourceFile): DeclarationEmit {
let newLine = host.getNewLine(); const newLine = host.getNewLine();
let compilerOptions = host.getCompilerOptions(); const compilerOptions = host.getCompilerOptions();
let write: (s: string) => void; let write: (s: string) => void;
let writeLine: () => void; let writeLine: () => void;
let increaseIndent: () => void; let increaseIndent: () => void;
let decreaseIndent: () => void; let decreaseIndent: () => void;
let writeTextOfNode: (sourceFile: SourceFile, node: Node) => void; let writeTextOfNode: (text: string, node: Node) => void;
let writer = createAndSetNewTextWriterWithSymbolWriter(); let writer = createAndSetNewTextWriterWithSymbolWriter();
let enclosingDeclaration: Node; let enclosingDeclaration: Node;
let currentSourceFile: SourceFile; let currentText: string;
let currentLineMap: number[];
let currentIdentifiers: Map<string>;
let isCurrentFileExternalModule: boolean;
let reportedDeclarationError = false; let reportedDeclarationError = false;
let errorNameNode: DeclarationName; let errorNameNode: DeclarationName;
let emitJsDocComments = compilerOptions.removeComments ? function (declaration: Node) { } : writeJsDocComments; const emitJsDocComments = compilerOptions.removeComments ? function (declaration: Node) { } : writeJsDocComments;
let emit = compilerOptions.stripInternal ? stripInternal : emitNode; const emit = compilerOptions.stripInternal ? stripInternal : emitNode;
let noDeclare = !root; let noDeclare = !root;
let moduleElementDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[] = []; let moduleElementDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[] = [];
@ -70,7 +73,7 @@ namespace ts {
if (!compilerOptions.noResolve) { if (!compilerOptions.noResolve) {
let addedGlobalFileReference = false; let addedGlobalFileReference = false;
forEach(root.referencedFiles, fileReference => { forEach(root.referencedFiles, fileReference => {
let referencedFile = tryResolveScriptReference(host, root, fileReference); const referencedFile = tryResolveScriptReference(host, root, fileReference);
// All the references that are not going to be part of same file // All the references that are not going to be part of same file
if (referencedFile && ((referencedFile.flags & NodeFlags.DeclarationFile) || // This is a declare file reference if (referencedFile && ((referencedFile.flags & NodeFlags.DeclarationFile) || // This is a declare file reference
@ -89,7 +92,7 @@ namespace ts {
// create asynchronous output for the importDeclarations // create asynchronous output for the importDeclarations
if (moduleElementDeclarationEmitInfo.length) { if (moduleElementDeclarationEmitInfo.length) {
let oldWriter = writer; const oldWriter = writer;
forEach(moduleElementDeclarationEmitInfo, aliasEmitInfo => { forEach(moduleElementDeclarationEmitInfo, aliasEmitInfo => {
if (aliasEmitInfo.isVisible) { if (aliasEmitInfo.isVisible) {
Debug.assert(aliasEmitInfo.node.kind === SyntaxKind.ImportDeclaration); Debug.assert(aliasEmitInfo.node.kind === SyntaxKind.ImportDeclaration);
@ -104,14 +107,14 @@ namespace ts {
} }
else { else {
// Emit references corresponding to this file // Emit references corresponding to this file
let emittedReferencedFiles: SourceFile[] = []; const emittedReferencedFiles: SourceFile[] = [];
let prevModuleElementDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[] = []; let prevModuleElementDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[] = [];
forEach(host.getSourceFiles(), sourceFile => { forEach(host.getSourceFiles(), sourceFile => {
if (!isDeclarationFile(sourceFile)) { if (!isDeclarationFile(sourceFile)) {
// Check what references need to be added // Check what references need to be added
if (!compilerOptions.noResolve) { if (!compilerOptions.noResolve) {
forEach(sourceFile.referencedFiles, fileReference => { forEach(sourceFile.referencedFiles, fileReference => {
let referencedFile = tryResolveScriptReference(host, sourceFile, fileReference); const referencedFile = tryResolveScriptReference(host, sourceFile, fileReference);
// If the reference file is a declaration file, emit that reference // If the reference file is a declaration file, emit that reference
if (referencedFile && (isDeclarationFile(referencedFile) && if (referencedFile && (isDeclarationFile(referencedFile) &&
@ -169,14 +172,13 @@ namespace ts {
}; };
function hasInternalAnnotation(range: CommentRange) { function hasInternalAnnotation(range: CommentRange) {
let text = currentSourceFile.text; const comment = currentText.substring(range.pos, range.end);
let comment = text.substring(range.pos, range.end);
return comment.indexOf("@internal") >= 0; return comment.indexOf("@internal") >= 0;
} }
function stripInternal(node: Node) { function stripInternal(node: Node) {
if (node) { if (node) {
let leadingCommentRanges = getLeadingCommentRanges(currentSourceFile.text, node.pos); const leadingCommentRanges = getLeadingCommentRanges(currentText, node.pos);
if (forEach(leadingCommentRanges, hasInternalAnnotation)) { if (forEach(leadingCommentRanges, hasInternalAnnotation)) {
return; return;
} }
@ -186,7 +188,7 @@ namespace ts {
} }
function createAndSetNewTextWriterWithSymbolWriter(): EmitTextWriterWithSymbolWriter { function createAndSetNewTextWriterWithSymbolWriter(): EmitTextWriterWithSymbolWriter {
let writer = <EmitTextWriterWithSymbolWriter>createTextWriter(newLine); const writer = <EmitTextWriterWithSymbolWriter>createTextWriter(newLine);
writer.trackSymbol = trackSymbol; writer.trackSymbol = trackSymbol;
writer.reportInaccessibleThisError = reportInaccessibleThisError; writer.reportInaccessibleThisError = reportInaccessibleThisError;
writer.writeKeyword = writer.write; writer.writeKeyword = writer.write;
@ -210,7 +212,7 @@ namespace ts {
} }
function writeAsynchronousModuleElements(nodes: Node[]) { function writeAsynchronousModuleElements(nodes: Node[]) {
let oldWriter = writer; const oldWriter = writer;
forEach(nodes, declaration => { forEach(nodes, declaration => {
let nodeToCheck: Node; let nodeToCheck: Node;
if (declaration.kind === SyntaxKind.VariableDeclaration) { if (declaration.kind === SyntaxKind.VariableDeclaration) {
@ -273,12 +275,12 @@ namespace ts {
else { else {
// Report error // Report error
reportedDeclarationError = true; reportedDeclarationError = true;
let errorInfo = writer.getSymbolAccessibilityDiagnostic(symbolAccesibilityResult); const errorInfo = writer.getSymbolAccessibilityDiagnostic(symbolAccesibilityResult);
if (errorInfo) { if (errorInfo) {
if (errorInfo.typeName) { if (errorInfo.typeName) {
diagnostics.push(createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode, diagnostics.push(createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode,
errorInfo.diagnosticMessage, errorInfo.diagnosticMessage,
getSourceTextOfNodeFromSourceFile(currentSourceFile, errorInfo.typeName), getTextOfNodeFromSourceText(currentText, errorInfo.typeName),
symbolAccesibilityResult.errorSymbolName, symbolAccesibilityResult.errorSymbolName,
symbolAccesibilityResult.errorModuleName)); symbolAccesibilityResult.errorModuleName));
} }
@ -332,14 +334,14 @@ namespace ts {
} }
function emitLines(nodes: Node[]) { function emitLines(nodes: Node[]) {
for (let node of nodes) { for (const node of nodes) {
emit(node); emit(node);
} }
} }
function emitSeparatedList(nodes: Node[], separator: string, eachNodeEmitFn: (node: Node) => void, canEmitFn?: (node: Node) => boolean) { function emitSeparatedList(nodes: Node[], separator: string, eachNodeEmitFn: (node: Node) => void, canEmitFn?: (node: Node) => boolean) {
let currentWriterPos = writer.getTextPos(); let currentWriterPos = writer.getTextPos();
for (let node of nodes) { for (const node of nodes) {
if (!canEmitFn || canEmitFn(node)) { if (!canEmitFn || canEmitFn(node)) {
if (currentWriterPos !== writer.getTextPos()) { if (currentWriterPos !== writer.getTextPos()) {
write(separator); write(separator);
@ -356,10 +358,10 @@ namespace ts {
function writeJsDocComments(declaration: Node) { function writeJsDocComments(declaration: Node) {
if (declaration) { if (declaration) {
let jsDocComments = getJsDocComments(declaration, currentSourceFile); const jsDocComments = getJsDocCommentsFromText(declaration, currentText);
emitNewLineBeforeLeadingComments(currentSourceFile, writer, declaration, jsDocComments); emitNewLineBeforeLeadingComments(currentLineMap, writer, declaration, jsDocComments);
// jsDoc comments are emitted at /*leading comment1 */space/*leading comment*/space // jsDoc comments are emitted at /*leading comment1 */space/*leading comment*/space
emitComments(currentSourceFile, writer, jsDocComments, /*trailingSeparator*/ true, newLine, writeCommentRange); emitComments(currentText, currentLineMap, writer, jsDocComments, /*trailingSeparator*/ true, newLine, writeCommentRange);
} }
} }
@ -378,7 +380,7 @@ namespace ts {
case SyntaxKind.VoidKeyword: case SyntaxKind.VoidKeyword:
case SyntaxKind.ThisKeyword: case SyntaxKind.ThisKeyword:
case SyntaxKind.StringLiteral: case SyntaxKind.StringLiteral:
return writeTextOfNode(currentSourceFile, type); return writeTextOfNode(currentText, type);
case SyntaxKind.ExpressionWithTypeArguments: case SyntaxKind.ExpressionWithTypeArguments:
return emitExpressionWithTypeArguments(<ExpressionWithTypeArguments>type); return emitExpressionWithTypeArguments(<ExpressionWithTypeArguments>type);
case SyntaxKind.TypeReference: case SyntaxKind.TypeReference:
@ -410,19 +412,19 @@ namespace ts {
function writeEntityName(entityName: EntityName | Expression) { function writeEntityName(entityName: EntityName | Expression) {
if (entityName.kind === SyntaxKind.Identifier) { if (entityName.kind === SyntaxKind.Identifier) {
writeTextOfNode(currentSourceFile, entityName); writeTextOfNode(currentText, entityName);
} }
else { else {
let left = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).left : (<PropertyAccessExpression>entityName).expression; const left = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).left : (<PropertyAccessExpression>entityName).expression;
let right = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).right : (<PropertyAccessExpression>entityName).name; const right = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).right : (<PropertyAccessExpression>entityName).name;
writeEntityName(left); writeEntityName(left);
write("."); write(".");
writeTextOfNode(currentSourceFile, right); writeTextOfNode(currentText, right);
} }
} }
function emitEntityName(entityName: EntityName | PropertyAccessExpression) { function emitEntityName(entityName: EntityName | PropertyAccessExpression) {
let visibilityResult = resolver.isEntityNameVisible(entityName, const visibilityResult = resolver.isEntityNameVisible(entityName,
// Aliases can be written asynchronously so use correct enclosing declaration // Aliases can be written asynchronously so use correct enclosing declaration
entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration ? entityName.parent : enclosingDeclaration); entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration ? entityName.parent : enclosingDeclaration);
@ -452,7 +454,7 @@ namespace ts {
} }
function emitTypePredicate(type: TypePredicateNode) { function emitTypePredicate(type: TypePredicateNode) {
writeTextOfNode(currentSourceFile, type.parameterName); writeTextOfNode(currentText, type.parameterName);
write(" is "); write(" is ");
emitType(type.type); emitType(type.type);
} }
@ -501,9 +503,12 @@ namespace ts {
} }
function emitSourceFile(node: SourceFile) { function emitSourceFile(node: SourceFile) {
currentSourceFile = node; currentText = node.text;
currentLineMap = getLineStarts(node);
currentIdentifiers = node.identifiers;
isCurrentFileExternalModule = isExternalModule(node);
enclosingDeclaration = node; enclosingDeclaration = node;
emitDetachedComments(currentSourceFile, writer, writeCommentRange, node, newLine, true /* remove comments */); emitDetachedComments(currentText, currentLineMap, writer, writeCommentRange, node, newLine, true /* remove comments */);
emitLines(node.statements); emitLines(node.statements);
} }
@ -512,14 +517,14 @@ namespace ts {
// Note that export default is only allowed at most once in a module, so we // Note that export default is only allowed at most once in a module, so we
// do not need to keep track of created temp names. // do not need to keep track of created temp names.
function getExportDefaultTempVariableName(): string { function getExportDefaultTempVariableName(): string {
let baseName = "_default"; const baseName = "_default";
if (!hasProperty(currentSourceFile.identifiers, baseName)) { if (!hasProperty(currentIdentifiers, baseName)) {
return baseName; return baseName;
} }
let count = 0; let count = 0;
while (true) { while (true) {
let name = baseName + "_" + (++count); const name = baseName + "_" + (++count);
if (!hasProperty(currentSourceFile.identifiers, name)) { if (!hasProperty(currentIdentifiers, name)) {
return name; return name;
} }
} }
@ -528,11 +533,11 @@ namespace ts {
function emitExportAssignment(node: ExportAssignment) { function emitExportAssignment(node: ExportAssignment) {
if (node.expression.kind === SyntaxKind.Identifier) { if (node.expression.kind === SyntaxKind.Identifier) {
write(node.isExportEquals ? "export = " : "export default "); write(node.isExportEquals ? "export = " : "export default ");
writeTextOfNode(currentSourceFile, node.expression); writeTextOfNode(currentText, node.expression);
} }
else { else {
// Expression // Expression
let tempVarName = getExportDefaultTempVariableName(); const tempVarName = getExportDefaultTempVariableName();
write("declare var "); write("declare var ");
write(tempVarName); write(tempVarName);
write(": "); write(": ");
@ -548,7 +553,7 @@ namespace ts {
// Make all the declarations visible for the export name // Make all the declarations visible for the export name
if (node.expression.kind === SyntaxKind.Identifier) { if (node.expression.kind === SyntaxKind.Identifier) {
let nodes = resolver.collectLinkedAliases(<Identifier>node.expression); const nodes = resolver.collectLinkedAliases(<Identifier>node.expression);
// write each of these declarations asynchronously // write each of these declarations asynchronously
writeAsynchronousModuleElements(nodes); writeAsynchronousModuleElements(nodes);
@ -572,7 +577,7 @@ namespace ts {
} }
// Import equals declaration in internal module can become visible as part of any emit so lets make sure we add these irrespective // Import equals declaration in internal module can become visible as part of any emit so lets make sure we add these irrespective
else if (node.kind === SyntaxKind.ImportEqualsDeclaration || else if (node.kind === SyntaxKind.ImportEqualsDeclaration ||
(node.parent.kind === SyntaxKind.SourceFile && isExternalModule(currentSourceFile))) { (node.parent.kind === SyntaxKind.SourceFile && isCurrentFileExternalModule)) {
let isVisible: boolean; let isVisible: boolean;
if (asynchronousSubModuleDeclarationEmitInfo && node.parent.kind !== SyntaxKind.SourceFile) { if (asynchronousSubModuleDeclarationEmitInfo && node.parent.kind !== SyntaxKind.SourceFile) {
// Import declaration of another module that is visited async so lets put it in right spot // Import declaration of another module that is visited async so lets put it in right spot
@ -585,7 +590,7 @@ namespace ts {
} }
else { else {
if (node.kind === SyntaxKind.ImportDeclaration) { if (node.kind === SyntaxKind.ImportDeclaration) {
let importDeclaration = <ImportDeclaration>node; const importDeclaration = <ImportDeclaration>node;
if (importDeclaration.importClause) { if (importDeclaration.importClause) {
isVisible = (importDeclaration.importClause.name && resolver.isDeclarationVisible(importDeclaration.importClause)) || isVisible = (importDeclaration.importClause.name && resolver.isDeclarationVisible(importDeclaration.importClause)) ||
isVisibleNamedBinding(importDeclaration.importClause.namedBindings); isVisibleNamedBinding(importDeclaration.importClause.namedBindings);
@ -628,7 +633,7 @@ namespace ts {
function emitModuleElementDeclarationFlags(node: Node) { function emitModuleElementDeclarationFlags(node: Node) {
// If the node is parented in the current source file we need to emit export declare or just export // If the node is parented in the current source file we need to emit export declare or just export
if (node.parent === currentSourceFile) { if (node.parent.kind === SyntaxKind.SourceFile) {
// If the node is exported // If the node is exported
if (node.flags & NodeFlags.Export) { if (node.flags & NodeFlags.Export) {
write("export "); write("export ");
@ -667,7 +672,7 @@ namespace ts {
write("export "); write("export ");
} }
write("import "); write("import ");
writeTextOfNode(currentSourceFile, node.name); writeTextOfNode(currentText, node.name);
write(" = "); write(" = ");
if (isInternalModuleImportEqualsDeclaration(node)) { if (isInternalModuleImportEqualsDeclaration(node)) {
emitTypeWithNewGetSymbolAccessibilityDiagnostic(<EntityName>node.moduleReference, getImportEntityNameVisibilityError); emitTypeWithNewGetSymbolAccessibilityDiagnostic(<EntityName>node.moduleReference, getImportEntityNameVisibilityError);
@ -675,7 +680,7 @@ namespace ts {
} }
else { else {
write("require("); write("require(");
writeTextOfNode(currentSourceFile, getExternalModuleImportEqualsDeclarationExpression(node)); writeTextOfNode(currentText, getExternalModuleImportEqualsDeclarationExpression(node));
write(");"); write(");");
} }
writer.writeLine(); writer.writeLine();
@ -711,9 +716,9 @@ namespace ts {
} }
write("import "); write("import ");
if (node.importClause) { if (node.importClause) {
let currentWriterPos = writer.getTextPos(); const currentWriterPos = writer.getTextPos();
if (node.importClause.name && resolver.isDeclarationVisible(node.importClause)) { if (node.importClause.name && resolver.isDeclarationVisible(node.importClause)) {
writeTextOfNode(currentSourceFile, node.importClause.name); writeTextOfNode(currentText, node.importClause.name);
} }
if (node.importClause.namedBindings && isVisibleNamedBinding(node.importClause.namedBindings)) { if (node.importClause.namedBindings && isVisibleNamedBinding(node.importClause.namedBindings)) {
if (currentWriterPos !== writer.getTextPos()) { if (currentWriterPos !== writer.getTextPos()) {
@ -722,7 +727,7 @@ namespace ts {
} }
if (node.importClause.namedBindings.kind === SyntaxKind.NamespaceImport) { if (node.importClause.namedBindings.kind === SyntaxKind.NamespaceImport) {
write("* as "); write("* as ");
writeTextOfNode(currentSourceFile, (<NamespaceImport>node.importClause.namedBindings).name); writeTextOfNode(currentText, (<NamespaceImport>node.importClause.namedBindings).name);
} }
else { else {
write("{ "); write("{ ");
@ -748,22 +753,22 @@ namespace ts {
} }
} }
writeTextOfNode(currentSourceFile, moduleSpecifier); writeTextOfNode(currentText, moduleSpecifier);
} }
function emitImportOrExportSpecifier(node: ImportOrExportSpecifier) { function emitImportOrExportSpecifier(node: ImportOrExportSpecifier) {
if (node.propertyName) { if (node.propertyName) {
writeTextOfNode(currentSourceFile, node.propertyName); writeTextOfNode(currentText, node.propertyName);
write(" as "); write(" as ");
} }
writeTextOfNode(currentSourceFile, node.name); writeTextOfNode(currentText, node.name);
} }
function emitExportSpecifier(node: ExportSpecifier) { function emitExportSpecifier(node: ExportSpecifier) {
emitImportOrExportSpecifier(node); emitImportOrExportSpecifier(node);
// Make all the declarations visible for the export name // Make all the declarations visible for the export name
let nodes = resolver.collectLinkedAliases(node.propertyName || node.name); const nodes = resolver.collectLinkedAliases(node.propertyName || node.name);
// write each of these declarations asynchronously // write each of these declarations asynchronously
writeAsynchronousModuleElements(nodes); writeAsynchronousModuleElements(nodes);
@ -797,13 +802,13 @@ namespace ts {
else { else {
write("module "); write("module ");
} }
writeTextOfNode(currentSourceFile, node.name); writeTextOfNode(currentText, node.name);
while (node.body.kind !== SyntaxKind.ModuleBlock) { while (node.body.kind !== SyntaxKind.ModuleBlock) {
node = <ModuleDeclaration>node.body; node = <ModuleDeclaration>node.body;
write("."); write(".");
writeTextOfNode(currentSourceFile, node.name); writeTextOfNode(currentText, node.name);
} }
let prevEnclosingDeclaration = enclosingDeclaration; const prevEnclosingDeclaration = enclosingDeclaration;
enclosingDeclaration = node; enclosingDeclaration = node;
write(" {"); write(" {");
writeLine(); writeLine();
@ -816,12 +821,12 @@ namespace ts {
} }
function writeTypeAliasDeclaration(node: TypeAliasDeclaration) { function writeTypeAliasDeclaration(node: TypeAliasDeclaration) {
let prevEnclosingDeclaration = enclosingDeclaration; const prevEnclosingDeclaration = enclosingDeclaration;
enclosingDeclaration = node; enclosingDeclaration = node;
emitJsDocComments(node); emitJsDocComments(node);
emitModuleElementDeclarationFlags(node); emitModuleElementDeclarationFlags(node);
write("type "); write("type ");
writeTextOfNode(currentSourceFile, node.name); writeTextOfNode(currentText, node.name);
emitTypeParameters(node.typeParameters); emitTypeParameters(node.typeParameters);
write(" = "); write(" = ");
emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError); emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError);
@ -845,7 +850,7 @@ namespace ts {
write("const "); write("const ");
} }
write("enum "); write("enum ");
writeTextOfNode(currentSourceFile, node.name); writeTextOfNode(currentText, node.name);
write(" {"); write(" {");
writeLine(); writeLine();
increaseIndent(); increaseIndent();
@ -857,8 +862,8 @@ namespace ts {
function emitEnumMemberDeclaration(node: EnumMember) { function emitEnumMemberDeclaration(node: EnumMember) {
emitJsDocComments(node); emitJsDocComments(node);
writeTextOfNode(currentSourceFile, node.name); writeTextOfNode(currentText, node.name);
let enumMemberValue = resolver.getConstantValue(node); const enumMemberValue = resolver.getConstantValue(node);
if (enumMemberValue !== undefined) { if (enumMemberValue !== undefined) {
write(" = "); write(" = ");
write(enumMemberValue.toString()); write(enumMemberValue.toString());
@ -876,7 +881,7 @@ namespace ts {
increaseIndent(); increaseIndent();
emitJsDocComments(node); emitJsDocComments(node);
decreaseIndent(); decreaseIndent();
writeTextOfNode(currentSourceFile, node.name); writeTextOfNode(currentText, node.name);
// If there is constraint present and this is not a type parameter of the private method emit the constraint // If there is constraint present and this is not a type parameter of the private method emit the constraint
if (node.constraint && !isPrivateMethodTypeParameter(node)) { if (node.constraint && !isPrivateMethodTypeParameter(node)) {
write(" extends "); write(" extends ");
@ -1007,11 +1012,11 @@ namespace ts {
} }
write("class "); write("class ");
writeTextOfNode(currentSourceFile, node.name); writeTextOfNode(currentText, node.name);
let prevEnclosingDeclaration = enclosingDeclaration; const prevEnclosingDeclaration = enclosingDeclaration;
enclosingDeclaration = node; enclosingDeclaration = node;
emitTypeParameters(node.typeParameters); emitTypeParameters(node.typeParameters);
let baseTypeNode = getClassExtendsHeritageClauseElement(node); const baseTypeNode = getClassExtendsHeritageClauseElement(node);
if (baseTypeNode) { if (baseTypeNode) {
emitHeritageClause([baseTypeNode], /*isImplementsList*/ false); emitHeritageClause([baseTypeNode], /*isImplementsList*/ false);
} }
@ -1031,8 +1036,8 @@ namespace ts {
emitJsDocComments(node); emitJsDocComments(node);
emitModuleElementDeclarationFlags(node); emitModuleElementDeclarationFlags(node);
write("interface "); write("interface ");
writeTextOfNode(currentSourceFile, node.name); writeTextOfNode(currentText, node.name);
let prevEnclosingDeclaration = enclosingDeclaration; const prevEnclosingDeclaration = enclosingDeclaration;
enclosingDeclaration = node; enclosingDeclaration = node;
emitTypeParameters(node.typeParameters); emitTypeParameters(node.typeParameters);
emitHeritageClause(getInterfaceBaseTypeNodes(node), /*isImplementsList*/ false); emitHeritageClause(getInterfaceBaseTypeNodes(node), /*isImplementsList*/ false);
@ -1069,7 +1074,7 @@ namespace ts {
// If this node is a computed name, it can only be a symbol, because we've already skipped // If this node is a computed name, it can only be a symbol, because we've already skipped
// it if it's not a well known symbol. In that case, the text of the name will be exactly // it if it's not a well known symbol. In that case, the text of the name will be exactly
// what we want, namely the name expression enclosed in brackets. // what we want, namely the name expression enclosed in brackets.
writeTextOfNode(currentSourceFile, node.name); writeTextOfNode(currentText, node.name);
// If optional property emit ? // If optional property emit ?
if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) && hasQuestionToken(node)) { if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) && hasQuestionToken(node)) {
write("?"); write("?");
@ -1118,7 +1123,7 @@ namespace ts {
} }
function getVariableDeclarationTypeVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic { function getVariableDeclarationTypeVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
let diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult); const diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
return diagnosticMessage !== undefined ? { return diagnosticMessage !== undefined ? {
diagnosticMessage, diagnosticMessage,
errorNode: node, errorNode: node,
@ -1132,8 +1137,8 @@ namespace ts {
// For example: // For example:
// original: var [, c,,] = [ 2,3,4] // original: var [, c,,] = [ 2,3,4]
// emitted: declare var c: number; // instead of declare var c:number, ; // emitted: declare var c: number; // instead of declare var c:number, ;
let elements: Node[] = []; const elements: Node[] = [];
for (let element of bindingPattern.elements) { for (const element of bindingPattern.elements) {
if (element.kind !== SyntaxKind.OmittedExpression) { if (element.kind !== SyntaxKind.OmittedExpression) {
elements.push(element); elements.push(element);
} }
@ -1143,7 +1148,7 @@ namespace ts {
function emitBindingElement(bindingElement: BindingElement) { function emitBindingElement(bindingElement: BindingElement) {
function getBindingElementTypeVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic { function getBindingElementTypeVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
let diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult); const diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
return diagnosticMessage !== undefined ? { return diagnosticMessage !== undefined ? {
diagnosticMessage, diagnosticMessage,
errorNode: bindingElement, errorNode: bindingElement,
@ -1156,7 +1161,7 @@ namespace ts {
emitBindingPattern(<BindingPattern>bindingElement.name); emitBindingPattern(<BindingPattern>bindingElement.name);
} }
else { else {
writeTextOfNode(currentSourceFile, bindingElement.name); writeTextOfNode(currentText, bindingElement.name);
writeTypeOfDeclaration(bindingElement, /*type*/ undefined, getBindingElementTypeVisibilityError); writeTypeOfDeclaration(bindingElement, /*type*/ undefined, getBindingElementTypeVisibilityError);
} }
} }
@ -1199,20 +1204,20 @@ namespace ts {
return; return;
} }
let accessors = getAllAccessorDeclarations((<ClassDeclaration>node.parent).members, node); const accessors = getAllAccessorDeclarations((<ClassDeclaration>node.parent).members, node);
let accessorWithTypeAnnotation: AccessorDeclaration; let accessorWithTypeAnnotation: AccessorDeclaration;
if (node === accessors.firstAccessor) { if (node === accessors.firstAccessor) {
emitJsDocComments(accessors.getAccessor); emitJsDocComments(accessors.getAccessor);
emitJsDocComments(accessors.setAccessor); emitJsDocComments(accessors.setAccessor);
emitClassMemberDeclarationFlags(node); emitClassMemberDeclarationFlags(node);
writeTextOfNode(currentSourceFile, node.name); writeTextOfNode(currentText, node.name);
if (!(node.flags & NodeFlags.Private)) { if (!(node.flags & NodeFlags.Private)) {
accessorWithTypeAnnotation = node; accessorWithTypeAnnotation = node;
let type = getTypeAnnotationFromAccessor(node); let type = getTypeAnnotationFromAccessor(node);
if (!type) { if (!type) {
// couldn't get type for the first accessor, try the another one // couldn't get type for the first accessor, try the another one
let anotherAccessor = node.kind === SyntaxKind.GetAccessor ? accessors.setAccessor : accessors.getAccessor; const anotherAccessor = node.kind === SyntaxKind.GetAccessor ? accessors.setAccessor : accessors.getAccessor;
type = getTypeAnnotationFromAccessor(anotherAccessor); type = getTypeAnnotationFromAccessor(anotherAccessor);
if (type) { if (type) {
accessorWithTypeAnnotation = anotherAccessor; accessorWithTypeAnnotation = anotherAccessor;
@ -1296,13 +1301,13 @@ namespace ts {
} }
if (node.kind === SyntaxKind.FunctionDeclaration) { if (node.kind === SyntaxKind.FunctionDeclaration) {
write("function "); write("function ");
writeTextOfNode(currentSourceFile, node.name); writeTextOfNode(currentText, node.name);
} }
else if (node.kind === SyntaxKind.Constructor) { else if (node.kind === SyntaxKind.Constructor) {
write("constructor"); write("constructor");
} }
else { else {
writeTextOfNode(currentSourceFile, node.name); writeTextOfNode(currentText, node.name);
if (hasQuestionToken(node)) { if (hasQuestionToken(node)) {
write("?"); write("?");
} }
@ -1329,7 +1334,7 @@ namespace ts {
write("("); write("(");
} }
let prevEnclosingDeclaration = enclosingDeclaration; const prevEnclosingDeclaration = enclosingDeclaration;
enclosingDeclaration = node; enclosingDeclaration = node;
// Parameters // Parameters
@ -1343,7 +1348,7 @@ namespace ts {
} }
// If this is not a constructor and is not private, emit the return type // If this is not a constructor and is not private, emit the return type
let isFunctionTypeOrConstructorType = node.kind === SyntaxKind.FunctionType || node.kind === SyntaxKind.ConstructorType; const isFunctionTypeOrConstructorType = node.kind === SyntaxKind.FunctionType || node.kind === SyntaxKind.ConstructorType;
if (isFunctionTypeOrConstructorType || node.parent.kind === SyntaxKind.TypeLiteral) { if (isFunctionTypeOrConstructorType || node.parent.kind === SyntaxKind.TypeLiteral) {
// Emit type literal signature return type only if specified // Emit type literal signature return type only if specified
if (node.type) { if (node.type) {
@ -1442,7 +1447,7 @@ namespace ts {
emitBindingPattern(<BindingPattern>node.name); emitBindingPattern(<BindingPattern>node.name);
} }
else { else {
writeTextOfNode(currentSourceFile, node.name); writeTextOfNode(currentText, node.name);
} }
if (resolver.isOptionalParameter(node)) { if (resolver.isOptionalParameter(node)) {
write("?"); write("?");
@ -1459,7 +1464,7 @@ namespace ts {
} }
function getParameterDeclarationTypeVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic { function getParameterDeclarationTypeVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
let diagnosticMessage: DiagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult); const diagnosticMessage: DiagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
return diagnosticMessage !== undefined ? { return diagnosticMessage !== undefined ? {
diagnosticMessage, diagnosticMessage,
errorNode: node, errorNode: node,
@ -1532,7 +1537,7 @@ namespace ts {
} }
else if (bindingPattern.kind === SyntaxKind.ArrayBindingPattern) { else if (bindingPattern.kind === SyntaxKind.ArrayBindingPattern) {
write("["); write("[");
let elements = bindingPattern.elements; const elements = bindingPattern.elements;
emitCommaList(elements, emitBindingElement); emitCommaList(elements, emitBindingElement);
if (elements && elements.hasTrailingComma) { if (elements && elements.hasTrailingComma) {
write(", "); write(", ");
@ -1543,7 +1548,7 @@ namespace ts {
function emitBindingElement(bindingElement: BindingElement) { function emitBindingElement(bindingElement: BindingElement) {
function getBindingElementTypeVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic { function getBindingElementTypeVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
let diagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult); const diagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
return diagnosticMessage !== undefined ? { return diagnosticMessage !== undefined ? {
diagnosticMessage, diagnosticMessage,
errorNode: bindingElement, errorNode: bindingElement,
@ -1568,7 +1573,7 @@ namespace ts {
// Example: // Example:
// original: function foo({y: [a,b,c]}) {} // original: function foo({y: [a,b,c]}) {}
// emit : declare function foo({y: [a, b, c]}: { y: [any, any, any] }) void; // emit : declare function foo({y: [a, b, c]}: { y: [any, any, any] }) void;
writeTextOfNode(currentSourceFile, bindingElement.propertyName); writeTextOfNode(currentText, bindingElement.propertyName);
write(": "); write(": ");
} }
if (bindingElement.name) { if (bindingElement.name) {
@ -1591,7 +1596,7 @@ namespace ts {
if (bindingElement.dotDotDotToken) { if (bindingElement.dotDotDotToken) {
write("..."); write("...");
} }
writeTextOfNode(currentSourceFile, bindingElement.name); writeTextOfNode(currentText, bindingElement.name);
} }
} }
} }
@ -1658,11 +1663,11 @@ namespace ts {
/* @internal */ /* @internal */
export function writeDeclarationFile(jsFilePath: string, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, diagnostics: Diagnostic[]) { export function writeDeclarationFile(jsFilePath: string, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, diagnostics: Diagnostic[]) {
let emitDeclarationResult = emitDeclarations(host, resolver, diagnostics, jsFilePath, sourceFile); const emitDeclarationResult = emitDeclarations(host, resolver, diagnostics, jsFilePath, sourceFile);
// TODO(shkamat): Should we not write any declaration file if any of them can produce error, // TODO(shkamat): Should we not write any declaration file if any of them can produce error,
// or should we just not write this file like we are doing now // or should we just not write this file like we are doing now
if (!emitDeclarationResult.reportedDeclarationError) { if (!emitDeclarationResult.reportedDeclarationError) {
let declarationOutput = emitDeclarationResult.referencePathsOutput const declarationOutput = emitDeclarationResult.referencePathsOutput
+ getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo); + getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo);
writeFile(host, diagnostics, removeFileExtension(jsFilePath) + ".d.ts", declarationOutput, host.getCompilerOptions().emitBOM); writeFile(host, diagnostics, removeFileExtension(jsFilePath) + ".d.ts", declarationOutput, host.getCompilerOptions().emitBOM);
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,7 @@ namespace ts {
/** The version of the TypeScript compiler release */ /** The version of the TypeScript compiler release */
let emptyArray: any[] = []; const emptyArray: any[] = [];
export const version = "1.8.0"; export const version = "1.8.0";
@ -20,7 +20,7 @@ namespace ts {
if (sys.fileExists(fileName)) { if (sys.fileExists(fileName)) {
return fileName; return fileName;
} }
let parentPath = getDirectoryPath(searchPath); const parentPath = getDirectoryPath(searchPath);
if (parentPath === searchPath) { if (parentPath === searchPath) {
break; break;
} }
@ -31,13 +31,13 @@ namespace ts {
} }
export function resolveTripleslashReference(moduleName: string, containingFile: string): string { export function resolveTripleslashReference(moduleName: string, containingFile: string): string {
let basePath = getDirectoryPath(containingFile); const basePath = getDirectoryPath(containingFile);
let referencedFileName = isRootedDiskPath(moduleName) ? moduleName : combinePaths(basePath, moduleName); const referencedFileName = isRootedDiskPath(moduleName) ? moduleName : combinePaths(basePath, moduleName);
return normalizePath(referencedFileName); return normalizePath(referencedFileName);
} }
export function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations { export function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations {
let moduleResolution = compilerOptions.moduleResolution !== undefined const moduleResolution = compilerOptions.moduleResolution !== undefined
? compilerOptions.moduleResolution ? compilerOptions.moduleResolution
: compilerOptions.module === ModuleKind.CommonJS ? ModuleResolutionKind.NodeJs : ModuleResolutionKind.Classic; : compilerOptions.module === ModuleKind.CommonJS ? ModuleResolutionKind.NodeJs : ModuleResolutionKind.Classic;
@ -48,11 +48,11 @@ namespace ts {
} }
export function nodeModuleNameResolver(moduleName: string, containingFile: string, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations { export function nodeModuleNameResolver(moduleName: string, containingFile: string, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations {
let containingDirectory = getDirectoryPath(containingFile); const containingDirectory = getDirectoryPath(containingFile);
if (getRootLength(moduleName) !== 0 || nameStartsWithDotSlashOrDotDotSlash(moduleName)) { if (getRootLength(moduleName) !== 0 || nameStartsWithDotSlashOrDotDotSlash(moduleName)) {
let failedLookupLocations: string[] = []; const failedLookupLocations: string[] = [];
let candidate = normalizePath(combinePaths(containingDirectory, moduleName)); const candidate = normalizePath(combinePaths(containingDirectory, moduleName));
let resolvedFileName = loadNodeModuleFromFile(candidate, failedLookupLocations, host); let resolvedFileName = loadNodeModuleFromFile(candidate, failedLookupLocations, host);
if (resolvedFileName) { if (resolvedFileName) {
@ -73,7 +73,7 @@ namespace ts {
return forEach(moduleFileExtensions, tryLoad); return forEach(moduleFileExtensions, tryLoad);
function tryLoad(ext: string): string { function tryLoad(ext: string): string {
let fileName = fileExtensionIs(candidate, ext) ? candidate : candidate + ext; const fileName = fileExtensionIs(candidate, ext) ? candidate : candidate + ext;
if (host.fileExists(fileName)) { if (host.fileExists(fileName)) {
return fileName; return fileName;
} }
@ -85,13 +85,13 @@ namespace ts {
} }
function loadNodeModuleFromDirectory(candidate: string, failedLookupLocation: string[], host: ModuleResolutionHost): string { function loadNodeModuleFromDirectory(candidate: string, failedLookupLocation: string[], host: ModuleResolutionHost): string {
let packageJsonPath = combinePaths(candidate, "package.json"); const packageJsonPath = combinePaths(candidate, "package.json");
if (host.fileExists(packageJsonPath)) { if (host.fileExists(packageJsonPath)) {
let jsonContent: { typings?: string }; let jsonContent: { typings?: string };
try { try {
let jsonText = host.readFile(packageJsonPath); const jsonText = host.readFile(packageJsonPath);
jsonContent = jsonText ? <{ typings?: string }>JSON.parse(jsonText) : { typings: undefined }; jsonContent = jsonText ? <{ typings?: string }>JSON.parse(jsonText) : { typings: undefined };
} }
catch (e) { catch (e) {
@ -100,7 +100,7 @@ namespace ts {
} }
if (jsonContent.typings) { if (jsonContent.typings) {
let result = loadNodeModuleFromFile(normalizePath(combinePaths(candidate, jsonContent.typings)), failedLookupLocation, host); const result = loadNodeModuleFromFile(normalizePath(combinePaths(candidate, jsonContent.typings)), failedLookupLocation, host);
if (result) { if (result) {
return result; return result;
} }
@ -115,13 +115,13 @@ namespace ts {
} }
function loadModuleFromNodeModules(moduleName: string, directory: string, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations { function loadModuleFromNodeModules(moduleName: string, directory: string, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations {
let failedLookupLocations: string[] = []; const failedLookupLocations: string[] = [];
directory = normalizeSlashes(directory); directory = normalizeSlashes(directory);
while (true) { while (true) {
let baseName = getBaseFileName(directory); const baseName = getBaseFileName(directory);
if (baseName !== "node_modules") { if (baseName !== "node_modules") {
let nodeModulesFolder = combinePaths(directory, "node_modules"); const nodeModulesFolder = combinePaths(directory, "node_modules");
let candidate = normalizePath(combinePaths(nodeModulesFolder, moduleName)); const candidate = normalizePath(combinePaths(nodeModulesFolder, moduleName));
let result = loadNodeModuleFromFile(candidate, failedLookupLocations, host); let result = loadNodeModuleFromFile(candidate, failedLookupLocations, host);
if (result) { if (result) {
return { resolvedModule: { resolvedFileName: result, isExternalLibraryImport: true }, failedLookupLocations }; return { resolvedModule: { resolvedFileName: result, isExternalLibraryImport: true }, failedLookupLocations };
@ -133,7 +133,7 @@ namespace ts {
} }
} }
let parentPath = getDirectoryPath(directory); const parentPath = getDirectoryPath(directory);
if (parentPath === directory) { if (parentPath === directory) {
break; break;
} }
@ -145,7 +145,7 @@ namespace ts {
} }
function nameStartsWithDotSlashOrDotDotSlash(name: string) { function nameStartsWithDotSlashOrDotDotSlash(name: string) {
let i = name.lastIndexOf("./", 1); const i = name.lastIndexOf("./", 1);
return i === 0 || (i === 1 && name.charCodeAt(0) === CharacterCodes.dot); return i === 0 || (i === 1 && name.charCodeAt(0) === CharacterCodes.dot);
} }
@ -159,7 +159,7 @@ namespace ts {
let searchPath = getDirectoryPath(containingFile); let searchPath = getDirectoryPath(containingFile);
let searchName: string; let searchName: string;
let failedLookupLocations: string[] = []; const failedLookupLocations: string[] = [];
let referencedSourceFile: string; let referencedSourceFile: string;
while (true) { while (true) {
@ -171,7 +171,7 @@ namespace ts {
return undefined; return undefined;
} }
let candidate = searchName + extension; const candidate = searchName + extension;
if (host.fileExists(candidate)) { if (host.fileExists(candidate)) {
return candidate; return candidate;
} }
@ -184,7 +184,7 @@ namespace ts {
break; break;
} }
let parentPath = getDirectoryPath(searchPath); const parentPath = getDirectoryPath(searchPath);
if (parentPath === searchPath) { if (parentPath === searchPath) {
break; break;
} }
@ -199,15 +199,13 @@ namespace ts {
/* @internal */ /* @internal */
export const defaultInitCompilerOptions: CompilerOptions = { export const defaultInitCompilerOptions: CompilerOptions = {
module: ModuleKind.CommonJS, module: ModuleKind.CommonJS,
target: ScriptTarget.ES3, target: ScriptTarget.ES5,
noImplicitAny: false, noImplicitAny: false,
outDir: "built",
rootDir: ".",
sourceMap: false, sourceMap: false,
}; };
export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost { export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost {
let existingDirectories: Map<boolean> = {}; const existingDirectories: Map<boolean> = {};
function getCanonicalFileName(fileName: string): string { function getCanonicalFileName(fileName: string): string {
// if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form. // if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
@ -216,12 +214,12 @@ namespace ts {
} }
// returned by CScript sys environment // returned by CScript sys environment
let unsupportedFileEncodingErrorCode = -2147024809; const unsupportedFileEncodingErrorCode = -2147024809;
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile { function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile {
let text: string; let text: string;
try { try {
let start = new Date().getTime(); const start = new Date().getTime();
text = sys.readFile(fileName, options.charset); text = sys.readFile(fileName, options.charset);
ioReadTime += new Date().getTime() - start; ioReadTime += new Date().getTime() - start;
} }
@ -250,7 +248,7 @@ namespace ts {
function ensureDirectoriesExist(directoryPath: string) { function ensureDirectoriesExist(directoryPath: string) {
if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) { if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) {
let parentDirectory = getDirectoryPath(directoryPath); const parentDirectory = getDirectoryPath(directoryPath);
ensureDirectoriesExist(parentDirectory); ensureDirectoriesExist(parentDirectory);
sys.createDirectory(directoryPath); sys.createDirectory(directoryPath);
} }
@ -258,7 +256,7 @@ namespace ts {
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) { function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
try { try {
let start = new Date().getTime(); const start = new Date().getTime();
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName))); ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
sys.writeFile(fileName, data, writeByteOrderMark); sys.writeFile(fileName, data, writeByteOrderMark);
ioWriteTime += new Date().getTime() - start; ioWriteTime += new Date().getTime() - start;
@ -286,7 +284,7 @@ namespace ts {
} }
export function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[] { export function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[] {
let diagnostics = program.getOptionsDiagnostics(cancellationToken).concat( const diagnostics = program.getOptionsDiagnostics(cancellationToken).concat(
program.getSyntacticDiagnostics(sourceFile, cancellationToken), program.getSyntacticDiagnostics(sourceFile, cancellationToken),
program.getGlobalDiagnostics(cancellationToken), program.getGlobalDiagnostics(cancellationToken),
program.getSemanticDiagnostics(sourceFile, cancellationToken)); program.getSemanticDiagnostics(sourceFile, cancellationToken));
@ -328,7 +326,7 @@ namespace ts {
let program: Program; let program: Program;
let files: SourceFile[] = []; let files: SourceFile[] = [];
let fileProcessingDiagnostics = createDiagnosticCollection(); let fileProcessingDiagnostics = createDiagnosticCollection();
let programDiagnostics = createDiagnosticCollection(); const programDiagnostics = createDiagnosticCollection();
let commonSourceDirectory: string; let commonSourceDirectory: string;
let diagnosticsProducingTypeChecker: TypeChecker; let diagnosticsProducingTypeChecker: TypeChecker;
@ -337,7 +335,7 @@ namespace ts {
let skipDefaultLib = options.noLib; let skipDefaultLib = options.noLib;
let start = new Date().getTime(); const start = new Date().getTime();
host = host || createCompilerHost(options); host = host || createCompilerHost(options);
@ -346,15 +344,15 @@ namespace ts {
? ((moduleNames: string[], containingFile: string) => host.resolveModuleNames(moduleNames, containingFile)) ? ((moduleNames: string[], containingFile: string) => host.resolveModuleNames(moduleNames, containingFile))
: ((moduleNames: string[], containingFile: string) => map(moduleNames, moduleName => resolveModuleName(moduleName, containingFile, options, host).resolvedModule)); : ((moduleNames: string[], containingFile: string) => map(moduleNames, moduleName => resolveModuleName(moduleName, containingFile, options, host).resolvedModule));
let filesByName = createFileMap<SourceFile>(); const filesByName = createFileMap<SourceFile>();
// stores 'filename -> file association' ignoring case // stores 'filename -> file association' ignoring case
// used to track cases when two file names differ only in casing // used to track cases when two file names differ only in casing
let filesByNameIgnoreCase = host.useCaseSensitiveFileNames() ? createFileMap<SourceFile>(fileName => fileName.toLowerCase()) : undefined; const filesByNameIgnoreCase = host.useCaseSensitiveFileNames() ? createFileMap<SourceFile>(fileName => fileName.toLowerCase()) : undefined;
if (oldProgram) { if (oldProgram) {
// check properties that can affect structure of the program or module resolution strategy // check properties that can affect structure of the program or module resolution strategy
// if any of these properties has changed - structure cannot be reused // if any of these properties has changed - structure cannot be reused
let oldOptions = oldProgram.getCompilerOptions(); const oldOptions = oldProgram.getCompilerOptions();
if ((oldOptions.module !== options.module) || if ((oldOptions.module !== options.module) ||
(oldOptions.noResolve !== options.noResolve) || (oldOptions.noResolve !== options.noResolve) ||
(oldOptions.target !== options.target) || (oldOptions.target !== options.target) ||
@ -412,7 +410,7 @@ namespace ts {
getTypeChecker(); getTypeChecker();
classifiableNames = {}; classifiableNames = {};
for (let sourceFile of files) { for (const sourceFile of files) {
copyMap(sourceFile.classifiableNames, classifiableNames); copyMap(sourceFile.classifiableNames, classifiableNames);
} }
} }
@ -428,17 +426,17 @@ namespace ts {
Debug.assert(!oldProgram.structureIsReused); Debug.assert(!oldProgram.structureIsReused);
// there is an old program, check if we can reuse its structure // there is an old program, check if we can reuse its structure
let oldRootNames = oldProgram.getRootFileNames(); const oldRootNames = oldProgram.getRootFileNames();
if (!arrayIsEqualTo(oldRootNames, rootNames)) { if (!arrayIsEqualTo(oldRootNames, rootNames)) {
return false; return false;
} }
// check if program source files has changed in the way that can affect structure of the program // check if program source files has changed in the way that can affect structure of the program
let newSourceFiles: SourceFile[] = []; const newSourceFiles: SourceFile[] = [];
let filePaths: Path[] = []; const filePaths: Path[] = [];
let modifiedSourceFiles: SourceFile[] = []; const modifiedSourceFiles: SourceFile[] = [];
for (let oldSourceFile of oldProgram.getSourceFiles()) { for (const oldSourceFile of oldProgram.getSourceFiles()) {
let newSourceFile = host.getSourceFile(oldSourceFile.fileName, options.target); let newSourceFile = host.getSourceFile(oldSourceFile.fileName, options.target);
if (!newSourceFile) { if (!newSourceFile) {
return false; return false;
@ -468,13 +466,13 @@ namespace ts {
} }
if (resolveModuleNamesWorker) { if (resolveModuleNamesWorker) {
let moduleNames = map(newSourceFile.imports, name => name.text); const moduleNames = map(newSourceFile.imports, name => name.text);
let resolutions = resolveModuleNamesWorker(moduleNames, getNormalizedAbsolutePath(newSourceFile.fileName, currentDirectory)); const resolutions = resolveModuleNamesWorker(moduleNames, getNormalizedAbsolutePath(newSourceFile.fileName, currentDirectory));
// ensure that module resolution results are still correct // ensure that module resolution results are still correct
for (let i = 0; i < moduleNames.length; ++i) { for (let i = 0; i < moduleNames.length; ++i) {
let newResolution = resolutions[i]; const newResolution = resolutions[i];
let oldResolution = getResolvedModule(oldSourceFile, moduleNames[i]); const oldResolution = getResolvedModule(oldSourceFile, moduleNames[i]);
let resolutionChanged = oldResolution const resolutionChanged = oldResolution
? !newResolution || ? !newResolution ||
oldResolution.resolvedFileName !== newResolution.resolvedFileName || oldResolution.resolvedFileName !== newResolution.resolvedFileName ||
!!oldResolution.isExternalLibraryImport !== !!newResolution.isExternalLibraryImport !!oldResolution.isExternalLibraryImport !== !!newResolution.isExternalLibraryImport
@ -506,7 +504,7 @@ namespace ts {
files = newSourceFiles; files = newSourceFiles;
fileProcessingDiagnostics = oldProgram.getFileProcessingDiagnostics(); fileProcessingDiagnostics = oldProgram.getFileProcessingDiagnostics();
for (let modifiedFile of modifiedSourceFiles) { for (const modifiedFile of modifiedSourceFiles) {
fileProcessingDiagnostics.reattachFileDiagnostics(modifiedFile); fileProcessingDiagnostics.reattachFileDiagnostics(modifiedFile);
} }
oldProgram.structureIsReused = true; oldProgram.structureIsReused = true;
@ -556,11 +554,11 @@ namespace ts {
// This is because in the -out scenario all files need to be emitted, and therefore all // This is because in the -out scenario all files need to be emitted, and therefore all
// files need to be type checked. And the way to specify that all files need to be type // files need to be type checked. And the way to specify that all files need to be type
// checked is to not pass the file to getEmitResolver. // checked is to not pass the file to getEmitResolver.
let emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver((options.outFile || options.out) ? undefined : sourceFile); const emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver((options.outFile || options.out) ? undefined : sourceFile);
let start = new Date().getTime(); const start = new Date().getTime();
let emitResult = emitFiles( const emitResult = emitFiles(
emitResolver, emitResolver,
getEmitHost(writeFileCallback), getEmitHost(writeFileCallback),
sourceFile); sourceFile);
@ -581,7 +579,7 @@ namespace ts {
return getDiagnostics(sourceFile, cancellationToken); return getDiagnostics(sourceFile, cancellationToken);
} }
let allDiagnostics: Diagnostic[] = []; const allDiagnostics: Diagnostic[] = [];
forEach(program.getSourceFiles(), sourceFile => { forEach(program.getSourceFiles(), sourceFile => {
if (cancellationToken) { if (cancellationToken) {
cancellationToken.throwIfCancellationRequested(); cancellationToken.throwIfCancellationRequested();
@ -633,13 +631,13 @@ namespace ts {
function getSemanticDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] { function getSemanticDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
return runWithCancellationToken(() => { return runWithCancellationToken(() => {
let typeChecker = getDiagnosticsProducingTypeChecker(); const typeChecker = getDiagnosticsProducingTypeChecker();
Debug.assert(!!sourceFile.bindDiagnostics); Debug.assert(!!sourceFile.bindDiagnostics);
let bindDiagnostics = sourceFile.bindDiagnostics; const bindDiagnostics = sourceFile.bindDiagnostics;
let checkDiagnostics = typeChecker.getDiagnostics(sourceFile, cancellationToken); const checkDiagnostics = typeChecker.getDiagnostics(sourceFile, cancellationToken);
let fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName); const fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName);
let programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName); const programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName);
return bindDiagnostics.concat(checkDiagnostics).concat(fileProcessingDiagnosticsInFile).concat(programDiagnosticsInFile); return bindDiagnostics.concat(checkDiagnostics).concat(fileProcessingDiagnosticsInFile).concat(programDiagnosticsInFile);
}); });
@ -648,23 +646,23 @@ namespace ts {
function getDeclarationDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] { function getDeclarationDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
return runWithCancellationToken(() => { return runWithCancellationToken(() => {
if (!isDeclarationFile(sourceFile)) { if (!isDeclarationFile(sourceFile)) {
let resolver = getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile, cancellationToken); const resolver = getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile, cancellationToken);
// Don't actually write any files since we're just getting diagnostics. // Don't actually write any files since we're just getting diagnostics.
let writeFile: WriteFileCallback = () => { }; const writeFile: WriteFileCallback = () => { };
return ts.getDeclarationDiagnostics(getEmitHost(writeFile), resolver, sourceFile); return ts.getDeclarationDiagnostics(getEmitHost(writeFile), resolver, sourceFile);
} }
}); });
} }
function getOptionsDiagnostics(): Diagnostic[] { function getOptionsDiagnostics(): Diagnostic[] {
let allDiagnostics: Diagnostic[] = []; const allDiagnostics: Diagnostic[] = [];
addRange(allDiagnostics, fileProcessingDiagnostics.getGlobalDiagnostics()); addRange(allDiagnostics, fileProcessingDiagnostics.getGlobalDiagnostics());
addRange(allDiagnostics, programDiagnostics.getGlobalDiagnostics()); addRange(allDiagnostics, programDiagnostics.getGlobalDiagnostics());
return sortAndDeduplicateDiagnostics(allDiagnostics); return sortAndDeduplicateDiagnostics(allDiagnostics);
} }
function getGlobalDiagnostics(): Diagnostic[] { function getGlobalDiagnostics(): Diagnostic[] {
let allDiagnostics: Diagnostic[] = []; const allDiagnostics: Diagnostic[] = [];
addRange(allDiagnostics, getDiagnosticsProducingTypeChecker().getGlobalDiagnostics()); addRange(allDiagnostics, getDiagnosticsProducingTypeChecker().getGlobalDiagnostics());
return sortAndDeduplicateDiagnostics(allDiagnostics); return sortAndDeduplicateDiagnostics(allDiagnostics);
} }
@ -691,7 +689,7 @@ namespace ts {
} }
let imports: LiteralExpression[]; let imports: LiteralExpression[];
for (let node of file.statements) { for (const node of file.statements) {
collect(node, /* allowRelativeModuleNames */ true); collect(node, /* allowRelativeModuleNames */ true);
} }
@ -751,7 +749,7 @@ namespace ts {
} }
} }
else { else {
let nonTsFile: SourceFile = options.allowNonTsExtensions && findSourceFile(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, refFile, refPos, refEnd); const nonTsFile: SourceFile = options.allowNonTsExtensions && findSourceFile(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, refFile, refPos, refEnd);
if (!nonTsFile) { if (!nonTsFile) {
if (options.allowNonTsExtensions) { if (options.allowNonTsExtensions) {
diagnostic = Diagnostics.File_0_not_found; diagnostic = Diagnostics.File_0_not_found;
@ -799,7 +797,7 @@ namespace ts {
} }
// We haven't looked for this file, do so now and cache result // We haven't looked for this file, do so now and cache result
let file = host.getSourceFile(fileName, options.target, hostErrorMessage => { const file = host.getSourceFile(fileName, options.target, hostErrorMessage => {
if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) { if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) {
fileProcessingDiagnostics.add(createFileDiagnostic(refFile, refPos, refEnd - refPos, fileProcessingDiagnostics.add(createFileDiagnostic(refFile, refPos, refEnd - refPos,
Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage)); Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage));
@ -826,7 +824,7 @@ namespace ts {
skipDefaultLib = skipDefaultLib || file.hasNoDefaultLib; skipDefaultLib = skipDefaultLib || file.hasNoDefaultLib;
let basePath = getDirectoryPath(fileName); const basePath = getDirectoryPath(fileName);
if (!options.noResolve) { if (!options.noResolve) {
processReferencedFiles(file, basePath); processReferencedFiles(file, basePath);
} }
@ -848,7 +846,7 @@ namespace ts {
function processReferencedFiles(file: SourceFile, basePath: string) { function processReferencedFiles(file: SourceFile, basePath: string) {
forEach(file.referencedFiles, ref => { forEach(file.referencedFiles, ref => {
let referencedFileName = resolveTripleslashReference(ref.fileName, file.fileName); const referencedFileName = resolveTripleslashReference(ref.fileName, file.fileName);
processSourceFile(referencedFileName, /* isDefaultLib */ false, file, ref.pos, ref.end); processSourceFile(referencedFileName, /* isDefaultLib */ false, file, ref.pos, ref.end);
}); });
} }
@ -861,21 +859,21 @@ namespace ts {
collectExternalModuleReferences(file); collectExternalModuleReferences(file);
if (file.imports.length) { if (file.imports.length) {
file.resolvedModules = {}; file.resolvedModules = {};
let moduleNames = map(file.imports, name => name.text); const moduleNames = map(file.imports, name => name.text);
let resolutions = resolveModuleNamesWorker(moduleNames, getNormalizedAbsolutePath(file.fileName, currentDirectory)); const resolutions = resolveModuleNamesWorker(moduleNames, getNormalizedAbsolutePath(file.fileName, currentDirectory));
for (let i = 0; i < file.imports.length; ++i) { for (let i = 0; i < file.imports.length; ++i) {
let resolution = resolutions[i]; const resolution = resolutions[i];
setResolvedModule(file, moduleNames[i], resolution); setResolvedModule(file, moduleNames[i], resolution);
if (resolution && !options.noResolve) { if (resolution && !options.noResolve) {
const importedFile = findSourceFile(resolution.resolvedFileName, toPath(resolution.resolvedFileName, currentDirectory, getCanonicalFileName), /* isDefaultLib */ false, file, skipTrivia(file.text, file.imports[i].pos), file.imports[i].end); const importedFile = findSourceFile(resolution.resolvedFileName, toPath(resolution.resolvedFileName, currentDirectory, getCanonicalFileName), /* isDefaultLib */ false, file, skipTrivia(file.text, file.imports[i].pos), file.imports[i].end);
if (importedFile && resolution.isExternalLibraryImport) { if (importedFile && resolution.isExternalLibraryImport) {
if (!isExternalModule(importedFile)) { if (!isExternalModule(importedFile)) {
let start = getTokenPosOfNode(file.imports[i], file); const start = getTokenPosOfNode(file.imports[i], file);
fileProcessingDiagnostics.add(createFileDiagnostic(file, start, file.imports[i].end - start, Diagnostics.Exported_external_package_typings_file_0_is_not_a_module_Please_contact_the_package_author_to_update_the_package_definition, importedFile.fileName)); fileProcessingDiagnostics.add(createFileDiagnostic(file, start, file.imports[i].end - start, Diagnostics.Exported_external_package_typings_file_0_is_not_a_module_Please_contact_the_package_author_to_update_the_package_definition, importedFile.fileName));
} }
else if (importedFile.referencedFiles.length) { else if (importedFile.referencedFiles.length) {
let firstRef = importedFile.referencedFiles[0]; const firstRef = importedFile.referencedFiles[0];
fileProcessingDiagnostics.add(createFileDiagnostic(importedFile, firstRef.pos, firstRef.end - firstRef.pos, Diagnostics.Exported_external_package_typings_file_cannot_contain_tripleslash_references_Please_contact_the_package_author_to_update_the_package_definition)); fileProcessingDiagnostics.add(createFileDiagnostic(importedFile, firstRef.pos, firstRef.end - firstRef.pos, Diagnostics.Exported_external_package_typings_file_cannot_contain_tripleslash_references_Please_contact_the_package_author_to_update_the_package_definition));
} }
} }
@ -897,7 +895,7 @@ namespace ts {
return; return;
} }
let sourcePathComponents = getNormalizedPathComponents(sourceFile.fileName, currentDirectory); const sourcePathComponents = getNormalizedPathComponents(sourceFile.fileName, currentDirectory);
sourcePathComponents.pop(); // The base file name is not part of the common directory path sourcePathComponents.pop(); // The base file name is not part of the common directory path
if (!commonPathComponents) { if (!commonPathComponents) {
@ -935,11 +933,11 @@ namespace ts {
function checkSourceFilesBelongToPath(sourceFiles: SourceFile[], rootDirectory: string): boolean { function checkSourceFilesBelongToPath(sourceFiles: SourceFile[], rootDirectory: string): boolean {
let allFilesBelongToPath = true; let allFilesBelongToPath = true;
if (sourceFiles) { if (sourceFiles) {
let absoluteRootDirectoryPath = host.getCanonicalFileName(getNormalizedAbsolutePath(rootDirectory, currentDirectory)); const absoluteRootDirectoryPath = host.getCanonicalFileName(getNormalizedAbsolutePath(rootDirectory, currentDirectory));
for (var sourceFile of sourceFiles) { for (var sourceFile of sourceFiles) {
if (!isDeclarationFile(sourceFile)) { if (!isDeclarationFile(sourceFile)) {
let absoluteSourceFilePath = host.getCanonicalFileName(getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory)); const absoluteSourceFilePath = host.getCanonicalFileName(getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory));
if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) { if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, sourceFile.fileName, options.rootDir)); programDiagnostics.add(createCompilerDiagnostic(Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, sourceFile.fileName, options.rootDir));
allFilesBelongToPath = false; allFilesBelongToPath = false;
@ -1004,24 +1002,24 @@ namespace ts {
return; return;
} }
let languageVersion = options.target || ScriptTarget.ES3; const languageVersion = options.target || ScriptTarget.ES3;
let outFile = options.outFile || options.out; const outFile = options.outFile || options.out;
let firstExternalModuleSourceFile = forEach(files, f => isExternalModule(f) ? f : undefined); const firstExternalModuleSourceFile = forEach(files, f => isExternalModule(f) ? f : undefined);
if (options.isolatedModules) { if (options.isolatedModules) {
if (!options.module && languageVersion < ScriptTarget.ES6) { if (!options.module && languageVersion < ScriptTarget.ES6) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_isolatedModules_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES2015_or_higher)); programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_isolatedModules_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES2015_or_higher));
} }
let firstNonExternalModuleSourceFile = forEach(files, f => !isExternalModule(f) && !isDeclarationFile(f) ? f : undefined); const firstNonExternalModuleSourceFile = forEach(files, f => !isExternalModule(f) && !isDeclarationFile(f) ? f : undefined);
if (firstNonExternalModuleSourceFile) { if (firstNonExternalModuleSourceFile) {
let span = getErrorSpanForNode(firstNonExternalModuleSourceFile, firstNonExternalModuleSourceFile); const span = getErrorSpanForNode(firstNonExternalModuleSourceFile, firstNonExternalModuleSourceFile);
programDiagnostics.add(createFileDiagnostic(firstNonExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_compile_namespaces_when_the_isolatedModules_flag_is_provided)); programDiagnostics.add(createFileDiagnostic(firstNonExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_compile_namespaces_when_the_isolatedModules_flag_is_provided));
} }
} }
else if (firstExternalModuleSourceFile && languageVersion < ScriptTarget.ES6 && !options.module) { else if (firstExternalModuleSourceFile && languageVersion < ScriptTarget.ES6 && !options.module) {
// We cannot use createDiagnosticFromNode because nodes do not have parents yet // We cannot use createDiagnosticFromNode because nodes do not have parents yet
let span = getErrorSpanForNode(firstExternalModuleSourceFile, firstExternalModuleSourceFile.externalModuleIndicator); const span = getErrorSpanForNode(firstExternalModuleSourceFile, firstExternalModuleSourceFile.externalModuleIndicator);
programDiagnostics.add(createFileDiagnostic(firstExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_compile_modules_unless_the_module_flag_is_provided)); programDiagnostics.add(createFileDiagnostic(firstExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_compile_modules_unless_the_module_flag_is_provided));
} }

File diff suppressed because one or more lines are too long

View file

@ -51,15 +51,15 @@ namespace ts {
function getWScriptSystem(): System { function getWScriptSystem(): System {
let fso = new ActiveXObject("Scripting.FileSystemObject"); const fso = new ActiveXObject("Scripting.FileSystemObject");
let fileStream = new ActiveXObject("ADODB.Stream"); const fileStream = new ActiveXObject("ADODB.Stream");
fileStream.Type = 2 /*text*/; fileStream.Type = 2 /*text*/;
let binaryStream = new ActiveXObject("ADODB.Stream"); const binaryStream = new ActiveXObject("ADODB.Stream");
binaryStream.Type = 1 /*binary*/; binaryStream.Type = 1 /*binary*/;
let args: string[] = []; const args: string[] = [];
for (let i = 0; i < WScript.Arguments.length; i++) { for (let i = 0; i < WScript.Arguments.length; i++) {
args[i] = WScript.Arguments.Item(i); args[i] = WScript.Arguments.Item(i);
} }
@ -78,7 +78,7 @@ namespace ts {
// Load file and read the first two bytes into a string with no interpretation // Load file and read the first two bytes into a string with no interpretation
fileStream.Charset = "x-ansi"; fileStream.Charset = "x-ansi";
fileStream.LoadFromFile(fileName); fileStream.LoadFromFile(fileName);
let bom = fileStream.ReadText(2) || ""; const bom = fileStream.ReadText(2) || "";
// Position must be at 0 before encoding can be changed // Position must be at 0 before encoding can be changed
fileStream.Position = 0; fileStream.Position = 0;
// [0xFF,0xFE] and [0xFE,0xFF] mean utf-16 (little or big endian), otherwise default to utf-8 // [0xFF,0xFE] and [0xFE,0xFF] mean utf-16 (little or big endian), otherwise default to utf-8
@ -124,7 +124,7 @@ namespace ts {
} }
function getNames(collection: any): string[] { function getNames(collection: any): string[] {
let result: string[] = []; const result: string[] = [];
for (let e = new Enumerator(collection); !e.atEnd(); e.moveNext()) { for (let e = new Enumerator(collection); !e.atEnd(); e.moveNext()) {
result.push(e.item().Name); result.push(e.item().Name);
} }
@ -132,22 +132,22 @@ namespace ts {
} }
function readDirectory(path: string, extension?: string, exclude?: string[]): string[] { function readDirectory(path: string, extension?: string, exclude?: string[]): string[] {
let result: string[] = []; const result: string[] = [];
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s))); exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
visitDirectory(path); visitDirectory(path);
return result; return result;
function visitDirectory(path: string) { function visitDirectory(path: string) {
let folder = fso.GetFolder(path || "."); const folder = fso.GetFolder(path || ".");
let files = getNames(folder.files); const files = getNames(folder.files);
for (let current of files) { for (const current of files) {
let name = combinePaths(path, current); const name = combinePaths(path, current);
if ((!extension || fileExtensionIs(name, extension)) && !contains(exclude, getCanonicalPath(name))) { if ((!extension || fileExtensionIs(name, extension)) && !contains(exclude, getCanonicalPath(name))) {
result.push(name); result.push(name);
} }
} }
let subfolders = getNames(folder.subfolders); const subfolders = getNames(folder.subfolders);
for (let current of subfolders) { for (const current of subfolders) {
let name = combinePaths(path, current); const name = combinePaths(path, current);
if (!contains(exclude, getCanonicalPath(name))) { if (!contains(exclude, getCanonicalPath(name))) {
visitDirectory(name); visitDirectory(name);
} }
@ -212,7 +212,7 @@ namespace ts {
} }
function poll(checkedIndex: number) { function poll(checkedIndex: number) {
let watchedFile = watchedFiles[checkedIndex]; const watchedFile = watchedFiles[checkedIndex];
if (!watchedFile) { if (!watchedFile) {
return; return;
} }
@ -252,7 +252,7 @@ namespace ts {
} }
function addFile(fileName: string, callback: (fileName: string, removed?: boolean) => void): WatchedFile { function addFile(fileName: string, callback: (fileName: string, removed?: boolean) => void): WatchedFile {
let file: WatchedFile = { const file: WatchedFile = {
fileName, fileName,
callback, callback,
mtime: getModifiedTime(fileName) mtime: getModifiedTime(fileName)
@ -291,7 +291,7 @@ namespace ts {
// changes for large reference sets? If so, do we want // changes for large reference sets? If so, do we want
// to increase the chunk size or decrease the interval // to increase the chunk size or decrease the interval
// time dynamically to match the large reference set? // time dynamically to match the large reference set?
let watchedFileSet = createWatchedFileSet(); const watchedFileSet = createWatchedFileSet();
function isNode4OrLater(): Boolean { function isNode4OrLater(): Boolean {
return parseInt(process.version.charAt(1)) >= 4; return parseInt(process.version.charAt(1)) >= 4;
@ -305,14 +305,14 @@ namespace ts {
if (!_fs.existsSync(fileName)) { if (!_fs.existsSync(fileName)) {
return undefined; return undefined;
} }
let buffer = _fs.readFileSync(fileName); const buffer = _fs.readFileSync(fileName);
let len = buffer.length; let len = buffer.length;
if (len >= 2 && buffer[0] === 0xFE && buffer[1] === 0xFF) { if (len >= 2 && buffer[0] === 0xFE && buffer[1] === 0xFF) {
// Big endian UTF-16 byte order mark detected. Since big endian is not supported by node.js, // Big endian UTF-16 byte order mark detected. Since big endian is not supported by node.js,
// flip all byte pairs and treat as little endian. // flip all byte pairs and treat as little endian.
len &= ~1; len &= ~1;
for (let i = 0; i < len; i += 2) { for (let i = 0; i < len; i += 2) {
let temp = buffer[i]; const temp = buffer[i];
buffer[i] = buffer[i + 1]; buffer[i] = buffer[i + 1];
buffer[i + 1] = temp; buffer[i + 1] = temp;
} }
@ -336,7 +336,17 @@ namespace ts {
data = "\uFEFF" + data; data = "\uFEFF" + data;
} }
_fs.writeFileSync(fileName, data, "utf8"); let fd: number;
try {
fd = _fs.openSync(fileName, "w");
_fs.writeSync(fd, data, undefined, "utf8");
}
finally {
if (fd !== undefined) {
_fs.closeSync(fd);
}
}
} }
function getCanonicalPath(path: string): string { function getCanonicalPath(path: string): string {
@ -344,17 +354,17 @@ namespace ts {
} }
function readDirectory(path: string, extension?: string, exclude?: string[]): string[] { function readDirectory(path: string, extension?: string, exclude?: string[]): string[] {
let result: string[] = []; const result: string[] = [];
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s))); exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
visitDirectory(path); visitDirectory(path);
return result; return result;
function visitDirectory(path: string) { function visitDirectory(path: string) {
let files = _fs.readdirSync(path || ".").sort(); const files = _fs.readdirSync(path || ".").sort();
let directories: string[] = []; const directories: string[] = [];
for (let current of files) { for (const current of files) {
let name = combinePaths(path, current); const name = combinePaths(path, current);
if (!contains(exclude, getCanonicalPath(name))) { if (!contains(exclude, getCanonicalPath(name))) {
let stat = _fs.statSync(name); const stat = _fs.statSync(name);
if (stat.isFile()) { if (stat.isFile()) {
if (!extension || fileExtensionIs(name, extension)) { if (!extension || fileExtensionIs(name, extension)) {
result.push(name); result.push(name);
@ -365,7 +375,7 @@ namespace ts {
} }
} }
} }
for (let current of directories) { for (const current of directories) {
visitDirectory(current); visitDirectory(current);
} }
} }
@ -390,7 +400,7 @@ namespace ts {
return _fs.watch(fileName, (eventName: string, relativeFileName: string) => callback(fileName)); return _fs.watch(fileName, (eventName: string, relativeFileName: string) => callback(fileName));
} }
let watchedFile = watchedFileSet.addFile(fileName, callback); const watchedFile = watchedFileSet.addFile(fileName, callback);
return { return {
close: () => watchedFileSet.removeFile(watchedFile) close: () => watchedFileSet.removeFile(watchedFile)
}; };

View file

@ -9,7 +9,7 @@ namespace ts {
let reportDiagnostic = reportDiagnosticSimply; let reportDiagnostic = reportDiagnosticSimply;
function reportDiagnostics(diagnostics: Diagnostic[], host: CompilerHost): void { function reportDiagnostics(diagnostics: Diagnostic[], host: CompilerHost): void {
for (let diagnostic of diagnostics) { for (const diagnostic of diagnostics) {
reportDiagnostic(diagnostic, host); reportDiagnostic(diagnostic, host);
} }
} }
@ -19,15 +19,15 @@ namespace ts {
* and if it is, attempts to set the appropriate language. * and if it is, attempts to set the appropriate language.
*/ */
function validateLocaleAndSetLanguage(locale: string, errors: Diagnostic[]): boolean { function validateLocaleAndSetLanguage(locale: string, errors: Diagnostic[]): boolean {
let matchResult = /^([a-z]+)([_\-]([a-z]+))?$/.exec(locale.toLowerCase()); const matchResult = /^([a-z]+)([_\-]([a-z]+))?$/.exec(locale.toLowerCase());
if (!matchResult) { if (!matchResult) {
errors.push(createCompilerDiagnostic(Diagnostics.Locale_must_be_of_the_form_language_or_language_territory_For_example_0_or_1, "en", "ja-jp")); errors.push(createCompilerDiagnostic(Diagnostics.Locale_must_be_of_the_form_language_or_language_territory_For_example_0_or_1, "en", "ja-jp"));
return false; return false;
} }
let language = matchResult[1]; const language = matchResult[1];
let territory = matchResult[3]; const territory = matchResult[3];
// First try the entire locale, then fall back to just language if that's all we have. // First try the entire locale, then fall back to just language if that's all we have.
if (!trySetLanguageAndTerritory(language, territory, errors) && if (!trySetLanguageAndTerritory(language, territory, errors) &&
@ -41,8 +41,8 @@ namespace ts {
} }
function trySetLanguageAndTerritory(language: string, territory: string, errors: Diagnostic[]): boolean { function trySetLanguageAndTerritory(language: string, territory: string, errors: Diagnostic[]): boolean {
let compilerFilePath = normalizePath(sys.getExecutingFilePath()); const compilerFilePath = normalizePath(sys.getExecutingFilePath());
let containingDirectoryPath = getDirectoryPath(compilerFilePath); const containingDirectoryPath = getDirectoryPath(compilerFilePath);
let filePath = combinePaths(containingDirectoryPath, language); let filePath = combinePaths(containingDirectoryPath, language);
@ -85,23 +85,24 @@ namespace ts {
} }
function getDiagnosticText(message: DiagnosticMessage, ...args: any[]): string { function getDiagnosticText(message: DiagnosticMessage, ...args: any[]): string {
let diagnostic = createCompilerDiagnostic.apply(undefined, arguments); const diagnostic = createCompilerDiagnostic.apply(undefined, arguments);
return <string>diagnostic.messageText; return <string>diagnostic.messageText;
} }
function getRelativeFileName(fileName: string, host: CompilerHost): string {
return host ? convertToRelativePath(fileName, host.getCurrentDirectory(), fileName => host.getCanonicalFileName(fileName)) : fileName;
}
function reportDiagnosticSimply(diagnostic: Diagnostic, host: CompilerHost): void { function reportDiagnosticSimply(diagnostic: Diagnostic, host: CompilerHost): void {
let output = ""; let output = "";
if (diagnostic.file) { if (diagnostic.file) {
const { line, character } = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start); const { line, character } = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
const relativeFileName = host const relativeFileName = getRelativeFileName(diagnostic.file.fileName, host);
? convertToRelativePath(diagnostic.file.fileName, host.getCurrentDirectory(), fileName => host.getCanonicalFileName(fileName)) output += `${ relativeFileName }(${ line + 1 },${ character + 1 }): `;
: diagnostic.file.fileName;
output += `${ diagnostic.file.fileName }(${ line + 1 },${ character + 1 }): `;
} }
let category = DiagnosticCategory[diagnostic.category].toLowerCase(); const category = DiagnosticCategory[diagnostic.category].toLowerCase();
output += `${ category } TS${ diagnostic.code }: ${ flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine) }${ sys.newLine }`; output += `${ category } TS${ diagnostic.code }: ${ flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine) }${ sys.newLine }`;
sys.write(output); sys.write(output);
@ -129,12 +130,13 @@ namespace ts {
let output = ""; let output = "";
if (diagnostic.file) { if (diagnostic.file) {
let { start, length, file } = diagnostic; const { start, length, file } = diagnostic;
let { line: firstLine, character: firstLineChar } = getLineAndCharacterOfPosition(file, start); const { line: firstLine, character: firstLineChar } = getLineAndCharacterOfPosition(file, start);
let { line: lastLine, character: lastLineChar } = getLineAndCharacterOfPosition(file, start + length); const { line: lastLine, character: lastLineChar } = getLineAndCharacterOfPosition(file, start + length);
const lastLineInFile = getLineAndCharacterOfPosition(file, file.text.length).line; const lastLineInFile = getLineAndCharacterOfPosition(file, file.text.length).line;
const relativeFileName = getRelativeFileName(file.fileName, host);
let hasMoreThanFiveLines = (lastLine - firstLine) >= 4; const hasMoreThanFiveLines = (lastLine - firstLine) >= 4;
let gutterWidth = (lastLine + 1 + "").length; let gutterWidth = (lastLine + 1 + "").length;
if (hasMoreThanFiveLines) { if (hasMoreThanFiveLines) {
gutterWidth = Math.max(elipsis.length, gutterWidth); gutterWidth = Math.max(elipsis.length, gutterWidth);
@ -149,8 +151,8 @@ namespace ts {
i = lastLine - 1; i = lastLine - 1;
} }
let lineStart = getPositionOfLineAndCharacter(file, i, 0); const lineStart = getPositionOfLineAndCharacter(file, i, 0);
let lineEnd = i < lastLineInFile ? getPositionOfLineAndCharacter(file, i + 1, 0) : file.text.length; const lineEnd = i < lastLineInFile ? getPositionOfLineAndCharacter(file, i + 1, 0) : file.text.length;
let lineContent = file.text.slice(lineStart, lineEnd); let lineContent = file.text.slice(lineStart, lineEnd);
lineContent = lineContent.replace(/\s+$/g, ""); // trim from end lineContent = lineContent.replace(/\s+$/g, ""); // trim from end
lineContent = lineContent.replace("\t", " "); // convert tabs to single spaces lineContent = lineContent.replace("\t", " "); // convert tabs to single spaces
@ -183,7 +185,7 @@ namespace ts {
} }
output += sys.newLine; output += sys.newLine;
output += `${ file.fileName }(${ firstLine + 1 },${ firstLineChar + 1 }): `; output += `${ relativeFileName }(${ firstLine + 1 },${ firstLineChar + 1 }): `;
} }
const categoryColor = categoryFormatMap[diagnostic.category]; const categoryColor = categoryFormatMap[diagnostic.category];
@ -198,7 +200,7 @@ namespace ts {
let output = new Date().toLocaleTimeString() + " - "; let output = new Date().toLocaleTimeString() + " - ";
if (diagnostic.file) { if (diagnostic.file) {
let loc = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start); const loc = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
output += `${ diagnostic.file.fileName }(${ loc.line + 1 },${ loc.character + 1 }): `; output += `${ diagnostic.file.fileName }(${ loc.line + 1 },${ loc.character + 1 }): `;
} }
@ -239,7 +241,7 @@ namespace ts {
} }
export function executeCommandLine(args: string[]): void { export function executeCommandLine(args: string[]): void {
let commandLine = parseCommandLine(args); const commandLine = parseCommandLine(args);
let configFileName: string; // Configuration file name (if any) let configFileName: string; // Configuration file name (if any)
let cachedConfigFileText: string; // Cached configuration file text, used for reparsing (if any) let cachedConfigFileText: string; // Cached configuration file text, used for reparsing (if any)
let configFileWatcher: FileWatcher; // Configuration file watcher let configFileWatcher: FileWatcher; // Configuration file watcher
@ -300,7 +302,7 @@ namespace ts {
} }
} }
else if (commandLine.fileNames.length === 0 && isJSONSupported()) { else if (commandLine.fileNames.length === 0 && isJSONSupported()) {
let searchPath = normalizePath(sys.getCurrentDirectory()); const searchPath = normalizePath(sys.getCurrentDirectory());
configFileName = findConfigFile(searchPath); configFileName = findConfigFile(searchPath);
} }
@ -320,7 +322,7 @@ namespace ts {
configFileWatcher = sys.watchFile(configFileName, configFileChanged); configFileWatcher = sys.watchFile(configFileName, configFileChanged);
} }
if (sys.watchDirectory && configFileName) { if (sys.watchDirectory && configFileName) {
let directory = ts.getDirectoryPath(configFileName); const directory = ts.getDirectoryPath(configFileName);
directoryWatcher = sys.watchDirectory( directoryWatcher = sys.watchDirectory(
// When the configFileName is just "tsconfig.json", the watched directory should be // When the configFileName is just "tsconfig.json", the watched directory should be
// the current direcotry; if there is a given "project" parameter, then the configFileName // the current direcotry; if there is a given "project" parameter, then the configFileName
@ -338,16 +340,16 @@ namespace ts {
cachedConfigFileText = sys.readFile(configFileName); cachedConfigFileText = sys.readFile(configFileName);
} }
catch (e) { catch (e) {
let error = createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, configFileName, e.message); const error = createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, configFileName, e.message);
reportWatchDiagnostic(error); reportWatchDiagnostic(error);
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
return; return;
} }
} }
let result = parseConfigFileTextToJson(configFileName, cachedConfigFileText); const result = parseConfigFileTextToJson(configFileName, cachedConfigFileText);
let configObject = result.config; const configObject = result.config;
let configParseResult = parseJsonConfigFileContent(configObject, sys, getDirectoryPath(configFileName)); const configParseResult = parseJsonConfigFileContent(configObject, sys, getDirectoryPath(configFileName));
if (configParseResult.errors.length > 0) { if (configParseResult.errors.length > 0) {
reportDiagnostics(configParseResult.errors, /* compilerHost */ undefined); reportDiagnostics(configParseResult.errors, /* compilerHost */ undefined);
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
@ -361,7 +363,7 @@ namespace ts {
if (!cachedProgram) { if (!cachedProgram) {
if (configFileName) { if (configFileName) {
let configParseResult = parseConfigFile(); const configParseResult = parseConfigFile();
rootFileNames = configParseResult.fileNames; rootFileNames = configParseResult.fileNames;
compilerOptions = extend(commandLine.options, configParseResult.options); compilerOptions = extend(commandLine.options, configParseResult.options);
} }
@ -384,7 +386,7 @@ namespace ts {
// reset the cache of existing files // reset the cache of existing files
cachedExistingFiles = {}; cachedExistingFiles = {};
let compileResult = compile(rootFileNames, compilerOptions, compilerHost); const compileResult = compile(rootFileNames, compilerOptions, compilerHost);
if (!compilerOptions.watch) { if (!compilerOptions.watch) {
return sys.exit(compileResult.exitStatus); return sys.exit(compileResult.exitStatus);
@ -404,14 +406,14 @@ namespace ts {
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void) { function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void) {
// Return existing SourceFile object if one is available // Return existing SourceFile object if one is available
if (cachedProgram) { if (cachedProgram) {
let sourceFile = cachedProgram.getSourceFile(fileName); const sourceFile = cachedProgram.getSourceFile(fileName);
// A modified source file has no watcher and should not be reused // A modified source file has no watcher and should not be reused
if (sourceFile && sourceFile.fileWatcher) { if (sourceFile && sourceFile.fileWatcher) {
return sourceFile; return sourceFile;
} }
} }
// Use default host function // Use default host function
let sourceFile = hostGetSourceFile(fileName, languageVersion, onError); const sourceFile = hostGetSourceFile(fileName, languageVersion, onError);
if (sourceFile && compilerOptions.watch) { if (sourceFile && compilerOptions.watch) {
// Attach a file watcher // Attach a file watcher
sourceFile.fileWatcher = sys.watchFile(sourceFile.fileName, (fileName: string, removed?: boolean) => sourceFileChanged(sourceFile, removed)); sourceFile.fileWatcher = sys.watchFile(sourceFile.fileName, (fileName: string, removed?: boolean) => sourceFileChanged(sourceFile, removed));
@ -422,7 +424,7 @@ namespace ts {
// Change cached program to the given program // Change cached program to the given program
function setCachedProgram(program: Program) { function setCachedProgram(program: Program) {
if (cachedProgram) { if (cachedProgram) {
let newSourceFiles = program ? program.getSourceFiles() : undefined; const newSourceFiles = program ? program.getSourceFiles() : undefined;
forEach(cachedProgram.getSourceFiles(), sourceFile => { forEach(cachedProgram.getSourceFiles(), sourceFile => {
if (!(newSourceFiles && contains(newSourceFiles, sourceFile))) { if (!(newSourceFiles && contains(newSourceFiles, sourceFile))) {
if (sourceFile.fileWatcher) { if (sourceFile.fileWatcher) {
@ -440,7 +442,7 @@ namespace ts {
sourceFile.fileWatcher.close(); sourceFile.fileWatcher.close();
sourceFile.fileWatcher = undefined; sourceFile.fileWatcher = undefined;
if (removed) { if (removed) {
let index = rootFileNames.indexOf(sourceFile.fileName); const index = rootFileNames.indexOf(sourceFile.fileName);
if (index >= 0) { if (index >= 0) {
rootFileNames.splice(index, 1); rootFileNames.splice(index, 1);
} }
@ -471,9 +473,9 @@ namespace ts {
} }
function directoryChangeHandler() { function directoryChangeHandler() {
let parsedCommandLine = parseConfigFile(); const parsedCommandLine = parseConfigFile();
let newFileNames = ts.map(parsedCommandLine.fileNames, compilerHost.getCanonicalFileName); const newFileNames = ts.map(parsedCommandLine.fileNames, compilerHost.getCanonicalFileName);
let canonicalRootFileNames = ts.map(rootFileNames, compilerHost.getCanonicalFileName); const canonicalRootFileNames = ts.map(rootFileNames, compilerHost.getCanonicalFileName);
// We check if the project file list has changed. If so, we just throw away the old program and start fresh. // We check if the project file list has changed. If so, we just throw away the old program and start fresh.
if (!arrayIsEqualTo(newFileNames && newFileNames.sort(), canonicalRootFileNames && canonicalRootFileNames.sort())) { if (!arrayIsEqualTo(newFileNames && newFileNames.sort(), canonicalRootFileNames && canonicalRootFileNames.sort())) {
@ -507,8 +509,8 @@ namespace ts {
checkTime = 0; checkTime = 0;
emitTime = 0; emitTime = 0;
let program = createProgram(fileNames, compilerOptions, compilerHost); const program = createProgram(fileNames, compilerOptions, compilerHost);
let exitStatus = compileProgram(); const exitStatus = compileProgram();
if (compilerOptions.listFiles) { if (compilerOptions.listFiles) {
forEach(program.getSourceFiles(), file => { forEach(program.getSourceFiles(), file => {
@ -517,7 +519,7 @@ namespace ts {
} }
if (compilerOptions.diagnostics) { if (compilerOptions.diagnostics) {
let memoryUsed = sys.getMemoryUsage ? sys.getMemoryUsage() : -1; const memoryUsed = sys.getMemoryUsage ? sys.getMemoryUsage() : -1;
reportCountStatistic("Files", program.getSourceFiles().length); reportCountStatistic("Files", program.getSourceFiles().length);
reportCountStatistic("Lines", countLines(program)); reportCountStatistic("Lines", countLines(program));
reportCountStatistic("Nodes", program.getNodeCount()); reportCountStatistic("Nodes", program.getNodeCount());
@ -570,7 +572,7 @@ namespace ts {
} }
// Otherwise, emit and report any errors we ran into. // Otherwise, emit and report any errors we ran into.
let emitOutput = program.emit(); const emitOutput = program.emit();
reportDiagnostics(emitOutput.diagnostics, compilerHost); reportDiagnostics(emitOutput.diagnostics, compilerHost);
// If the emitter didn't emit anything, then pass that value along. // If the emitter didn't emit anything, then pass that value along.
@ -596,8 +598,8 @@ namespace ts {
let output = ""; let output = "";
// We want to align our "syntax" and "examples" commands to a certain margin. // We want to align our "syntax" and "examples" commands to a certain margin.
let syntaxLength = getDiagnosticText(Diagnostics.Syntax_Colon_0, "").length; const syntaxLength = getDiagnosticText(Diagnostics.Syntax_Colon_0, "").length;
let examplesLength = getDiagnosticText(Diagnostics.Examples_Colon_0, "").length; const examplesLength = getDiagnosticText(Diagnostics.Examples_Colon_0, "").length;
let marginLength = Math.max(syntaxLength, examplesLength); let marginLength = Math.max(syntaxLength, examplesLength);
// Build up the syntactic skeleton. // Build up the syntactic skeleton.
@ -608,7 +610,7 @@ namespace ts {
output += sys.newLine + sys.newLine; output += sys.newLine + sys.newLine;
// Build up the list of examples. // Build up the list of examples.
let padding = makePadding(marginLength); const padding = makePadding(marginLength);
output += getDiagnosticText(Diagnostics.Examples_Colon_0, makePadding(marginLength - examplesLength) + "tsc hello.ts") + sys.newLine; output += getDiagnosticText(Diagnostics.Examples_Colon_0, makePadding(marginLength - examplesLength) + "tsc hello.ts") + sys.newLine;
output += padding + "tsc --out file.js file.ts" + sys.newLine; output += padding + "tsc --out file.js file.ts" + sys.newLine;
output += padding + "tsc @args.txt" + sys.newLine; output += padding + "tsc @args.txt" + sys.newLine;
@ -617,17 +619,17 @@ namespace ts {
output += getDiagnosticText(Diagnostics.Options_Colon) + sys.newLine; output += getDiagnosticText(Diagnostics.Options_Colon) + sys.newLine;
// Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch") // Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch")
let optsList = filter(optionDeclarations.slice(), v => !v.experimental); const optsList = filter(optionDeclarations.slice(), v => !v.experimental);
optsList.sort((a, b) => compareValues<string>(a.name.toLowerCase(), b.name.toLowerCase())); optsList.sort((a, b) => compareValues<string>(a.name.toLowerCase(), b.name.toLowerCase()));
// We want our descriptions to align at the same column in our output, // We want our descriptions to align at the same column in our output,
// so we keep track of the longest option usage string. // so we keep track of the longest option usage string.
marginLength = 0; marginLength = 0;
let usageColumn: string[] = []; // Things like "-d, --declaration" go in here. const usageColumn: string[] = []; // Things like "-d, --declaration" go in here.
let descriptionColumn: string[] = []; const descriptionColumn: string[] = [];
for (let i = 0; i < optsList.length; i++) { for (let i = 0; i < optsList.length; i++) {
let option = optsList[i]; const option = optsList[i];
// If an option lacks a description, // If an option lacks a description,
// it is not officially supported. // it is not officially supported.
@ -653,15 +655,15 @@ namespace ts {
} }
// Special case that can't fit in the loop. // Special case that can't fit in the loop.
let usageText = " @<" + getDiagnosticText(Diagnostics.file) + ">"; const usageText = " @<" + getDiagnosticText(Diagnostics.file) + ">";
usageColumn.push(usageText); usageColumn.push(usageText);
descriptionColumn.push(getDiagnosticText(Diagnostics.Insert_command_line_options_and_files_from_a_file)); descriptionColumn.push(getDiagnosticText(Diagnostics.Insert_command_line_options_and_files_from_a_file));
marginLength = Math.max(usageText.length, marginLength); marginLength = Math.max(usageText.length, marginLength);
// Print out each row, aligning all the descriptions on the same column. // Print out each row, aligning all the descriptions on the same column.
for (let i = 0; i < usageColumn.length; i++) { for (let i = 0; i < usageColumn.length; i++) {
let usage = usageColumn[i]; const usage = usageColumn[i];
let description = descriptionColumn[i]; const description = descriptionColumn[i];
output += usage + makePadding(marginLength - usage.length + 2) + description + sys.newLine; output += usage + makePadding(marginLength - usage.length + 2) + description + sys.newLine;
} }
@ -681,14 +683,14 @@ namespace ts {
} }
function writeConfigFile(options: CompilerOptions, fileNames: string[]) { function writeConfigFile(options: CompilerOptions, fileNames: string[]) {
let currentDirectory = sys.getCurrentDirectory(); const currentDirectory = sys.getCurrentDirectory();
let file = normalizePath(combinePaths(currentDirectory, "tsconfig.json")); const file = normalizePath(combinePaths(currentDirectory, "tsconfig.json"));
if (sys.fileExists(file)) { if (sys.fileExists(file)) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file), /* compilerHost */ undefined); reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file), /* compilerHost */ undefined);
} }
else { else {
let compilerOptions = extend(options, defaultInitCompilerOptions); const compilerOptions = extend(options, defaultInitCompilerOptions);
let configurations: any = { const configurations: any = {
compilerOptions: serializeCompilerOptions(compilerOptions), compilerOptions: serializeCompilerOptions(compilerOptions),
exclude: ["node_modules"] exclude: ["node_modules"]
}; };
@ -705,12 +707,12 @@ namespace ts {
return; return;
function serializeCompilerOptions(options: CompilerOptions): Map<string | number | boolean> { function serializeCompilerOptions(options: CompilerOptions): Map<string | number | boolean> {
let result: Map<string | number | boolean> = {}; const result: Map<string | number | boolean> = {};
let optionsNameMap = getOptionNameMap().optionNameMap; const optionsNameMap = getOptionNameMap().optionNameMap;
for (let name in options) { for (const name in options) {
if (hasProperty(options, name)) { if (hasProperty(options, name)) {
let value = options[name]; const value = options[name];
switch (name) { switch (name) {
case "init": case "init":
case "watch": case "watch":
@ -727,8 +729,8 @@ namespace ts {
} }
else { else {
// Enum // Enum
let typeMap = <Map<number>>optionDefinition.type; const typeMap = <Map<number>>optionDefinition.type;
for (let key in typeMap) { for (const key in typeMap) {
if (hasProperty(typeMap, key)) { if (hasProperty(typeMap, key)) {
if (typeMap[key] === value) if (typeMap[key] === value)
result[name] = key; result[name] = key;

View file

@ -1957,6 +1957,8 @@ namespace ts {
target?: TypeParameter; // Instantiation target target?: TypeParameter; // Instantiation target
/* @internal */ /* @internal */
mapper?: TypeMapper; // Instantiation mapper mapper?: TypeMapper; // Instantiation mapper
/* @internal */
resolvedApparentType: Type;
} }
export const enum SignatureKind { export const enum SignatureKind {

View file

@ -16,9 +16,9 @@ namespace ts {
} }
export function getDeclarationOfKind(symbol: Symbol, kind: SyntaxKind): Declaration { export function getDeclarationOfKind(symbol: Symbol, kind: SyntaxKind): Declaration {
let declarations = symbol.declarations; const declarations = symbol.declarations;
if (declarations) { if (declarations) {
for (let declaration of declarations) { for (const declaration of declarations) {
if (declaration.kind === kind) { if (declaration.kind === kind) {
return declaration; return declaration;
} }
@ -43,12 +43,12 @@ namespace ts {
} }
// Pool writers to avoid needing to allocate them for every symbol we write. // Pool writers to avoid needing to allocate them for every symbol we write.
let stringWriters: StringSymbolWriter[] = []; const stringWriters: StringSymbolWriter[] = [];
export function getSingleLineStringWriter(): StringSymbolWriter { export function getSingleLineStringWriter(): StringSymbolWriter {
if (stringWriters.length === 0) { if (stringWriters.length === 0) {
let str = ""; let str = "";
let writeText: (text: string) => void = text => str += text; const writeText: (text: string) => void = text => str += text;
return { return {
string: () => str, string: () => str,
writeKeyword: writeText, writeKeyword: writeText,
@ -92,7 +92,7 @@ namespace ts {
} }
for (let i = 0; i < array1.length; ++i) { for (let i = 0; i < array1.length; ++i) {
let equals = equaler ? equaler(array1[i], array2[i]) : array1[i] === array2[i]; const equals = equaler ? equaler(array1[i], array2[i]) : array1[i] === array2[i];
if (!equals) { if (!equals) {
return false; return false;
} }
@ -128,7 +128,7 @@ namespace ts {
// A node is considered to contain a parse error if: // A node is considered to contain a parse error if:
// a) the parser explicitly marked that it had an error // a) the parser explicitly marked that it had an error
// b) any of it's children reported that it had an error. // b) any of it's children reported that it had an error.
let thisNodeOrAnySubNodesHasError = ((node.parserContextFlags & ParserContextFlags.ThisNodeHasError) !== 0) || const thisNodeOrAnySubNodesHasError = ((node.parserContextFlags & ParserContextFlags.ThisNodeHasError) !== 0) ||
forEachChild(node, containsParseError); forEachChild(node, containsParseError);
// If so, mark ourselves accordingly. // If so, mark ourselves accordingly.
@ -157,8 +157,8 @@ namespace ts {
// This is a useful function for debugging purposes. // This is a useful function for debugging purposes.
export function nodePosToString(node: Node): string { export function nodePosToString(node: Node): string {
let file = getSourceFileOfNode(node); const file = getSourceFileOfNode(node);
let loc = getLineAndCharacterOfPosition(file, node.pos); const loc = getLineAndCharacterOfPosition(file, node.pos);
return `${ file.fileName }(${ loc.line + 1 },${ loc.character + 1 })`; return `${ file.fileName }(${ loc.line + 1 },${ loc.character + 1 })`;
} }
@ -213,7 +213,7 @@ namespace ts {
return ""; return "";
} }
let text = sourceFile.text; const text = sourceFile.text;
return text.substring(includeTrivia ? node.pos : skipTrivia(text, node.pos), node.end); return text.substring(includeTrivia ? node.pos : skipTrivia(text, node.pos), node.end);
} }
@ -294,14 +294,14 @@ namespace ts {
} }
export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): Diagnostic { export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): Diagnostic {
let sourceFile = getSourceFileOfNode(node); const sourceFile = getSourceFileOfNode(node);
let span = getErrorSpanForNode(sourceFile, node); const span = getErrorSpanForNode(sourceFile, node);
return createFileDiagnostic(sourceFile, span.start, span.length, message, arg0, arg1, arg2); return createFileDiagnostic(sourceFile, span.start, span.length, message, arg0, arg1, arg2);
} }
export function createDiagnosticForNodeFromMessageChain(node: Node, messageChain: DiagnosticMessageChain): Diagnostic { export function createDiagnosticForNodeFromMessageChain(node: Node, messageChain: DiagnosticMessageChain): Diagnostic {
let sourceFile = getSourceFileOfNode(node); const sourceFile = getSourceFileOfNode(node);
let span = getErrorSpanForNode(sourceFile, node); const span = getErrorSpanForNode(sourceFile, node);
return { return {
file: sourceFile, file: sourceFile,
start: span.start, start: span.start,
@ -313,9 +313,9 @@ namespace ts {
} }
export function getSpanOfTokenAtPosition(sourceFile: SourceFile, pos: number): TextSpan { export function getSpanOfTokenAtPosition(sourceFile: SourceFile, pos: number): TextSpan {
let scanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/ true, sourceFile.languageVariant, sourceFile.text, /*onError:*/ undefined, pos); const scanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/ true, sourceFile.languageVariant, sourceFile.text, /*onError:*/ undefined, pos);
scanner.scan(); scanner.scan();
let start = scanner.getTokenPos(); const start = scanner.getTokenPos();
return createTextSpanFromBounds(start, scanner.getTextPos()); return createTextSpanFromBounds(start, scanner.getTextPos());
} }
@ -351,7 +351,7 @@ namespace ts {
return getSpanOfTokenAtPosition(sourceFile, node.pos); return getSpanOfTokenAtPosition(sourceFile, node.pos);
} }
let pos = nodeIsMissing(errorNode) const pos = nodeIsMissing(errorNode)
? errorNode.pos ? errorNode.pos
: skipTrivia(sourceFile.text, errorNode.pos); : skipTrivia(sourceFile.text, errorNode.pos);
@ -421,18 +421,26 @@ namespace ts {
return getLeadingCommentRanges(sourceFileOfNode.text, node.pos); return getLeadingCommentRanges(sourceFileOfNode.text, node.pos);
} }
export function getLeadingCommentRangesOfNodeFromText(node: Node, text: string) {
return getLeadingCommentRanges(text, node.pos);
}
export function getJsDocComments(node: Node, sourceFileOfNode: SourceFile) { export function getJsDocComments(node: Node, sourceFileOfNode: SourceFile) {
let commentRanges = (node.kind === SyntaxKind.Parameter || node.kind === SyntaxKind.TypeParameter) ? return getJsDocCommentsFromText(node, sourceFileOfNode.text);
concatenate(getTrailingCommentRanges(sourceFileOfNode.text, node.pos), }
getLeadingCommentRanges(sourceFileOfNode.text, node.pos)) :
getLeadingCommentRangesOfNode(node, sourceFileOfNode); export function getJsDocCommentsFromText(node: Node, text: string) {
const commentRanges = (node.kind === SyntaxKind.Parameter || node.kind === SyntaxKind.TypeParameter) ?
concatenate(getTrailingCommentRanges(text, node.pos),
getLeadingCommentRanges(text, node.pos)) :
getLeadingCommentRangesOfNodeFromText(node, text);
return filter(commentRanges, isJsDocComment); return filter(commentRanges, isJsDocComment);
function isJsDocComment(comment: CommentRange) { function isJsDocComment(comment: CommentRange) {
// True if the comment starts with '/**' but not if it is '/**/' // True if the comment starts with '/**' but not if it is '/**/'
return sourceFileOfNode.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk && return text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk &&
sourceFileOfNode.text.charCodeAt(comment.pos + 2) === CharacterCodes.asterisk && text.charCodeAt(comment.pos + 2) === CharacterCodes.asterisk &&
sourceFileOfNode.text.charCodeAt(comment.pos + 3) !== CharacterCodes.slash; text.charCodeAt(comment.pos + 3) !== CharacterCodes.slash;
} }
} }
@ -579,7 +587,7 @@ namespace ts {
return; return;
default: default:
if (isFunctionLike(node)) { if (isFunctionLike(node)) {
let name = (<FunctionLikeDeclaration>node).name; const name = (<FunctionLikeDeclaration>node).name;
if (name && name.kind === SyntaxKind.ComputedPropertyName) { if (name && name.kind === SyntaxKind.ComputedPropertyName) {
// Note that we will not include methods/accessors of a class because they would require // Note that we will not include methods/accessors of a class because they would require
// first descending into the class. This is by design. // first descending into the class. This is by design.
@ -1030,7 +1038,7 @@ namespace ts {
} }
export function isInstantiatedModule(node: ModuleDeclaration, preserveConstEnums: boolean) { export function isInstantiatedModule(node: ModuleDeclaration, preserveConstEnums: boolean) {
let moduleState = getModuleInstanceState(node); const moduleState = getModuleInstanceState(node);
return moduleState === ModuleInstanceState.Instantiated || return moduleState === ModuleInstanceState.Instantiated ||
(preserveConstEnums && moduleState === ModuleInstanceState.ConstEnumOnly); (preserveConstEnums && moduleState === ModuleInstanceState.ConstEnumOnly);
} }
@ -1053,7 +1061,7 @@ namespace ts {
return (<ImportDeclaration>node).moduleSpecifier; return (<ImportDeclaration>node).moduleSpecifier;
} }
if (node.kind === SyntaxKind.ImportEqualsDeclaration) { if (node.kind === SyntaxKind.ImportEqualsDeclaration) {
let reference = (<ImportEqualsDeclaration>node).moduleReference; const reference = (<ImportEqualsDeclaration>node).moduleReference;
if (reference.kind === SyntaxKind.ExternalModuleReference) { if (reference.kind === SyntaxKind.ExternalModuleReference) {
return (<ExternalModuleReference>reference).expression; return (<ExternalModuleReference>reference).expression;
} }
@ -1088,7 +1096,7 @@ namespace ts {
function getJSDocTag(node: Node, kind: SyntaxKind): JSDocTag { function getJSDocTag(node: Node, kind: SyntaxKind): JSDocTag {
if (node && node.jsDocComment) { if (node && node.jsDocComment) {
for (let tag of node.jsDocComment.tags) { for (const tag of node.jsDocComment.tags) {
if (tag.kind === kind) { if (tag.kind === kind) {
return tag; return tag;
} }
@ -1112,14 +1120,14 @@ namespace ts {
if (parameter.name && parameter.name.kind === SyntaxKind.Identifier) { if (parameter.name && parameter.name.kind === SyntaxKind.Identifier) {
// If it's a parameter, see if the parent has a jsdoc comment with an @param // If it's a parameter, see if the parent has a jsdoc comment with an @param
// annotation. // annotation.
let parameterName = (<Identifier>parameter.name).text; const parameterName = (<Identifier>parameter.name).text;
let docComment = parameter.parent.jsDocComment; const docComment = parameter.parent.jsDocComment;
if (docComment) { if (docComment) {
return <JSDocParameterTag>forEach(docComment.tags, t => { return <JSDocParameterTag>forEach(docComment.tags, t => {
if (t.kind === SyntaxKind.JSDocParameterTag) { if (t.kind === SyntaxKind.JSDocParameterTag) {
let parameterTag = <JSDocParameterTag>t; const parameterTag = <JSDocParameterTag>t;
let name = parameterTag.preParameterName || parameterTag.postParameterName; const name = parameterTag.preParameterName || parameterTag.postParameterName;
if (name.text === parameterName) { if (name.text === parameterName) {
return t; return t;
} }
@ -1140,7 +1148,7 @@ namespace ts {
return true; return true;
} }
let paramTag = getCorrespondingJSDocParameterTag(node); const paramTag = getCorrespondingJSDocParameterTag(node);
if (paramTag && paramTag.typeExpression) { if (paramTag && paramTag.typeExpression) {
return paramTag.typeExpression.type.kind === SyntaxKind.JSDocVariadicType; return paramTag.typeExpression.type.kind === SyntaxKind.JSDocVariadicType;
} }
@ -1270,7 +1278,7 @@ namespace ts {
return false; return false;
} }
let parent = name.parent; const parent = name.parent;
if (parent.kind === SyntaxKind.ImportSpecifier || parent.kind === SyntaxKind.ExportSpecifier) { if (parent.kind === SyntaxKind.ImportSpecifier || parent.kind === SyntaxKind.ExportSpecifier) {
if ((<ImportOrExportSpecifier>parent).propertyName) { if ((<ImportOrExportSpecifier>parent).propertyName) {
return true; return true;
@ -1337,23 +1345,23 @@ namespace ts {
} }
export function getClassExtendsHeritageClauseElement(node: ClassLikeDeclaration) { export function getClassExtendsHeritageClauseElement(node: ClassLikeDeclaration) {
let heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ExtendsKeyword); const heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ExtendsKeyword);
return heritageClause && heritageClause.types.length > 0 ? heritageClause.types[0] : undefined; return heritageClause && heritageClause.types.length > 0 ? heritageClause.types[0] : undefined;
} }
export function getClassImplementsHeritageClauseElements(node: ClassLikeDeclaration) { export function getClassImplementsHeritageClauseElements(node: ClassLikeDeclaration) {
let heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ImplementsKeyword); const heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ImplementsKeyword);
return heritageClause ? heritageClause.types : undefined; return heritageClause ? heritageClause.types : undefined;
} }
export function getInterfaceBaseTypeNodes(node: InterfaceDeclaration) { export function getInterfaceBaseTypeNodes(node: InterfaceDeclaration) {
let heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ExtendsKeyword); const heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ExtendsKeyword);
return heritageClause ? heritageClause.types : undefined; return heritageClause ? heritageClause.types : undefined;
} }
export function getHeritageClause(clauses: NodeArray<HeritageClause>, kind: SyntaxKind) { export function getHeritageClause(clauses: NodeArray<HeritageClause>, kind: SyntaxKind) {
if (clauses) { if (clauses) {
for (let clause of clauses) { for (const clause of clauses) {
if (clause.token === kind) { if (clause.token === kind) {
return clause; return clause;
} }
@ -1365,7 +1373,7 @@ namespace ts {
export function tryResolveScriptReference(host: ScriptReferenceHost, sourceFile: SourceFile, reference: FileReference) { export function tryResolveScriptReference(host: ScriptReferenceHost, sourceFile: SourceFile, reference: FileReference) {
if (!host.getCompilerOptions().noResolve) { if (!host.getCompilerOptions().noResolve) {
let referenceFileName = isRootedDiskPath(reference.fileName) ? reference.fileName : combinePaths(getDirectoryPath(sourceFile.fileName), reference.fileName); const referenceFileName = isRootedDiskPath(reference.fileName) ? reference.fileName : combinePaths(getDirectoryPath(sourceFile.fileName), reference.fileName);
return host.getSourceFile(referenceFileName); return host.getSourceFile(referenceFileName);
} }
} }
@ -1381,19 +1389,19 @@ namespace ts {
} }
export function getFileReferenceFromReferencePath(comment: string, commentRange: CommentRange): ReferencePathMatchResult { export function getFileReferenceFromReferencePath(comment: string, commentRange: CommentRange): ReferencePathMatchResult {
let simpleReferenceRegEx = /^\/\/\/\s*<reference\s+/gim; const simpleReferenceRegEx = /^\/\/\/\s*<reference\s+/gim;
let isNoDefaultLibRegEx = /^(\/\/\/\s*<reference\s+no-default-lib\s*=\s*)('|")(.+?)\2\s*\/>/gim; const isNoDefaultLibRegEx = /^(\/\/\/\s*<reference\s+no-default-lib\s*=\s*)('|")(.+?)\2\s*\/>/gim;
if (simpleReferenceRegEx.exec(comment)) { if (simpleReferenceRegEx.test(comment)) {
if (isNoDefaultLibRegEx.exec(comment)) { if (isNoDefaultLibRegEx.test(comment)) {
return { return {
isNoDefaultLib: true isNoDefaultLib: true
}; };
} }
else { else {
let matchResult = fullTripleSlashReferencePathRegEx.exec(comment); const matchResult = fullTripleSlashReferencePathRegEx.exec(comment);
if (matchResult) { if (matchResult) {
let start = commentRange.pos; const start = commentRange.pos;
let end = commentRange.end; const end = commentRange.end;
return { return {
fileReference: { fileReference: {
pos: start, pos: start,
@ -1454,9 +1462,9 @@ namespace ts {
return (<Identifier | LiteralExpression>name).text; return (<Identifier | LiteralExpression>name).text;
} }
if (name.kind === SyntaxKind.ComputedPropertyName) { if (name.kind === SyntaxKind.ComputedPropertyName) {
let nameExpression = (<ComputedPropertyName>name).expression; const nameExpression = (<ComputedPropertyName>name).expression;
if (isWellKnownSymbolSyntactically(nameExpression)) { if (isWellKnownSymbolSyntactically(nameExpression)) {
let rightHandSideName = (<PropertyAccessExpression>nameExpression).name.text; const rightHandSideName = (<PropertyAccessExpression>nameExpression).name.text;
return getPropertyNameForKnownSymbolName(rightHandSideName); return getPropertyNameForKnownSymbolName(rightHandSideName);
} }
} }
@ -1493,7 +1501,7 @@ namespace ts {
} }
export function isParameterDeclaration(node: VariableLikeDeclaration) { export function isParameterDeclaration(node: VariableLikeDeclaration) {
let root = getRootDeclaration(node); const root = getRootDeclaration(node);
return root.kind === SyntaxKind.Parameter; return root.kind === SyntaxKind.Parameter;
} }
@ -1510,12 +1518,12 @@ namespace ts {
export function cloneEntityName(node: EntityName): EntityName { export function cloneEntityName(node: EntityName): EntityName {
if (node.kind === SyntaxKind.Identifier) { if (node.kind === SyntaxKind.Identifier) {
let clone = <Identifier>createSynthesizedNode(SyntaxKind.Identifier); const clone = <Identifier>createSynthesizedNode(SyntaxKind.Identifier);
clone.text = (<Identifier>node).text; clone.text = (<Identifier>node).text;
return clone; return clone;
} }
else { else {
let clone = <QualifiedName>createSynthesizedNode(SyntaxKind.QualifiedName); const clone = <QualifiedName>createSynthesizedNode(SyntaxKind.QualifiedName);
clone.left = cloneEntityName((<QualifiedName>node).left); clone.left = cloneEntityName((<QualifiedName>node).left);
clone.left.parent = clone; clone.left.parent = clone;
clone.right = <Identifier>cloneEntityName((<QualifiedName>node).right); clone.right = <Identifier>cloneEntityName((<QualifiedName>node).right);
@ -1529,13 +1537,13 @@ namespace ts {
} }
export function createSynthesizedNode(kind: SyntaxKind, startsOnNewLine?: boolean): Node { export function createSynthesizedNode(kind: SyntaxKind, startsOnNewLine?: boolean): Node {
let node = <SynthesizedNode>createNode(kind, /* pos */ -1, /* end */ -1); const node = <SynthesizedNode>createNode(kind, /* pos */ -1, /* end */ -1);
node.startsOnNewLine = startsOnNewLine; node.startsOnNewLine = startsOnNewLine;
return node; return node;
} }
export function createSynthesizedNodeArray(): NodeArray<any> { export function createSynthesizedNodeArray(): NodeArray<any> {
let array = <NodeArray<any>>[]; const array = <NodeArray<any>>[];
array.pos = -1; array.pos = -1;
array.end = -1; array.end = -1;
return array; return array;
@ -1543,7 +1551,7 @@ namespace ts {
export function createDiagnosticCollection(): DiagnosticCollection { export function createDiagnosticCollection(): DiagnosticCollection {
let nonFileDiagnostics: Diagnostic[] = []; let nonFileDiagnostics: Diagnostic[] = [];
let fileDiagnostics: Map<Diagnostic[]> = {}; const fileDiagnostics: Map<Diagnostic[]> = {};
let diagnosticsModified = false; let diagnosticsModified = false;
let modificationCount = 0; let modificationCount = 0;
@ -1565,7 +1573,7 @@ namespace ts {
return; return;
} }
for (let diagnostic of fileDiagnostics[newFile.fileName]) { for (const diagnostic of fileDiagnostics[newFile.fileName]) {
diagnostic.file = newFile; diagnostic.file = newFile;
} }
} }
@ -1599,14 +1607,14 @@ namespace ts {
return fileDiagnostics[fileName] || []; return fileDiagnostics[fileName] || [];
} }
let allDiagnostics: Diagnostic[] = []; const allDiagnostics: Diagnostic[] = [];
function pushDiagnostic(d: Diagnostic) { function pushDiagnostic(d: Diagnostic) {
allDiagnostics.push(d); allDiagnostics.push(d);
} }
forEach(nonFileDiagnostics, pushDiagnostic); forEach(nonFileDiagnostics, pushDiagnostic);
for (let key in fileDiagnostics) { for (const key in fileDiagnostics) {
if (hasProperty(fileDiagnostics, key)) { if (hasProperty(fileDiagnostics, key)) {
forEach(fileDiagnostics[key], pushDiagnostic); forEach(fileDiagnostics[key], pushDiagnostic);
} }
@ -1623,7 +1631,7 @@ namespace ts {
diagnosticsModified = false; diagnosticsModified = false;
nonFileDiagnostics = sortAndDeduplicateDiagnostics(nonFileDiagnostics); nonFileDiagnostics = sortAndDeduplicateDiagnostics(nonFileDiagnostics);
for (let key in fileDiagnostics) { for (const key in fileDiagnostics) {
if (hasProperty(fileDiagnostics, key)) { if (hasProperty(fileDiagnostics, key)) {
fileDiagnostics[key] = sortAndDeduplicateDiagnostics(fileDiagnostics[key]); fileDiagnostics[key] = sortAndDeduplicateDiagnostics(fileDiagnostics[key]);
} }
@ -1636,8 +1644,8 @@ namespace ts {
// the language service. These characters should be escaped when printing, and if any characters are added, // the language service. These characters should be escaped when printing, and if any characters are added,
// the map below must be updated. Note that this regexp *does not* include the 'delete' character. // the map below must be updated. Note that this regexp *does not* include the 'delete' character.
// There is no reason for this other than that JSON.stringify does not handle it either. // There is no reason for this other than that JSON.stringify does not handle it either.
let escapedCharsRegExp = /[\\\"\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g; const escapedCharsRegExp = /[\\\"\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
let escapedCharsMap: Map<string> = { const escapedCharsMap: Map<string> = {
"\0": "\\0", "\0": "\\0",
"\t": "\\t", "\t": "\\t",
"\v": "\\v", "\v": "\\v",
@ -1669,17 +1677,17 @@ namespace ts {
} }
export function isIntrinsicJsxName(name: string) { export function isIntrinsicJsxName(name: string) {
let ch = name.substr(0, 1); const ch = name.substr(0, 1);
return ch.toLowerCase() === ch; return ch.toLowerCase() === ch;
} }
function get16BitUnicodeEscapeSequence(charCode: number): string { function get16BitUnicodeEscapeSequence(charCode: number): string {
let hexCharCode = charCode.toString(16).toUpperCase(); const hexCharCode = charCode.toString(16).toUpperCase();
let paddedHexCode = ("0000" + hexCharCode).slice(-4); const paddedHexCode = ("0000" + hexCharCode).slice(-4);
return "\\u" + paddedHexCode; return "\\u" + paddedHexCode;
} }
let nonAsciiCharacters = /[^\u0000-\u007F]/g; const nonAsciiCharacters = /[^\u0000-\u007F]/g;
export function escapeNonAsciiCharacters(s: string): string { export function escapeNonAsciiCharacters(s: string): string {
// Replace non-ASCII characters with '\uNNNN' escapes if any exist. // Replace non-ASCII characters with '\uNNNN' escapes if any exist.
// Otherwise just return the original string. // Otherwise just return the original string.
@ -1690,7 +1698,7 @@ namespace ts {
export interface EmitTextWriter { export interface EmitTextWriter {
write(s: string): void; write(s: string): void;
writeTextOfNode(sourceFile: SourceFile, node: Node): void; writeTextOfNode(text: string, node: Node): void;
writeLine(): void; writeLine(): void;
increaseIndent(): void; increaseIndent(): void;
decreaseIndent(): void; decreaseIndent(): void;
@ -1701,9 +1709,10 @@ namespace ts {
getLine(): number; getLine(): number;
getColumn(): number; getColumn(): number;
getIndent(): number; getIndent(): number;
reset(): void;
} }
let indentStrings: string[] = ["", " "]; const indentStrings: string[] = ["", " "];
export function getIndentString(level: number) { export function getIndentString(level: number) {
if (indentStrings[level] === undefined) { if (indentStrings[level] === undefined) {
indentStrings[level] = getIndentString(level - 1) + indentStrings[1]; indentStrings[level] = getIndentString(level - 1) + indentStrings[1];
@ -1716,11 +1725,11 @@ namespace ts {
} }
export function createTextWriter(newLine: String): EmitTextWriter { export function createTextWriter(newLine: String): EmitTextWriter {
let output = ""; let output: string;
let indent = 0; let indent: number;
let lineStart = true; let lineStart: boolean;
let lineCount = 0; let lineCount: number;
let linePos = 0; let linePos: number;
function write(s: string) { function write(s: string) {
if (s && s.length) { if (s && s.length) {
@ -1732,6 +1741,14 @@ namespace ts {
} }
} }
function reset(): void {
output = "";
indent = 0;
lineStart = true;
lineCount = 0;
linePos = 0;
}
function rawWrite(s: string) { function rawWrite(s: string) {
if (s !== undefined) { if (s !== undefined) {
if (lineStart) { if (lineStart) {
@ -1744,7 +1761,7 @@ namespace ts {
function writeLiteral(s: string) { function writeLiteral(s: string) {
if (s && s.length) { if (s && s.length) {
write(s); write(s);
let lineStartsOfS = computeLineStarts(s); const lineStartsOfS = computeLineStarts(s);
if (lineStartsOfS.length > 1) { if (lineStartsOfS.length > 1) {
lineCount = lineCount + lineStartsOfS.length - 1; lineCount = lineCount + lineStartsOfS.length - 1;
linePos = output.length - s.length + lastOrUndefined(lineStartsOfS); linePos = output.length - s.length + lastOrUndefined(lineStartsOfS);
@ -1761,10 +1778,12 @@ namespace ts {
} }
} }
function writeTextOfNode(sourceFile: SourceFile, node: Node) { function writeTextOfNode(text: string, node: Node) {
write(getSourceTextOfNodeFromSourceFile(sourceFile, node)); write(getTextOfNodeFromSourceText(text, node));
} }
reset();
return { return {
write, write,
rawWrite, rawWrite,
@ -1778,6 +1797,7 @@ namespace ts {
getLine: () => lineCount + 1, getLine: () => lineCount + 1,
getColumn: () => lineStart ? indent * getIndentSize() + 1 : output.length - linePos + 1, getColumn: () => lineStart ? indent * getIndentSize() + 1 : output.length - linePos + 1,
getText: () => output, getText: () => output,
reset
}; };
} }
@ -1791,7 +1811,7 @@ namespace ts {
} }
export function getOwnEmitOutputFilePath(sourceFile: SourceFile, host: EmitHost, extension: string) { export function getOwnEmitOutputFilePath(sourceFile: SourceFile, host: EmitHost, extension: string) {
let compilerOptions = host.getCompilerOptions(); const compilerOptions = host.getCompilerOptions();
let emitOutputFilePathWithoutExtension: string; let emitOutputFilePathWithoutExtension: string;
if (compilerOptions.outDir) { if (compilerOptions.outDir) {
emitOutputFilePathWithoutExtension = removeFileExtension(getSourceFilePathInNewDir(sourceFile, host, compilerOptions.outDir)); emitOutputFilePathWithoutExtension = removeFileExtension(getSourceFilePathInNewDir(sourceFile, host, compilerOptions.outDir));
@ -1819,6 +1839,10 @@ namespace ts {
return getLineAndCharacterOfPosition(currentSourceFile, pos).line; return getLineAndCharacterOfPosition(currentSourceFile, pos).line;
} }
export function getLineOfLocalPositionFromLineMap(lineMap: number[], pos: number) {
return computeLineAndCharacterOfPosition(lineMap, pos).line;
}
export function getFirstConstructorWithBody(node: ClassLikeDeclaration): ConstructorDeclaration { export function getFirstConstructorWithBody(node: ClassLikeDeclaration): ConstructorDeclaration {
return forEach(node.members, member => { return forEach(node.members, member => {
if (member.kind === SyntaxKind.Constructor && nodeIsPresent((<ConstructorDeclaration>member).body)) { if (member.kind === SyntaxKind.Constructor && nodeIsPresent((<ConstructorDeclaration>member).body)) {
@ -1864,8 +1888,8 @@ namespace ts {
forEach(declarations, (member: Declaration) => { forEach(declarations, (member: Declaration) => {
if ((member.kind === SyntaxKind.GetAccessor || member.kind === SyntaxKind.SetAccessor) if ((member.kind === SyntaxKind.GetAccessor || member.kind === SyntaxKind.SetAccessor)
&& (member.flags & NodeFlags.Static) === (accessor.flags & NodeFlags.Static)) { && (member.flags & NodeFlags.Static) === (accessor.flags & NodeFlags.Static)) {
let memberName = getPropertyNameForPropertyNameNode(member.name); const memberName = getPropertyNameForPropertyNameNode(member.name);
let accessorName = getPropertyNameForPropertyNameNode(accessor.name); const accessorName = getPropertyNameForPropertyNameNode(accessor.name);
if (memberName === accessorName) { if (memberName === accessorName) {
if (!firstAccessor) { if (!firstAccessor) {
firstAccessor = <AccessorDeclaration>member; firstAccessor = <AccessorDeclaration>member;
@ -1893,23 +1917,23 @@ namespace ts {
}; };
} }
export function emitNewLineBeforeLeadingComments(currentSourceFile: SourceFile, writer: EmitTextWriter, node: TextRange, leadingComments: CommentRange[]) { export function emitNewLineBeforeLeadingComments(lineMap: number[], writer: EmitTextWriter, node: TextRange, leadingComments: CommentRange[]) {
// If the leading comments start on different line than the start of node, write new line // If the leading comments start on different line than the start of node, write new line
if (leadingComments && leadingComments.length && node.pos !== leadingComments[0].pos && if (leadingComments && leadingComments.length && node.pos !== leadingComments[0].pos &&
getLineOfLocalPosition(currentSourceFile, node.pos) !== getLineOfLocalPosition(currentSourceFile, leadingComments[0].pos)) { getLineOfLocalPositionFromLineMap(lineMap, node.pos) !== getLineOfLocalPositionFromLineMap(lineMap, leadingComments[0].pos)) {
writer.writeLine(); writer.writeLine();
} }
} }
export function emitComments(currentSourceFile: SourceFile, writer: EmitTextWriter, comments: CommentRange[], trailingSeparator: boolean, newLine: string, export function emitComments(text: string, lineMap: number[], writer: EmitTextWriter, comments: CommentRange[], trailingSeparator: boolean, newLine: string,
writeComment: (currentSourceFile: SourceFile, writer: EmitTextWriter, comment: CommentRange, newLine: string) => void) { writeComment: (text: string, lineMap: number[], writer: EmitTextWriter, comment: CommentRange, newLine: string) => void) {
let emitLeadingSpace = !trailingSeparator; let emitLeadingSpace = !trailingSeparator;
forEach(comments, comment => { forEach(comments, comment => {
if (emitLeadingSpace) { if (emitLeadingSpace) {
writer.write(" "); writer.write(" ");
emitLeadingSpace = false; emitLeadingSpace = false;
} }
writeComment(currentSourceFile, writer, comment, newLine); writeComment(text, lineMap, writer, comment, newLine);
if (comment.hasTrailingNewLine) { if (comment.hasTrailingNewLine) {
writer.writeLine(); writer.writeLine();
} }
@ -1927,8 +1951,8 @@ namespace ts {
* Detached comment is a comment at the top of file or function body that is separated from * Detached comment is a comment at the top of file or function body that is separated from
* the next statement by space. * the next statement by space.
*/ */
export function emitDetachedComments(currentSourceFile: SourceFile, writer: EmitTextWriter, export function emitDetachedComments(text: string, lineMap: number[], writer: EmitTextWriter,
writeComment: (currentSourceFile: SourceFile, writer: EmitTextWriter, comment: CommentRange, newLine: string) => void, writeComment: (text: string, lineMap: number[], writer: EmitTextWriter, comment: CommentRange, newLine: string) => void,
node: TextRange, newLine: string, removeComments: boolean) { node: TextRange, newLine: string, removeComments: boolean) {
let leadingComments: CommentRange[]; let leadingComments: CommentRange[];
let currentDetachedCommentInfo: {nodePos: number, detachedCommentEndPos: number}; let currentDetachedCommentInfo: {nodePos: number, detachedCommentEndPos: number};
@ -1939,22 +1963,22 @@ namespace ts {
// //
// var x = 10; // var x = 10;
if (node.pos === 0) { if (node.pos === 0) {
leadingComments = filter(getLeadingCommentRanges(currentSourceFile.text, node.pos), isPinnedComment); leadingComments = filter(getLeadingCommentRanges(text, node.pos), isPinnedComment);
} }
} }
else { else {
// removeComments is false, just get detached as normal and bypass the process to filter comment // removeComments is false, just get detached as normal and bypass the process to filter comment
leadingComments = getLeadingCommentRanges(currentSourceFile.text, node.pos); leadingComments = getLeadingCommentRanges(text, node.pos);
} }
if (leadingComments) { if (leadingComments) {
let detachedComments: CommentRange[] = []; const detachedComments: CommentRange[] = [];
let lastComment: CommentRange; let lastComment: CommentRange;
for (let comment of leadingComments) { for (const comment of leadingComments) {
if (lastComment) { if (lastComment) {
let lastCommentLine = getLineOfLocalPosition(currentSourceFile, lastComment.end); const lastCommentLine = getLineOfLocalPositionFromLineMap(lineMap, lastComment.end);
let commentLine = getLineOfLocalPosition(currentSourceFile, comment.pos); const commentLine = getLineOfLocalPositionFromLineMap(lineMap, comment.pos);
if (commentLine >= lastCommentLine + 2) { if (commentLine >= lastCommentLine + 2) {
// There was a blank line between the last comment and this comment. This // There was a blank line between the last comment and this comment. This
@ -1972,12 +1996,12 @@ namespace ts {
// All comments look like they could have been part of the copyright header. Make // All comments look like they could have been part of the copyright header. Make
// sure there is at least one blank line between it and the node. If not, it's not // sure there is at least one blank line between it and the node. If not, it's not
// a copyright header. // a copyright header.
let lastCommentLine = getLineOfLocalPosition(currentSourceFile, lastOrUndefined(detachedComments).end); const lastCommentLine = getLineOfLocalPositionFromLineMap(lineMap, lastOrUndefined(detachedComments).end);
let nodeLine = getLineOfLocalPosition(currentSourceFile, skipTrivia(currentSourceFile.text, node.pos)); const nodeLine = getLineOfLocalPositionFromLineMap(lineMap, skipTrivia(text, node.pos));
if (nodeLine >= lastCommentLine + 2) { if (nodeLine >= lastCommentLine + 2) {
// Valid detachedComments // Valid detachedComments
emitNewLineBeforeLeadingComments(currentSourceFile, writer, node, leadingComments); emitNewLineBeforeLeadingComments(lineMap, writer, node, leadingComments);
emitComments(currentSourceFile, writer, detachedComments, /*trailingSeparator*/ true, newLine, writeComment); emitComments(text, lineMap, writer, detachedComments, /*trailingSeparator*/ true, newLine, writeComment);
currentDetachedCommentInfo = { nodePos: node.pos, detachedCommentEndPos: lastOrUndefined(detachedComments).end }; currentDetachedCommentInfo = { nodePos: node.pos, detachedCommentEndPos: lastOrUndefined(detachedComments).end };
} }
} }
@ -1986,29 +2010,30 @@ namespace ts {
return currentDetachedCommentInfo; return currentDetachedCommentInfo;
function isPinnedComment(comment: CommentRange) { function isPinnedComment(comment: CommentRange) {
return currentSourceFile.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk && return text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk &&
currentSourceFile.text.charCodeAt(comment.pos + 2) === CharacterCodes.exclamation; text.charCodeAt(comment.pos + 2) === CharacterCodes.exclamation;
}
} }
export function writeCommentRange(currentSourceFile: SourceFile, writer: EmitTextWriter, comment: CommentRange, newLine: string) { }
if (currentSourceFile.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk) {
let firstCommentLineAndCharacter = getLineAndCharacterOfPosition(currentSourceFile, comment.pos); export function writeCommentRange(text: string, lineMap: number[], writer: EmitTextWriter, comment: CommentRange, newLine: string) {
let lineCount = getLineStarts(currentSourceFile).length; if (text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk) {
const firstCommentLineAndCharacter = computeLineAndCharacterOfPosition(lineMap, comment.pos);
const lineCount = lineMap.length;
let firstCommentLineIndent: number; let firstCommentLineIndent: number;
for (let pos = comment.pos, currentLine = firstCommentLineAndCharacter.line; pos < comment.end; currentLine++) { for (let pos = comment.pos, currentLine = firstCommentLineAndCharacter.line; pos < comment.end; currentLine++) {
let nextLineStart = (currentLine + 1) === lineCount const nextLineStart = (currentLine + 1) === lineCount
? currentSourceFile.text.length + 1 ? text.length + 1
: getStartPositionOfLine(currentLine + 1, currentSourceFile); : lineMap[currentLine + 1];
if (pos !== comment.pos) { if (pos !== comment.pos) {
// If we are not emitting first line, we need to write the spaces to adjust the alignment // If we are not emitting first line, we need to write the spaces to adjust the alignment
if (firstCommentLineIndent === undefined) { if (firstCommentLineIndent === undefined) {
firstCommentLineIndent = calculateIndent(getStartPositionOfLine(firstCommentLineAndCharacter.line, currentSourceFile), comment.pos); firstCommentLineIndent = calculateIndent(text, lineMap[firstCommentLineAndCharacter.line], comment.pos);
} }
// These are number of spaces writer is going to write at current indent // These are number of spaces writer is going to write at current indent
let currentWriterIndentSpacing = writer.getIndent() * getIndentSize(); const currentWriterIndentSpacing = writer.getIndent() * getIndentSize();
// Number of spaces we want to be writing // Number of spaces we want to be writing
// eg: Assume writer indent // eg: Assume writer indent
@ -2024,10 +2049,10 @@ namespace ts {
// More right indented comment */ --4 = 8 - 4 + 11 // More right indented comment */ --4 = 8 - 4 + 11
// class c { } // class c { }
// } // }
let spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + calculateIndent(pos, nextLineStart); const spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + calculateIndent(text, pos, nextLineStart);
if (spacesToEmit > 0) { if (spacesToEmit > 0) {
let numberOfSingleSpacesToEmit = spacesToEmit % getIndentSize(); let numberOfSingleSpacesToEmit = spacesToEmit % getIndentSize();
let indentSizeSpaceString = getIndentString((spacesToEmit - numberOfSingleSpacesToEmit) / getIndentSize()); const indentSizeSpaceString = getIndentString((spacesToEmit - numberOfSingleSpacesToEmit) / getIndentSize());
// Write indent size string ( in eg 1: = "", 2: "" , 3: string with 8 spaces 4: string with 12 spaces // Write indent size string ( in eg 1: = "", 2: "" , 3: string with 8 spaces 4: string with 12 spaces
writer.rawWrite(indentSizeSpaceString); writer.rawWrite(indentSizeSpaceString);
@ -2045,19 +2070,20 @@ namespace ts {
} }
// Write the comment line text // Write the comment line text
writeTrimmedCurrentLine(pos, nextLineStart); writeTrimmedCurrentLine(text, comment, writer, newLine, pos, nextLineStart);
pos = nextLineStart; pos = nextLineStart;
} }
} }
else { else {
// Single line comment of style //.... // Single line comment of style //....
writer.write(currentSourceFile.text.substring(comment.pos, comment.end)); writer.write(text.substring(comment.pos, comment.end));
}
} }
function writeTrimmedCurrentLine(pos: number, nextLineStart: number) { function writeTrimmedCurrentLine(text: string, comment: CommentRange, writer: EmitTextWriter, newLine: string, pos: number, nextLineStart: number) {
let end = Math.min(comment.end, nextLineStart - 1); const end = Math.min(comment.end, nextLineStart - 1);
let currentLineText = currentSourceFile.text.substring(pos, end).replace(/^\s+|\s+$/g, ""); const currentLineText = text.substring(pos, end).replace(/^\s+|\s+$/g, "");
if (currentLineText) { if (currentLineText) {
// trimmed forward and ending spaces text // trimmed forward and ending spaces text
writer.write(currentLineText); writer.write(currentLineText);
@ -2071,10 +2097,10 @@ namespace ts {
} }
} }
function calculateIndent(pos: number, end: number) { function calculateIndent(text: string, pos: number, end: number) {
let currentLineIndent = 0; let currentLineIndent = 0;
for (; pos < end && isWhiteSpace(currentSourceFile.text.charCodeAt(pos)); pos++) { for (; pos < end && isWhiteSpace(text.charCodeAt(pos)); pos++) {
if (currentSourceFile.text.charCodeAt(pos) === CharacterCodes.tab) { if (text.charCodeAt(pos) === CharacterCodes.tab) {
// Tabs = TabSize = indent size and go to next tabStop // Tabs = TabSize = indent size and go to next tabStop
currentLineIndent += getIndentSize() - (currentLineIndent % getIndentSize()); currentLineIndent += getIndentSize() - (currentLineIndent % getIndentSize());
} }
@ -2086,7 +2112,6 @@ namespace ts {
return currentLineIndent; return currentLineIndent;
} }
}
export function modifierToFlag(token: SyntaxKind): NodeFlags { export function modifierToFlag(token: SyntaxKind): NodeFlags {
switch (token) { switch (token) {
@ -2171,7 +2196,7 @@ namespace ts {
} }
export function isEmptyObjectLiteralOrArrayLiteral(expression: Node): boolean { export function isEmptyObjectLiteralOrArrayLiteral(expression: Node): boolean {
let kind = expression.kind; const kind = expression.kind;
if (kind === SyntaxKind.ObjectLiteralExpression) { if (kind === SyntaxKind.ObjectLiteralExpression) {
return (<ObjectLiteralExpression>expression).properties.length === 0; return (<ObjectLiteralExpression>expression).properties.length === 0;
} }
@ -2198,11 +2223,11 @@ namespace ts {
* representing the UTF-8 encoding of the character, and return the expanded char code list. * representing the UTF-8 encoding of the character, and return the expanded char code list.
*/ */
function getExpandedCharCodes(input: string): number[] { function getExpandedCharCodes(input: string): number[] {
let output: number[] = []; const output: number[] = [];
let length = input.length; const length = input.length;
for (let i = 0; i < length; i++) { for (let i = 0; i < length; i++) {
let charCode = input.charCodeAt(i); const charCode = input.charCodeAt(i);
// handel utf8 // handel utf8
if (charCode < 0x80) { if (charCode < 0x80) {
@ -2238,9 +2263,9 @@ namespace ts {
*/ */
export function convertToBase64(input: string): string { export function convertToBase64(input: string): string {
let result = ""; let result = "";
let charCodes = getExpandedCharCodes(input); const charCodes = getExpandedCharCodes(input);
let i = 0; let i = 0;
let length = charCodes.length; const length = charCodes.length;
let byte1: number, byte2: number, byte3: number, byte4: number; let byte1: number, byte2: number, byte3: number, byte4: number;
while (i < length) { while (i < length) {
@ -2314,14 +2339,14 @@ namespace ts {
} }
export function textSpanOverlapsWith(span: TextSpan, other: TextSpan) { export function textSpanOverlapsWith(span: TextSpan, other: TextSpan) {
let overlapStart = Math.max(span.start, other.start); const overlapStart = Math.max(span.start, other.start);
let overlapEnd = Math.min(textSpanEnd(span), textSpanEnd(other)); const overlapEnd = Math.min(textSpanEnd(span), textSpanEnd(other));
return overlapStart < overlapEnd; return overlapStart < overlapEnd;
} }
export function textSpanOverlap(span1: TextSpan, span2: TextSpan) { export function textSpanOverlap(span1: TextSpan, span2: TextSpan) {
let overlapStart = Math.max(span1.start, span2.start); const overlapStart = Math.max(span1.start, span2.start);
let overlapEnd = Math.min(textSpanEnd(span1), textSpanEnd(span2)); const overlapEnd = Math.min(textSpanEnd(span1), textSpanEnd(span2));
if (overlapStart < overlapEnd) { if (overlapStart < overlapEnd) {
return createTextSpanFromBounds(overlapStart, overlapEnd); return createTextSpanFromBounds(overlapStart, overlapEnd);
} }
@ -2333,13 +2358,13 @@ namespace ts {
} }
export function textSpanIntersectsWith(span: TextSpan, start: number, length: number) { export function textSpanIntersectsWith(span: TextSpan, start: number, length: number) {
let end = start + length; const end = start + length;
return start <= textSpanEnd(span) && end >= span.start; return start <= textSpanEnd(span) && end >= span.start;
} }
export function decodedTextSpanIntersectsWith(start1: number, length1: number, start2: number, length2: number) { export function decodedTextSpanIntersectsWith(start1: number, length1: number, start2: number, length2: number) {
let end1 = start1 + length1; const end1 = start1 + length1;
let end2 = start2 + length2; const end2 = start2 + length2;
return start2 <= end1 && end2 >= start1; return start2 <= end1 && end2 >= start1;
} }
@ -2348,8 +2373,8 @@ namespace ts {
} }
export function textSpanIntersection(span1: TextSpan, span2: TextSpan) { export function textSpanIntersection(span1: TextSpan, span2: TextSpan) {
let intersectStart = Math.max(span1.start, span2.start); const intersectStart = Math.max(span1.start, span2.start);
let intersectEnd = Math.min(textSpanEnd(span1), textSpanEnd(span2)); const intersectEnd = Math.min(textSpanEnd(span1), textSpanEnd(span2));
if (intersectStart <= intersectEnd) { if (intersectStart <= intersectEnd) {
return createTextSpanFromBounds(intersectStart, intersectEnd); return createTextSpanFromBounds(intersectStart, intersectEnd);
} }
@ -2408,14 +2433,14 @@ namespace ts {
// We change from talking about { { oldStart, oldLength }, newLength } to { oldStart, oldEnd, newEnd } // We change from talking about { { oldStart, oldLength }, newLength } to { oldStart, oldEnd, newEnd }
// as it makes things much easier to reason about. // as it makes things much easier to reason about.
let change0 = changes[0]; const change0 = changes[0];
let oldStartN = change0.span.start; let oldStartN = change0.span.start;
let oldEndN = textSpanEnd(change0.span); let oldEndN = textSpanEnd(change0.span);
let newEndN = oldStartN + change0.newLength; let newEndN = oldStartN + change0.newLength;
for (let i = 1; i < changes.length; i++) { for (let i = 1; i < changes.length; i++) {
let nextChange = changes[i]; const nextChange = changes[i];
// Consider the following case: // Consider the following case:
// i.e. two edits. The first represents the text change range { { 10, 50 }, 30 }. i.e. The span starting // i.e. two edits. The first represents the text change range { { 10, 50 }, 30 }. i.e. The span starting
@ -2497,13 +2522,13 @@ namespace ts {
// newEnd3 : Max(newEnd2, newEnd2 + (newEnd1 - oldEnd2)) // newEnd3 : Max(newEnd2, newEnd2 + (newEnd1 - oldEnd2))
// } // }
let oldStart1 = oldStartN; const oldStart1 = oldStartN;
let oldEnd1 = oldEndN; const oldEnd1 = oldEndN;
let newEnd1 = newEndN; const newEnd1 = newEndN;
let oldStart2 = nextChange.span.start; const oldStart2 = nextChange.span.start;
let oldEnd2 = textSpanEnd(nextChange.span); const oldEnd2 = textSpanEnd(nextChange.span);
let newEnd2 = oldStart2 + nextChange.newLength; const newEnd2 = oldStart2 + nextChange.newLength;
oldStartN = Math.min(oldStart1, oldStart2); oldStartN = Math.min(oldStart1, oldStart2);
oldEndN = Math.max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1)); oldEndN = Math.max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1));

View file

@ -140,7 +140,7 @@ class CompilerBaselineRunner extends RunnerBase {
it("Correct sourcemap content for " + fileName, () => { it("Correct sourcemap content for " + fileName, () => {
if (options.sourceMap || options.inlineSourceMap) { if (options.sourceMap || options.inlineSourceMap) {
Harness.Baseline.runBaseline("Correct sourcemap content for " + fileName, justName.replace(/\.tsx?$/, ".sourcemap.txt"), () => { Harness.Baseline.runBaseline("Correct sourcemap content for " + fileName, justName.replace(/\.tsx?$/, ".sourcemap.txt"), () => {
let record = result.getSourceMapRecord(); const record = result.getSourceMapRecord();
if (options.noEmitOnError && result.errors.length !== 0 && record === undefined) { if (options.noEmitOnError && result.errors.length !== 0 && record === undefined) {
// Because of the noEmitOnError option no files are created. We need to return null because baselining isn"t required. // Because of the noEmitOnError option no files are created. We need to return null because baselining isn"t required.
return null; return null;
@ -159,7 +159,7 @@ class CompilerBaselineRunner extends RunnerBase {
// check js output // check js output
Harness.Baseline.runBaseline("Correct JS output for " + fileName, justName.replace(/\.tsx?/, ".js"), () => { Harness.Baseline.runBaseline("Correct JS output for " + fileName, justName.replace(/\.tsx?/, ".js"), () => {
let tsCode = ""; let tsCode = "";
let tsSources = otherFiles.concat(toBeCompiled); const tsSources = otherFiles.concat(toBeCompiled);
if (tsSources.length > 1) { if (tsSources.length > 1) {
tsCode += "//// [" + fileName + "] ////\r\n\r\n"; tsCode += "//// [" + fileName + "] ////\r\n\r\n";
} }
@ -184,7 +184,7 @@ class CompilerBaselineRunner extends RunnerBase {
} }
} }
let declFileCompilationResult = harnessCompiler.compileDeclarationFiles(toBeCompiled, otherFiles, result, function (settings) { const declFileCompilationResult = harnessCompiler.compileDeclarationFiles(toBeCompiled, otherFiles, result, function (settings) {
harnessCompiler.setCompilerSettings(tcSettings); harnessCompiler.setCompilerSettings(tcSettings);
}, options); }, options);
@ -257,15 +257,15 @@ class CompilerBaselineRunner extends RunnerBase {
// These types are equivalent, but depend on what order the compiler observed // These types are equivalent, but depend on what order the compiler observed
// certain parts of the program. // certain parts of the program.
let allFiles = toBeCompiled.concat(otherFiles).filter(file => !!program.getSourceFile(file.unitName)); const allFiles = toBeCompiled.concat(otherFiles).filter(file => !!program.getSourceFile(file.unitName));
let fullWalker = new TypeWriterWalker(program, /*fullTypeCheck:*/ true); const fullWalker = new TypeWriterWalker(program, /*fullTypeCheck:*/ true);
let pullWalker = new TypeWriterWalker(program, /*fullTypeCheck:*/ false); const pullWalker = new TypeWriterWalker(program, /*fullTypeCheck:*/ false);
let fullResults: ts.Map<TypeWriterResult[]> = {}; const fullResults: ts.Map<TypeWriterResult[]> = {};
let pullResults: ts.Map<TypeWriterResult[]> = {}; const pullResults: ts.Map<TypeWriterResult[]> = {};
for (let sourceFile of allFiles) { for (const sourceFile of allFiles) {
fullResults[sourceFile.unitName] = fullWalker.getTypeAndSymbols(sourceFile.unitName); fullResults[sourceFile.unitName] = fullWalker.getTypeAndSymbols(sourceFile.unitName);
pullResults[sourceFile.unitName] = fullWalker.getTypeAndSymbols(sourceFile.unitName); pullResults[sourceFile.unitName] = fullWalker.getTypeAndSymbols(sourceFile.unitName);
} }
@ -294,11 +294,11 @@ class CompilerBaselineRunner extends RunnerBase {
return; return;
function checkBaseLines(isSymbolBaseLine: boolean) { function checkBaseLines(isSymbolBaseLine: boolean) {
let fullBaseLine = generateBaseLine(fullResults, isSymbolBaseLine); const fullBaseLine = generateBaseLine(fullResults, isSymbolBaseLine);
let pullBaseLine = generateBaseLine(pullResults, isSymbolBaseLine); const pullBaseLine = generateBaseLine(pullResults, isSymbolBaseLine);
let fullExtension = isSymbolBaseLine ? ".symbols" : ".types"; const fullExtension = isSymbolBaseLine ? ".symbols" : ".types";
let pullExtension = isSymbolBaseLine ? ".symbols.pull" : ".types.pull"; const pullExtension = isSymbolBaseLine ? ".symbols.pull" : ".types.pull";
if (fullBaseLine !== pullBaseLine) { if (fullBaseLine !== pullBaseLine) {
Harness.Baseline.runBaseline("Correct full information for " + fileName, justName.replace(/\.tsx?/, fullExtension), () => fullBaseLine); Harness.Baseline.runBaseline("Correct full information for " + fileName, justName.replace(/\.tsx?/, fullExtension), () => fullBaseLine);
@ -310,24 +310,24 @@ class CompilerBaselineRunner extends RunnerBase {
} }
function generateBaseLine(typeWriterResults: ts.Map<TypeWriterResult[]>, isSymbolBaseline: boolean): string { function generateBaseLine(typeWriterResults: ts.Map<TypeWriterResult[]>, isSymbolBaseline: boolean): string {
let typeLines: string[] = []; const typeLines: string[] = [];
let typeMap: { [fileName: string]: { [lineNum: number]: string[]; } } = {}; const typeMap: { [fileName: string]: { [lineNum: number]: string[]; } } = {};
allFiles.forEach(file => { allFiles.forEach(file => {
let codeLines = file.content.split("\n"); const codeLines = file.content.split("\n");
typeWriterResults[file.unitName].forEach(result => { typeWriterResults[file.unitName].forEach(result => {
if (isSymbolBaseline && !result.symbol) { if (isSymbolBaseline && !result.symbol) {
return; return;
} }
let typeOrSymbolString = isSymbolBaseline ? result.symbol : result.type; const typeOrSymbolString = isSymbolBaseline ? result.symbol : result.type;
let formattedLine = result.sourceText.replace(/\r?\n/g, "") + " : " + typeOrSymbolString; const formattedLine = result.sourceText.replace(/\r?\n/g, "") + " : " + typeOrSymbolString;
if (!typeMap[file.unitName]) { if (!typeMap[file.unitName]) {
typeMap[file.unitName] = {}; typeMap[file.unitName] = {};
} }
let typeInfo = [formattedLine]; let typeInfo = [formattedLine];
let existingTypeInfo = typeMap[file.unitName][result.line]; const existingTypeInfo = typeMap[file.unitName][result.line];
if (existingTypeInfo) { if (existingTypeInfo) {
typeInfo = existingTypeInfo.concat(typeInfo); typeInfo = existingTypeInfo.concat(typeInfo);
} }
@ -336,10 +336,10 @@ class CompilerBaselineRunner extends RunnerBase {
typeLines.push("=== " + file.unitName + " ===\r\n"); typeLines.push("=== " + file.unitName + " ===\r\n");
for (let i = 0; i < codeLines.length; i++) { for (let i = 0; i < codeLines.length; i++) {
let currentCodeLine = codeLines[i]; const currentCodeLine = codeLines[i];
typeLines.push(currentCodeLine + "\r\n"); typeLines.push(currentCodeLine + "\r\n");
if (typeMap[file.unitName]) { if (typeMap[file.unitName]) {
let typeInfo = typeMap[file.unitName][i]; const typeInfo = typeMap[file.unitName][i];
if (typeInfo) { if (typeInfo) {
typeInfo.forEach(ty => { typeInfo.forEach(ty => {
typeLines.push(">" + ty + "\r\n"); typeLines.push(">" + ty + "\r\n");
@ -367,13 +367,13 @@ class CompilerBaselineRunner extends RunnerBase {
public initializeTests() { public initializeTests() {
describe(this.testSuiteName + " tests", () => { describe(this.testSuiteName + " tests", () => {
describe("Setup compiler for compiler baselines", () => { describe("Setup compiler for compiler baselines", () => {
let harnessCompiler = Harness.Compiler.getCompiler(); const harnessCompiler = Harness.Compiler.getCompiler();
this.parseOptions(); this.parseOptions();
}); });
// this will set up a series of describe/it blocks to run between the setup and cleanup phases // this will set up a series of describe/it blocks to run between the setup and cleanup phases
if (this.tests.length === 0) { if (this.tests.length === 0) {
let testFiles = this.enumerateFiles(this.basePath, /\.tsx?$/, { recursive: true }); const testFiles = this.enumerateFiles(this.basePath, /\.tsx?$/, { recursive: true });
testFiles.forEach(fn => { testFiles.forEach(fn => {
fn = fn.replace(/\\/g, "/"); fn = fn.replace(/\\/g, "/");
this.checkTestCodeOutput(fn); this.checkTestCodeOutput(fn);
@ -392,7 +392,7 @@ class CompilerBaselineRunner extends RunnerBase {
this.decl = false; this.decl = false;
this.output = false; this.output = false;
let opts = this.options.split(","); const opts = this.options.split(",");
for (let i = 0; i < opts.length; i++) { for (let i = 0; i < opts.length; i++) {
switch (opts[i]) { switch (opts[i]) {
case "error": case "error":

File diff suppressed because it is too large Load diff

View file

@ -45,10 +45,10 @@ class FourSlashRunner extends RunnerBase {
this.tests.forEach((fn: string) => { this.tests.forEach((fn: string) => {
describe(fn, () => { describe(fn, () => {
fn = ts.normalizeSlashes(fn); fn = ts.normalizeSlashes(fn);
let justName = fn.replace(/^.*[\\\/]/, ""); const justName = fn.replace(/^.*[\\\/]/, "");
// Convert to relative path // Convert to relative path
let testIndex = fn.indexOf("tests/"); const testIndex = fn.indexOf("tests/");
if (testIndex >= 0) fn = fn.substr(testIndex); if (testIndex >= 0) fn = fn.substr(testIndex);
if (justName && !justName.match(/fourslash\.ts$/i) && !justName.match(/\.d\.ts$/i)) { if (justName && !justName.match(/fourslash\.ts$/i) && !justName.match(/\.d\.ts$/i)) {
@ -60,21 +60,21 @@ class FourSlashRunner extends RunnerBase {
}); });
describe("Generate Tao XML", () => { describe("Generate Tao XML", () => {
let invalidReasons: any = {}; const invalidReasons: any = {};
FourSlash.xmlData.forEach(xml => { FourSlash.xmlData.forEach(xml => {
if (xml.invalidReason !== null) { if (xml.invalidReason !== null) {
invalidReasons[xml.invalidReason] = (invalidReasons[xml.invalidReason] || 0) + 1; invalidReasons[xml.invalidReason] = (invalidReasons[xml.invalidReason] || 0) + 1;
} }
}); });
let invalidReport: { reason: string; count: number }[] = []; const invalidReport: { reason: string; count: number }[] = [];
for (let reason in invalidReasons) { for (const reason in invalidReasons) {
if (invalidReasons.hasOwnProperty(reason)) { if (invalidReasons.hasOwnProperty(reason)) {
invalidReport.push({ reason: reason, count: invalidReasons[reason] }); invalidReport.push({ reason: reason, count: invalidReasons[reason] });
} }
} }
invalidReport.sort((lhs, rhs) => lhs.count > rhs.count ? -1 : lhs.count === rhs.count ? 0 : 1); invalidReport.sort((lhs, rhs) => lhs.count > rhs.count ? -1 : lhs.count === rhs.count ? 0 : 1);
let lines: string[] = []; const lines: string[] = [];
lines.push("<!-- Blocked Test Report"); lines.push("<!-- Blocked Test Report");
invalidReport.forEach((reasonAndCount) => { invalidReport.forEach((reasonAndCount) => {
lines.push(reasonAndCount.count + " tests blocked by " + reasonAndCount.reason); lines.push(reasonAndCount.count + " tests blocked by " + reasonAndCount.reason);

View file

@ -67,7 +67,7 @@ namespace Utils {
} }
export function evalFile(fileContents: string, fileName: string, nodeContext?: any) { export function evalFile(fileContents: string, fileName: string, nodeContext?: any) {
let environment = getExecutionEnvironment(); const environment = getExecutionEnvironment();
switch (environment) { switch (environment) {
case ExecutionEnvironment.CScript: case ExecutionEnvironment.CScript:
case ExecutionEnvironment.Browser: case ExecutionEnvironment.Browser:
@ -121,11 +121,11 @@ namespace Utils {
} }
export function memoize<T extends Function>(f: T): T { export function memoize<T extends Function>(f: T): T {
let cache: { [idx: string]: any } = {}; const cache: { [idx: string]: any } = {};
return <any>(function () { return <any>(function () {
let key = Array.prototype.join.call(arguments); const key = Array.prototype.join.call(arguments);
let cachedResult = cache[key]; const cachedResult = cache[key];
if (cachedResult) { if (cachedResult) {
return cachedResult; return cachedResult;
} }
@ -172,14 +172,14 @@ namespace Utils {
currentPos = array.end; currentPos = array.end;
}); });
let childNodesAndArrays: any[] = []; const childNodesAndArrays: any[] = [];
ts.forEachChild(node, child => { childNodesAndArrays.push(child); }, array => { childNodesAndArrays.push(array); }); ts.forEachChild(node, child => { childNodesAndArrays.push(child); }, array => { childNodesAndArrays.push(array); });
for (let childName in node) { for (const childName in node) {
if (childName === "parent" || childName === "nextContainer" || childName === "modifiers" || childName === "externalModuleIndicator") { if (childName === "parent" || childName === "nextContainer" || childName === "modifiers" || childName === "externalModuleIndicator") {
continue; continue;
} }
let child = (<any>node)[childName]; const child = (<any>node)[childName];
if (isNodeOrArray(child)) { if (isNodeOrArray(child)) {
assert.isFalse(childNodesAndArrays.indexOf(child) < 0, assert.isFalse(childNodesAndArrays.indexOf(child) < 0,
"Missing child when forEach'ing over node: " + (<any>ts).SyntaxKind[node.kind] + "-" + childName); "Missing child when forEach'ing over node: " + (<any>ts).SyntaxKind[node.kind] + "-" + childName);
@ -247,7 +247,7 @@ namespace Utils {
function getParserContextFlagName(f: number) { return getFlagName((<any>ts).ParserContextFlags, f); } function getParserContextFlagName(f: number) { return getFlagName((<any>ts).ParserContextFlags, f); }
function serializeNode(n: ts.Node): any { function serializeNode(n: ts.Node): any {
let o: any = { kind: getKindName(n.kind) }; const o: any = { kind: getKindName(n.kind) };
if (ts.containsParseError(n)) { if (ts.containsParseError(n)) {
o.containsParseError = true; o.containsParseError = true;
} }
@ -329,8 +329,8 @@ namespace Utils {
assert.equal(array1.length, array2.length, "array1.length !== array2.length"); assert.equal(array1.length, array2.length, "array1.length !== array2.length");
for (let i = 0, n = array1.length; i < n; i++) { for (let i = 0, n = array1.length; i < n; i++) {
let d1 = array1[i]; const d1 = array1[i];
let d2 = array2[i]; const d2 = array2[i];
assert.equal(d1.start, d2.start, "d1.start !== d2.start"); assert.equal(d1.start, d2.start, "d1.start !== d2.start");
assert.equal(d1.length, d2.length, "d1.length !== d2.length"); assert.equal(d1.length, d2.length, "d1.length !== d2.length");
@ -361,14 +361,14 @@ namespace Utils {
ts.forEachChild(node1, ts.forEachChild(node1,
child1 => { child1 => {
let childName = findChildName(node1, child1); const childName = findChildName(node1, child1);
let child2: ts.Node = (<any>node2)[childName]; const child2: ts.Node = (<any>node2)[childName];
assertStructuralEquals(child1, child2); assertStructuralEquals(child1, child2);
}, },
(array1: ts.NodeArray<ts.Node>) => { (array1: ts.NodeArray<ts.Node>) => {
let childName = findChildName(node1, array1); const childName = findChildName(node1, array1);
let array2: ts.NodeArray<ts.Node> = (<any>node2)[childName]; const array2: ts.NodeArray<ts.Node> = (<any>node2)[childName];
assertArrayStructuralEquals(array1, array2); assertArrayStructuralEquals(array1, array2);
}); });
@ -391,7 +391,7 @@ namespace Utils {
} }
function findChildName(parent: any, child: any) { function findChildName(parent: any, child: any) {
for (let name in parent) { for (const name in parent) {
if (parent.hasOwnProperty(name) && parent[name] === child) { if (parent.hasOwnProperty(name) && parent[name] === child) {
return name; return name;
} }
@ -408,8 +408,8 @@ namespace Harness.Path {
export function filePath(fullPath: string) { export function filePath(fullPath: string) {
fullPath = ts.normalizeSlashes(fullPath); fullPath = ts.normalizeSlashes(fullPath);
let components = fullPath.split("/"); const components = fullPath.split("/");
let path: string[] = components.slice(0, components.length - 1); const path: string[] = components.slice(0, components.length - 1);
return path.join("/") + "/"; return path.join("/") + "/";
} }
} }
@ -510,15 +510,15 @@ namespace Harness {
return paths; return paths;
} }
let folder: any = fso.GetFolder(path); const folder: any = fso.GetFolder(path);
let paths: string[] = []; const paths: string[] = [];
return filesInFolder(folder, path); return filesInFolder(folder, path);
}; };
} }
export namespace Node { export namespace Node {
declare let require: any; declare const require: any;
let fs: any, pathModule: any; let fs: any, pathModule: any;
if (require) { if (require) {
fs = require("fs"); fs = require("fs");
@ -579,10 +579,10 @@ namespace Harness {
function filesInFolder(folder: string): string[] { function filesInFolder(folder: string): string[] {
let paths: string[] = []; let paths: string[] = [];
let files = fs.readdirSync(folder); const files = fs.readdirSync(folder);
for (let i = 0; i < files.length; i++) { for (let i = 0; i < files.length; i++) {
let pathToFile = pathModule.join(folder, files[i]); const pathToFile = pathModule.join(folder, files[i]);
let stat = fs.statSync(pathToFile); const stat = fs.statSync(pathToFile);
if (options.recursive && stat.isDirectory()) { if (options.recursive && stat.isDirectory()) {
paths = paths.concat(filesInFolder(pathToFile)); paths = paths.concat(filesInFolder(pathToFile));
} }
@ -606,7 +606,7 @@ namespace Harness {
} }
export namespace Network { export namespace Network {
let serverRoot = "http://localhost:8888/"; const serverRoot = "http://localhost:8888/";
export const newLine = () => harnessNewLine; export const newLine = () => harnessNewLine;
export const useCaseSensitiveFileNames = () => false; export const useCaseSensitiveFileNames = () => false;
@ -615,7 +615,7 @@ namespace Harness {
export const getExecutingFilePath = () => ""; export const getExecutingFilePath = () => "";
export const exit = (exitCode: number) => {}; export const exit = (exitCode: number) => {};
let supportsCodePage = () => false; const supportsCodePage = () => false;
export let log = (s: string) => console.log(s); export let log = (s: string) => console.log(s);
namespace Http { namespace Http {
@ -626,7 +626,7 @@ namespace Harness {
/// Ask the server to use node's path.resolve to resolve the given path /// Ask the server to use node's path.resolve to resolve the given path
function getResolvedPathFromServer(path: string) { function getResolvedPathFromServer(path: string) {
let xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
try { try {
xhr.open("GET", path + "?resolve", false); xhr.open("GET", path + "?resolve", false);
xhr.send(); xhr.send();
@ -645,7 +645,7 @@ namespace Harness {
/// Ask the server for the contents of the file at the given URL via a simple GET request /// Ask the server for the contents of the file at the given URL via a simple GET request
export function getFileFromServerSync(url: string): XHRResponse { export function getFileFromServerSync(url: string): XHRResponse {
let xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
try { try {
xhr.open("GET", url, false); xhr.open("GET", url, false);
xhr.send(); xhr.send();
@ -659,9 +659,9 @@ namespace Harness {
/// Submit a POST request to the server to do the given action (ex WRITE, DELETE) on the provided URL /// Submit a POST request to the server to do the given action (ex WRITE, DELETE) on the provided URL
export function writeToServerSync(url: string, action: string, contents?: string): XHRResponse { export function writeToServerSync(url: string, action: string, contents?: string): XHRResponse {
let xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
try { try {
let actionMsg = "?action=" + action; const actionMsg = "?action=" + action;
xhr.open("POST", url + actionMsg, false); xhr.open("POST", url + actionMsg, false);
xhr.setRequestHeader("Access-Control-Allow-Origin", "*"); xhr.setRequestHeader("Access-Control-Allow-Origin", "*");
xhr.send(contents); xhr.send(contents);
@ -712,14 +712,14 @@ namespace Harness {
export const resolvePath = (path: string) => directoryName(path); export const resolvePath = (path: string) => directoryName(path);
export function fileExists(path: string): boolean { export function fileExists(path: string): boolean {
let response = Http.getFileFromServerSync(serverRoot + path); const response = Http.getFileFromServerSync(serverRoot + path);
return response.status === 200; return response.status === 200;
} }
export function _listFilesImpl(path: string, spec?: RegExp, options?: any) { export function _listFilesImpl(path: string, spec?: RegExp, options?: any) {
let response = Http.getFileFromServerSync(serverRoot + path); const response = Http.getFileFromServerSync(serverRoot + path);
if (response.status === 200) { if (response.status === 200) {
let results = response.responseText.split(","); const results = response.responseText.split(",");
if (spec) { if (spec) {
return results.filter(file => spec.test(file)); return results.filter(file => spec.test(file));
} }
@ -734,7 +734,7 @@ namespace Harness {
export let listFiles = Utils.memoize(_listFilesImpl); export let listFiles = Utils.memoize(_listFilesImpl);
export function readFile(file: string) { export function readFile(file: string) {
let response = Http.getFileFromServerSync(serverRoot + file); const response = Http.getFileFromServerSync(serverRoot + file);
if (response.status === 200) { if (response.status === 200) {
return response.responseText; return response.responseText;
} }
@ -856,10 +856,10 @@ namespace Harness {
public reset() { this.fileCollection = {}; } public reset() { this.fileCollection = {}; }
public toArray(): { fileName: string; file: WriterAggregator; }[] { public toArray(): { fileName: string; file: WriterAggregator; }[] {
let result: { fileName: string; file: WriterAggregator; }[] = []; const result: { fileName: string; file: WriterAggregator; }[] = [];
for (let p in this.fileCollection) { for (const p in this.fileCollection) {
if (this.fileCollection.hasOwnProperty(p)) { if (this.fileCollection.hasOwnProperty(p)) {
let current = <Harness.Compiler.WriterAggregator>this.fileCollection[p]; const current = <Harness.Compiler.WriterAggregator>this.fileCollection[p];
if (current.lines.length > 0) { if (current.lines.length > 0) {
if (p.indexOf(".d.ts") !== -1) { current.lines.unshift(["////[", Path.getFileName(p), "]"].join("")); } if (p.indexOf(".d.ts") !== -1) { current.lines.unshift(["////[", Path.getFileName(p), "]"].join("")); }
result.push({ fileName: p, file: this.fileCollection[p] }); result.push({ fileName: p, file: this.fileCollection[p] });
@ -878,7 +878,7 @@ namespace Harness {
const shouldAssertInvariants = !Harness.lightMode; const shouldAssertInvariants = !Harness.lightMode;
// Only set the parent nodes if we're asserting inletiants. We don't need them otherwise. // Only set the parent nodes if we're asserting inletiants. We don't need them otherwise.
let result = ts.createSourceFile(fileName, sourceText, languageVersion, /*setParentNodes:*/ shouldAssertInvariants); const result = ts.createSourceFile(fileName, sourceText, languageVersion, /*setParentNodes:*/ shouldAssertInvariants);
if (shouldAssertInvariants) { if (shouldAssertInvariants) {
Utils.assertInvariants(result, /*parent:*/ undefined); Utils.assertInvariants(result, /*parent:*/ undefined);
@ -916,13 +916,13 @@ namespace Harness {
return useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); return useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
} }
let filemap: { [fileName: string]: ts.SourceFile; } = {}; const filemap: { [fileName: string]: ts.SourceFile; } = {};
let getCurrentDirectory = currentDirectory === undefined ? Harness.IO.getCurrentDirectory : () => currentDirectory; const getCurrentDirectory = currentDirectory === undefined ? Harness.IO.getCurrentDirectory : () => currentDirectory;
// Register input files // Register input files
function register(file: { unitName: string; content: string; }) { function register(file: { unitName: string; content: string; }) {
if (file.content !== undefined) { if (file.content !== undefined) {
let fileName = ts.normalizePath(file.unitName); const fileName = ts.normalizePath(file.unitName);
const sourceFile = createSourceFileAndAssertInvariants(fileName, file.content, scriptTarget); const sourceFile = createSourceFileAndAssertInvariants(fileName, file.content, scriptTarget);
filemap[getCanonicalFileName(fileName)] = sourceFile; filemap[getCanonicalFileName(fileName)] = sourceFile;
filemap[getCanonicalFileName(ts.getNormalizedAbsolutePath(fileName, getCurrentDirectory()))] = sourceFile; filemap[getCanonicalFileName(ts.getNormalizedAbsolutePath(fileName, getCurrentDirectory()))] = sourceFile;
@ -936,11 +936,11 @@ namespace Harness {
return filemap[getCanonicalFileName(fn)]; return filemap[getCanonicalFileName(fn)];
} }
else if (currentDirectory) { else if (currentDirectory) {
let canonicalAbsolutePath = getCanonicalFileName(ts.getNormalizedAbsolutePath(fn, currentDirectory)); const canonicalAbsolutePath = getCanonicalFileName(ts.getNormalizedAbsolutePath(fn, currentDirectory));
return Object.prototype.hasOwnProperty.call(filemap, getCanonicalFileName(canonicalAbsolutePath)) ? filemap[canonicalAbsolutePath] : undefined; return Object.prototype.hasOwnProperty.call(filemap, getCanonicalFileName(canonicalAbsolutePath)) ? filemap[canonicalAbsolutePath] : undefined;
} }
else if (fn === fourslashFileName) { else if (fn === fourslashFileName) {
let tsFn = "tests/cases/fourslash/" + fourslashFileName; const tsFn = "tests/cases/fourslash/" + fourslashFileName;
fourslashSourceFile = fourslashSourceFile || createSourceFileAndAssertInvariants(tsFn, Harness.IO.readFile(tsFn), scriptTarget); fourslashSourceFile = fourslashSourceFile || createSourceFileAndAssertInvariants(tsFn, Harness.IO.readFile(tsFn), scriptTarget);
return fourslashSourceFile; return fourslashSourceFile;
} }
@ -953,7 +953,7 @@ namespace Harness {
} }
} }
let newLine = const newLine =
newLineKind === ts.NewLineKind.CarriageReturnLineFeed ? carriageReturnLineFeed : newLineKind === ts.NewLineKind.CarriageReturnLineFeed ? carriageReturnLineFeed :
newLineKind === ts.NewLineKind.LineFeed ? lineFeed : newLineKind === ts.NewLineKind.LineFeed ? lineFeed :
Harness.IO.newLine(); Harness.IO.newLine();
@ -991,8 +991,8 @@ namespace Harness {
function getCommandLineOption(name: string): ts.CommandLineOption { function getCommandLineOption(name: string): ts.CommandLineOption {
if (!optionsIndex) { if (!optionsIndex) {
optionsIndex = {}; optionsIndex = {};
let optionDeclarations = harnessOptionDeclarations.concat(ts.optionDeclarations); const optionDeclarations = harnessOptionDeclarations.concat(ts.optionDeclarations);
for (let option of optionDeclarations) { for (const option of optionDeclarations) {
optionsIndex[option.name.toLowerCase()] = option; optionsIndex[option.name.toLowerCase()] = option;
} }
} }
@ -1000,13 +1000,13 @@ namespace Harness {
} }
export function setCompilerOptionsFromHarnessSetting(settings: Harness.TestCaseParser.CompilerSettings, options: ts.CompilerOptions & HarnessOptions): void { export function setCompilerOptionsFromHarnessSetting(settings: Harness.TestCaseParser.CompilerSettings, options: ts.CompilerOptions & HarnessOptions): void {
for (let name in settings) { for (const name in settings) {
if (settings.hasOwnProperty(name)) { if (settings.hasOwnProperty(name)) {
let value = settings[name]; const value = settings[name];
if (value === undefined) { if (value === undefined) {
throw new Error(`Cannot have undefined value for compiler option '${name}'.`); throw new Error(`Cannot have undefined value for compiler option '${name}'.`);
} }
let option = getCommandLineOption(name); const option = getCommandLineOption(name);
if (option) { if (option) {
switch (option.type) { switch (option.type) {
case "boolean": case "boolean":
@ -1102,37 +1102,37 @@ namespace Harness {
settingsCallback(null); settingsCallback(null);
} }
let newLine = "\r\n"; const newLine = "\r\n";
// Parse settings // Parse settings
setCompilerOptionsFromHarnessSetting(this.settings, options); setCompilerOptionsFromHarnessSetting(this.settings, options);
// Files from built\local that are requested by test "@includeBuiltFiles" to be in the context. // Files from built\local that are requested by test "@includeBuiltFiles" to be in the context.
// Treat them as library files, so include them in build, but not in baselines. // Treat them as library files, so include them in build, but not in baselines.
let includeBuiltFiles: { unitName: string; content: string }[] = []; const includeBuiltFiles: { unitName: string; content: string }[] = [];
if (options.includeBuiltFile) { if (options.includeBuiltFile) {
let builtFileName = libFolder + options.includeBuiltFile; const builtFileName = libFolder + options.includeBuiltFile;
includeBuiltFiles.push({ unitName: builtFileName, content: normalizeLineEndings(IO.readFile(builtFileName), newLine) }); includeBuiltFiles.push({ unitName: builtFileName, content: normalizeLineEndings(IO.readFile(builtFileName), newLine) });
} }
let useCaseSensitiveFileNames = options.useCaseSensitiveFileNames !== undefined ? options.useCaseSensitiveFileNames : Harness.IO.useCaseSensitiveFileNames(); const useCaseSensitiveFileNames = options.useCaseSensitiveFileNames !== undefined ? options.useCaseSensitiveFileNames : Harness.IO.useCaseSensitiveFileNames();
let fileOutputs: GeneratedFile[] = []; const fileOutputs: GeneratedFile[] = [];
let programFiles = inputFiles.concat(includeBuiltFiles).map(file => file.unitName); const programFiles = inputFiles.concat(includeBuiltFiles).map(file => file.unitName);
let compilerHost = createCompilerHost( const compilerHost = createCompilerHost(
inputFiles.concat(includeBuiltFiles).concat(otherFiles), inputFiles.concat(includeBuiltFiles).concat(otherFiles),
(fn, contents, writeByteOrderMark) => fileOutputs.push({ fileName: fn, code: contents, writeByteOrderMark: writeByteOrderMark }), (fn, contents, writeByteOrderMark) => fileOutputs.push({ fileName: fn, code: contents, writeByteOrderMark: writeByteOrderMark }),
options.target, useCaseSensitiveFileNames, currentDirectory, options.newLine); options.target, useCaseSensitiveFileNames, currentDirectory, options.newLine);
let program = ts.createProgram(programFiles, options, compilerHost); const program = ts.createProgram(programFiles, options, compilerHost);
let emitResult = program.emit(); const emitResult = program.emit();
let errors = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); const errors = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
this.lastErrors = errors; this.lastErrors = errors;
let result = new CompilerResult(fileOutputs, errors, program, Harness.IO.getCurrentDirectory(), emitResult.sourceMaps); const result = new CompilerResult(fileOutputs, errors, program, Harness.IO.getCurrentDirectory(), emitResult.sourceMaps);
onComplete(result, program); onComplete(result, program);
return options; return options;
@ -1149,8 +1149,8 @@ namespace Harness {
throw new Error("There were no errors and declFiles generated did not match number of js files generated"); throw new Error("There were no errors and declFiles generated did not match number of js files generated");
} }
let declInputFiles: { unitName: string; content: string }[] = []; const declInputFiles: { unitName: string; content: string }[] = [];
let declOtherFiles: { unitName: string; content: string }[] = []; const declOtherFiles: { unitName: string; content: string }[] = [];
let declResult: Harness.Compiler.CompilerResult; let declResult: Harness.Compiler.CompilerResult;
// if the .d.ts is non-empty, confirm it compiles correctly as well // if the .d.ts is non-empty, confirm it compiles correctly as well
@ -1168,18 +1168,18 @@ namespace Harness {
dtsFiles.push(file); dtsFiles.push(file);
} }
else if (isTS(file.unitName)) { else if (isTS(file.unitName)) {
let declFile = findResultCodeFile(file.unitName); const declFile = findResultCodeFile(file.unitName);
if (declFile && !findUnit(declFile.fileName, declInputFiles) && !findUnit(declFile.fileName, declOtherFiles)) { if (declFile && !findUnit(declFile.fileName, declInputFiles) && !findUnit(declFile.fileName, declOtherFiles)) {
dtsFiles.push({ unitName: declFile.fileName, content: declFile.code }); dtsFiles.push({ unitName: declFile.fileName, content: declFile.code });
} }
} }
function findResultCodeFile(fileName: string) { function findResultCodeFile(fileName: string) {
let sourceFile = result.program.getSourceFile(fileName); const sourceFile = result.program.getSourceFile(fileName);
assert(sourceFile, "Program has no source file with name '" + fileName + "'"); assert(sourceFile, "Program has no source file with name '" + fileName + "'");
// Is this file going to be emitted separately // Is this file going to be emitted separately
let sourceFileName: string; let sourceFileName: string;
let outFile = options.outFile || options.out; const outFile = options.outFile || options.out;
if (ts.isExternalModule(sourceFile) || !outFile) { if (ts.isExternalModule(sourceFile) || !outFile) {
if (options.outDir) { if (options.outDir) {
let sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, result.currentDirectoryForProgram); let sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, result.currentDirectoryForProgram);
@ -1195,7 +1195,7 @@ namespace Harness {
sourceFileName = outFile; sourceFileName = outFile;
} }
let dTsFileName = ts.removeFileExtension(sourceFileName) + ".d.ts"; const dTsFileName = ts.removeFileExtension(sourceFileName) + ".d.ts";
return ts.forEach(result.declFilesCode, declFile => declFile.fileName === dTsFileName ? declFile : undefined); return ts.forEach(result.declFilesCode, declFile => declFile.fileName === dTsFileName ? declFile : undefined);
} }
@ -1220,7 +1220,7 @@ namespace Harness {
let errorOutput = ""; let errorOutput = "";
ts.forEach(diagnostics, diagnostic => { ts.forEach(diagnostics, diagnostic => {
if (diagnostic.file) { if (diagnostic.file) {
let lineAndCharacter = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); const lineAndCharacter = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
errorOutput += diagnostic.file.fileName + "(" + (lineAndCharacter.line + 1) + "," + (lineAndCharacter.character + 1) + "): "; errorOutput += diagnostic.file.fileName + "(" + (lineAndCharacter.line + 1) + "," + (lineAndCharacter.character + 1) + "): ";
} }
@ -1232,14 +1232,14 @@ namespace Harness {
export function getErrorBaseline(inputFiles: { unitName: string; content: string }[], diagnostics: ts.Diagnostic[]) { export function getErrorBaseline(inputFiles: { unitName: string; content: string }[], diagnostics: ts.Diagnostic[]) {
diagnostics.sort(ts.compareDiagnostics); diagnostics.sort(ts.compareDiagnostics);
let outputLines: string[] = []; const outputLines: string[] = [];
// Count up all errors that were found in files other than lib.d.ts so we don't miss any // Count up all errors that were found in files other than lib.d.ts so we don't miss any
let totalErrorsReportedInNonLibraryFiles = 0; let totalErrorsReportedInNonLibraryFiles = 0;
function outputErrorText(error: ts.Diagnostic) { function outputErrorText(error: ts.Diagnostic) {
let message = ts.flattenDiagnosticMessageText(error.messageText, Harness.IO.newLine()); const message = ts.flattenDiagnosticMessageText(error.messageText, Harness.IO.newLine());
let errLines = RunnerBase.removeFullPaths(message) const errLines = RunnerBase.removeFullPaths(message)
.split("\n") .split("\n")
.map(s => s.length > 0 && s.charAt(s.length - 1) === "\r" ? s.substr(0, s.length - 1) : s) .map(s => s.length > 0 && s.charAt(s.length - 1) === "\r" ? s.substr(0, s.length - 1) : s)
.filter(s => s.length > 0) .filter(s => s.length > 0)
@ -1257,14 +1257,14 @@ namespace Harness {
} }
// Report global errors // Report global errors
let globalErrors = diagnostics.filter(err => !err.file); const globalErrors = diagnostics.filter(err => !err.file);
globalErrors.forEach(outputErrorText); globalErrors.forEach(outputErrorText);
// 'merge' the lines of each input file with any errors associated with it // 'merge' the lines of each input file with any errors associated with it
inputFiles.filter(f => f.content !== undefined).forEach(inputFile => { inputFiles.filter(f => f.content !== undefined).forEach(inputFile => {
// Filter down to the errors in the file // Filter down to the errors in the file
let fileErrors = diagnostics.filter(e => { const fileErrors = diagnostics.filter(e => {
let errFn = e.file; const errFn = e.file;
return errFn && errFn.fileName === inputFile.unitName; return errFn && errFn.fileName === inputFile.unitName;
}); });
@ -1278,7 +1278,7 @@ namespace Harness {
// Note: IE JS engine incorrectly handles consecutive delimiters here when using RegExp split, so // Note: IE JS engine incorrectly handles consecutive delimiters here when using RegExp split, so
// we have to string-based splitting instead and try to figure out the delimiting chars // we have to string-based splitting instead and try to figure out the delimiting chars
let lineStarts = ts.computeLineStarts(inputFile.content); const lineStarts = ts.computeLineStarts(inputFile.content);
let lines = inputFile.content.split("\n"); let lines = inputFile.content.split("\n");
if (lines.length === 1) { if (lines.length === 1) {
lines = lines[0].split("\r"); lines = lines[0].split("\r");
@ -1289,7 +1289,7 @@ namespace Harness {
line = line.substr(0, line.length - 1); line = line.substr(0, line.length - 1);
} }
let thisLineStart = lineStarts[lineIndex]; const thisLineStart = lineStarts[lineIndex];
let nextLineStart: number; let nextLineStart: number;
// On the last line of the file, fake the next line start number so that we handle errors on the last character of the file correctly // On the last line of the file, fake the next line start number so that we handle errors on the last character of the file correctly
if (lineIndex === lines.length - 1) { if (lineIndex === lines.length - 1) {
@ -1302,14 +1302,14 @@ namespace Harness {
outputLines.push(" " + line); outputLines.push(" " + line);
fileErrors.forEach(err => { fileErrors.forEach(err => {
// Does any error start or continue on to this line? Emit squiggles // Does any error start or continue on to this line? Emit squiggles
let end = ts.textSpanEnd(err); const end = ts.textSpanEnd(err);
if ((end >= thisLineStart) && ((err.start < nextLineStart) || (lineIndex === lines.length - 1))) { if ((end >= thisLineStart) && ((err.start < nextLineStart) || (lineIndex === lines.length - 1))) {
// How many characters from the start of this line the error starts at (could be positive or negative) // How many characters from the start of this line the error starts at (could be positive or negative)
let relativeOffset = err.start - thisLineStart; const relativeOffset = err.start - thisLineStart;
// How many characters of the error are on this line (might be longer than this line in reality) // How many characters of the error are on this line (might be longer than this line in reality)
let length = (end - err.start) - Math.max(0, thisLineStart - err.start); const length = (end - err.start) - Math.max(0, thisLineStart - err.start);
// Calculate the start of the squiggle // Calculate the start of the squiggle
let squiggleStart = Math.max(0, relativeOffset); const squiggleStart = Math.max(0, relativeOffset);
// TODO/REVIEW: this doesn't work quite right in the browser if a multi file test has files whose names are just the right length relative to one another // TODO/REVIEW: this doesn't work quite right in the browser if a multi file test has files whose names are just the right length relative to one another
outputLines.push(" " + line.substr(0, squiggleStart).replace(/[^\s]/g, " ") + new Array(Math.min(length, line.length - squiggleStart) + 1).join("~")); outputLines.push(" " + line.substr(0, squiggleStart).replace(/[^\s]/g, " ") + new Array(Math.min(length, line.length - squiggleStart) + 1).join("~"));
@ -1329,11 +1329,11 @@ namespace Harness {
assert.equal(markedErrorCount, fileErrors.length, "count of errors in " + inputFile.unitName); assert.equal(markedErrorCount, fileErrors.length, "count of errors in " + inputFile.unitName);
}); });
let numLibraryDiagnostics = ts.countWhere(diagnostics, diagnostic => { const numLibraryDiagnostics = ts.countWhere(diagnostics, diagnostic => {
return diagnostic.file && (isLibraryFile(diagnostic.file.fileName) || isBuiltFile(diagnostic.file.fileName)); return diagnostic.file && (isLibraryFile(diagnostic.file.fileName) || isBuiltFile(diagnostic.file.fileName));
}); });
let numTest262HarnessDiagnostics = ts.countWhere(diagnostics, diagnostic => { const numTest262HarnessDiagnostics = ts.countWhere(diagnostics, diagnostic => {
// Count an error generated from tests262-harness folder.This should only apply for test262 // Count an error generated from tests262-harness folder.This should only apply for test262
return diagnostic.file && diagnostic.file.fileName.indexOf("test262-harness") >= 0; return diagnostic.file && diagnostic.file.fileName.indexOf("test262-harness") >= 0;
}); });
@ -1351,7 +1351,7 @@ namespace Harness {
// Emit them // Emit them
let result = ""; let result = "";
for (let outputFile of outputFiles) { for (const outputFile of outputFiles) {
// Some extra spacing if this isn't the first file // Some extra spacing if this isn't the first file
if (result.length) { if (result.length) {
result += "\r\n\r\n"; result += "\r\n\r\n";
@ -1366,7 +1366,7 @@ namespace Harness {
return result; return result;
function cleanName(fn: string) { function cleanName(fn: string) {
let lastSlash = ts.normalizeSlashes(fn).lastIndexOf("/"); const lastSlash = ts.normalizeSlashes(fn).lastIndexOf("/");
return fn.substr(lastSlash + 1).toLowerCase(); return fn.substr(lastSlash + 1).toLowerCase();
} }
} }
@ -1475,10 +1475,10 @@ namespace Harness {
} }
// Regex for parsing options in the format "@Alpha: Value of any sort" // Regex for parsing options in the format "@Alpha: Value of any sort"
let optionRegex = /^[\/]{2}\s*@(\w+)\s*:\s*(\S*)/gm; // multiple matches on multiple lines const optionRegex = /^[\/]{2}\s*@(\w+)\s*:\s*(\S*)/gm; // multiple matches on multiple lines
function extractCompilerSettings(content: string): CompilerSettings { function extractCompilerSettings(content: string): CompilerSettings {
let opts: CompilerSettings = {}; const opts: CompilerSettings = {};
let match: RegExpExecArray; let match: RegExpExecArray;
while ((match = optionRegex.exec(content)) != null) { while ((match = optionRegex.exec(content)) != null) {
@ -1490,12 +1490,12 @@ namespace Harness {
/** Given a test file containing // @FileName directives, return an array of named units of code to be added to an existing compiler instance */ /** Given a test file containing // @FileName directives, return an array of named units of code to be added to an existing compiler instance */
export function makeUnitsFromTest(code: string, fileName: string): { settings: CompilerSettings; testUnitData: TestUnitData[]; } { export function makeUnitsFromTest(code: string, fileName: string): { settings: CompilerSettings; testUnitData: TestUnitData[]; } {
let settings = extractCompilerSettings(code); const settings = extractCompilerSettings(code);
// List of all the subfiles we've parsed out // List of all the subfiles we've parsed out
let testUnitData: TestUnitData[] = []; const testUnitData: TestUnitData[] = [];
let lines = Utils.splitContentByNewlines(code); const lines = Utils.splitContentByNewlines(code);
// Stuff related to the subfile we're parsing // Stuff related to the subfile we're parsing
let currentFileContent: string = null; let currentFileContent: string = null;
@ -1504,12 +1504,12 @@ namespace Harness {
let refs: string[] = []; let refs: string[] = [];
for (let i = 0; i < lines.length; i++) { for (let i = 0; i < lines.length; i++) {
let line = lines[i]; const line = lines[i];
let testMetaData = optionRegex.exec(line); const testMetaData = optionRegex.exec(line);
if (testMetaData) { if (testMetaData) {
// Comment line, check for global/file @options and record them // Comment line, check for global/file @options and record them
optionRegex.lastIndex = 0; optionRegex.lastIndex = 0;
let metaDataName = testMetaData[1].toLowerCase(); const metaDataName = testMetaData[1].toLowerCase();
if (metaDataName === "filename") { if (metaDataName === "filename") {
currentFileOptions[testMetaData[1]] = testMetaData[2]; currentFileOptions[testMetaData[1]] = testMetaData[2];
} }
@ -1520,7 +1520,7 @@ namespace Harness {
// New metadata statement after having collected some code to go with the previous metadata // New metadata statement after having collected some code to go with the previous metadata
if (currentFileName) { if (currentFileName) {
// Store result file // Store result file
let newTestFile = { const newTestFile = {
content: currentFileContent, content: currentFileContent,
name: currentFileName, name: currentFileName,
fileOptions: currentFileOptions, fileOptions: currentFileOptions,
@ -1558,7 +1558,7 @@ namespace Harness {
currentFileName = testUnitData.length > 0 ? currentFileName : Path.getFileName(fileName); currentFileName = testUnitData.length > 0 ? currentFileName : Path.getFileName(fileName);
// EOF, push whatever remains // EOF, push whatever remains
let newTestFile2 = { const newTestFile2 = {
content: currentFileContent || "", content: currentFileContent || "",
name: currentFileName, name: currentFileName,
fileOptions: currentFileOptions, fileOptions: currentFileOptions,
@ -1606,7 +1606,7 @@ namespace Harness {
} }
} }
let fileCache: { [idx: string]: boolean } = {}; const fileCache: { [idx: string]: boolean } = {};
function generateActual(actualFileName: string, generateContent: () => string): string { function generateActual(actualFileName: string, generateContent: () => string): string {
// For now this is written using TypeScript, because sys is not available when running old test cases. // For now this is written using TypeScript, because sys is not available when running old test cases.
// But we need to move to sys once we have // But we need to move to sys once we have
@ -1617,7 +1617,7 @@ namespace Harness {
return; return;
} }
let parentDirectory = IO.directoryName(dirName); const parentDirectory = IO.directoryName(dirName);
if (parentDirectory != "") { if (parentDirectory != "") {
createDirectoryStructure(parentDirectory); createDirectoryStructure(parentDirectory);
} }
@ -1633,7 +1633,7 @@ namespace Harness {
IO.deleteFile(actualFileName); IO.deleteFile(actualFileName);
} }
let actual = generateContent(); const actual = generateContent();
if (actual === undefined) { if (actual === undefined) {
throw new Error("The generated content was \"undefined\". Return \"null\" if no baselining is required.\""); throw new Error("The generated content was \"undefined\". Return \"null\" if no baselining is required.\"");
@ -1656,7 +1656,7 @@ namespace Harness {
return; return;
} }
let refFileName = referencePath(relativeFileName, opts && opts.Baselinefolder, opts && opts.Subfolder); const refFileName = referencePath(relativeFileName, opts && opts.Baselinefolder, opts && opts.Subfolder);
if (actual === null) { if (actual === null) {
actual = "<no content>"; actual = "<no content>";
@ -1671,10 +1671,10 @@ namespace Harness {
} }
function writeComparison(expected: string, actual: string, relativeFileName: string, actualFileName: string, descriptionForDescribe: string) { function writeComparison(expected: string, actual: string, relativeFileName: string, actualFileName: string, descriptionForDescribe: string) {
let encoded_actual = Utils.encodeString(actual); const encoded_actual = Utils.encodeString(actual);
if (expected != encoded_actual) { if (expected != encoded_actual) {
// Overwrite & issue error // Overwrite & issue error
let errMsg = "The baseline file " + relativeFileName + " has changed"; const errMsg = "The baseline file " + relativeFileName + " has changed";
throw new Error(errMsg); throw new Error(errMsg);
} }
} }
@ -1687,17 +1687,17 @@ namespace Harness {
opts?: BaselineOptions): void { opts?: BaselineOptions): void {
let actual = <string>undefined; let actual = <string>undefined;
let actualFileName = localPath(relativeFileName, opts && opts.Baselinefolder, opts && opts.Subfolder); const actualFileName = localPath(relativeFileName, opts && opts.Baselinefolder, opts && opts.Subfolder);
if (runImmediately) { if (runImmediately) {
actual = generateActual(actualFileName, generateContent); actual = generateActual(actualFileName, generateContent);
let comparison = compareToBaseline(actual, relativeFileName, opts); const comparison = compareToBaseline(actual, relativeFileName, opts);
writeComparison(comparison.expected, comparison.actual, relativeFileName, actualFileName, descriptionForDescribe); writeComparison(comparison.expected, comparison.actual, relativeFileName, actualFileName, descriptionForDescribe);
} }
else { else {
actual = generateActual(actualFileName, generateContent); actual = generateActual(actualFileName, generateContent);
let comparison = compareToBaseline(actual, relativeFileName, opts); const comparison = compareToBaseline(actual, relativeFileName, opts);
writeComparison(comparison.expected, comparison.actual, relativeFileName, actualFileName, descriptionForDescribe); writeComparison(comparison.expected, comparison.actual, relativeFileName, actualFileName, descriptionForDescribe);
} }
} }
@ -1712,7 +1712,7 @@ namespace Harness {
} }
export function getDefaultLibraryFile(io: Harness.IO): { unitName: string, content: string } { export function getDefaultLibraryFile(io: Harness.IO): { unitName: string, content: string } {
let libFile = Harness.userSpecifiedRoot + Harness.libFolder + "lib.d.ts"; const libFile = Harness.userSpecifiedRoot + Harness.libFolder + "lib.d.ts";
return { return {
unitName: libFile, unitName: libFile,
content: io.readFile(libFile) content: io.readFile(libFile)

View file

@ -26,9 +26,9 @@ namespace Harness.LanguageService {
public editContent(start: number, end: number, newText: string): void { public editContent(start: number, end: number, newText: string): void {
// Apply edits // Apply edits
let prefix = this.content.substring(0, start); const prefix = this.content.substring(0, start);
let middle = newText; const middle = newText;
let suffix = this.content.substring(end); const suffix = this.content.substring(end);
this.setContent(prefix + middle + suffix); this.setContent(prefix + middle + suffix);
// Store edit range + new length of script // Store edit range + new length of script
@ -48,10 +48,10 @@ namespace Harness.LanguageService {
return ts.unchangedTextChangeRange; return ts.unchangedTextChangeRange;
} }
let initialEditRangeIndex = this.editRanges.length - (this.version - startVersion); const initialEditRangeIndex = this.editRanges.length - (this.version - startVersion);
let lastEditRangeIndex = this.editRanges.length - (this.version - endVersion); const lastEditRangeIndex = this.editRanges.length - (this.version - endVersion);
let entries = this.editRanges.slice(initialEditRangeIndex, lastEditRangeIndex); const entries = this.editRanges.slice(initialEditRangeIndex, lastEditRangeIndex);
return ts.collapseTextChangeRangesAcrossMultipleVersions(entries.map(e => e.textChangeRange)); return ts.collapseTextChangeRangesAcrossMultipleVersions(entries.map(e => e.textChangeRange));
} }
} }
@ -74,7 +74,7 @@ namespace Harness.LanguageService {
} }
public getChangeRange(oldScript: ts.IScriptSnapshot): ts.TextChangeRange { public getChangeRange(oldScript: ts.IScriptSnapshot): ts.TextChangeRange {
let oldShim = <ScriptSnapshot>oldScript; const oldShim = <ScriptSnapshot>oldScript;
return this.scriptInfo.getTextChangeRangeBetweenVersions(oldShim.version, this.version); return this.scriptInfo.getTextChangeRangeBetweenVersions(oldShim.version, this.version);
} }
} }
@ -92,9 +92,9 @@ namespace Harness.LanguageService {
} }
public getChangeRange(oldScript: ts.ScriptSnapshotShim): string { public getChangeRange(oldScript: ts.ScriptSnapshotShim): string {
let oldShim = <ScriptSnapshotProxy>oldScript; const oldShim = <ScriptSnapshotProxy>oldScript;
let range = this.scriptSnapshot.getChangeRange(oldShim.scriptSnapshot); const range = this.scriptSnapshot.getChangeRange(oldShim.scriptSnapshot);
if (range === undefined) { if (range === undefined) {
return undefined; return undefined;
} }
@ -130,7 +130,7 @@ namespace Harness.LanguageService {
} }
public getFilenames(): string[] { public getFilenames(): string[] {
let fileNames: string[] = []; const fileNames: string[] = [];
ts.forEachKey(this.fileNameToScript, (fileName) => { fileNames.push(fileName); }); ts.forEachKey(this.fileNameToScript, (fileName) => { fileNames.push(fileName); });
return fileNames; return fileNames;
} }
@ -144,7 +144,7 @@ namespace Harness.LanguageService {
} }
public editScript(fileName: string, start: number, end: number, newText: string) { public editScript(fileName: string, start: number, end: number, newText: string) {
let script = this.getScriptInfo(fileName); const script = this.getScriptInfo(fileName);
if (script !== undefined) { if (script !== undefined) {
script.editContent(start, end, newText); script.editContent(start, end, newText);
return; return;
@ -161,7 +161,7 @@ namespace Harness.LanguageService {
* @param col 0 based index * @param col 0 based index
*/ */
public positionToLineAndCharacter(fileName: string, position: number): ts.LineAndCharacter { public positionToLineAndCharacter(fileName: string, position: number): ts.LineAndCharacter {
let script: ScriptInfo = this.fileNameToScript[fileName]; const script: ScriptInfo = this.fileNameToScript[fileName];
assert.isNotNull(script); assert.isNotNull(script);
return ts.computeLineAndCharacterOfPosition(script.lineMap, position); return ts.computeLineAndCharacterOfPosition(script.lineMap, position);
@ -176,11 +176,11 @@ namespace Harness.LanguageService {
getDefaultLibFileName(): string { return ""; } getDefaultLibFileName(): string { return ""; }
getScriptFileNames(): string[] { return this.getFilenames(); } getScriptFileNames(): string[] { return this.getFilenames(); }
getScriptSnapshot(fileName: string): ts.IScriptSnapshot { getScriptSnapshot(fileName: string): ts.IScriptSnapshot {
let script = this.getScriptInfo(fileName); const script = this.getScriptInfo(fileName);
return script ? new ScriptSnapshot(script) : undefined; return script ? new ScriptSnapshot(script) : undefined;
} }
getScriptVersion(fileName: string): string { getScriptVersion(fileName: string): string {
let script = this.getScriptInfo(fileName); const script = this.getScriptInfo(fileName);
return script ? script.version.toString() : undefined; return script ? script.version.toString() : undefined;
} }
@ -211,20 +211,20 @@ namespace Harness.LanguageService {
this.nativeHost = new NativeLanguageServiceHost(cancellationToken, options); this.nativeHost = new NativeLanguageServiceHost(cancellationToken, options);
if (preprocessToResolve) { if (preprocessToResolve) {
let compilerOptions = this.nativeHost.getCompilationSettings(); const compilerOptions = this.nativeHost.getCompilationSettings();
let moduleResolutionHost: ts.ModuleResolutionHost = { const moduleResolutionHost: ts.ModuleResolutionHost = {
fileExists: fileName => this.getScriptInfo(fileName) !== undefined, fileExists: fileName => this.getScriptInfo(fileName) !== undefined,
readFile: fileName => { readFile: fileName => {
let scriptInfo = this.getScriptInfo(fileName); const scriptInfo = this.getScriptInfo(fileName);
return scriptInfo && scriptInfo.content; return scriptInfo && scriptInfo.content;
} }
}; };
this.getModuleResolutionsForFile = (fileName) => { this.getModuleResolutionsForFile = (fileName) => {
let scriptInfo = this.getScriptInfo(fileName); const scriptInfo = this.getScriptInfo(fileName);
let preprocessInfo = ts.preProcessFile(scriptInfo.content, /*readImportFiles*/ true); const preprocessInfo = ts.preProcessFile(scriptInfo.content, /*readImportFiles*/ true);
let imports: ts.Map<string> = {}; const imports: ts.Map<string> = {};
for (let module of preprocessInfo.importedFiles) { for (const module of preprocessInfo.importedFiles) {
let resolutionInfo = ts.resolveModuleName(module.fileName, fileName, compilerOptions, moduleResolutionHost); const resolutionInfo = ts.resolveModuleName(module.fileName, fileName, compilerOptions, moduleResolutionHost);
if (resolutionInfo.resolvedModule) { if (resolutionInfo.resolvedModule) {
imports[module.fileName] = resolutionInfo.resolvedModule.resolvedFileName; imports[module.fileName] = resolutionInfo.resolvedModule.resolvedFileName;
} }
@ -246,7 +246,7 @@ namespace Harness.LanguageService {
getDefaultLibFileName(): string { return this.nativeHost.getDefaultLibFileName(); } getDefaultLibFileName(): string { return this.nativeHost.getDefaultLibFileName(); }
getScriptFileNames(): string { return JSON.stringify(this.nativeHost.getScriptFileNames()); } getScriptFileNames(): string { return JSON.stringify(this.nativeHost.getScriptFileNames()); }
getScriptSnapshot(fileName: string): ts.ScriptSnapshotShim { getScriptSnapshot(fileName: string): ts.ScriptSnapshotShim {
let nativeScriptSnapshot = this.nativeHost.getScriptSnapshot(fileName); const nativeScriptSnapshot = this.nativeHost.getScriptSnapshot(fileName);
return nativeScriptSnapshot && new ScriptSnapshotProxy(nativeScriptSnapshot); return nativeScriptSnapshot && new ScriptSnapshotProxy(nativeScriptSnapshot);
} }
getScriptVersion(fileName: string): string { return this.nativeHost.getScriptVersion(fileName); } getScriptVersion(fileName: string): string { return this.nativeHost.getScriptVersion(fileName); }
@ -257,7 +257,7 @@ namespace Harness.LanguageService {
} }
fileExists(fileName: string) { return this.getScriptInfo(fileName) !== undefined; } fileExists(fileName: string) { return this.getScriptInfo(fileName) !== undefined; }
readFile(fileName: string) { readFile(fileName: string) {
let snapshot = this.nativeHost.getScriptSnapshot(fileName); const snapshot = this.nativeHost.getScriptSnapshot(fileName);
return snapshot && snapshot.getText(0, snapshot.getLength()); return snapshot && snapshot.getText(0, snapshot.getLength());
} }
log(s: string): void { this.nativeHost.log(s); } log(s: string): void { this.nativeHost.log(s); }
@ -272,13 +272,13 @@ namespace Harness.LanguageService {
throw new Error("NYI"); throw new Error("NYI");
} }
getClassificationsForLine(text: string, lexState: ts.EndOfLineState, classifyKeywordsInGenerics?: boolean): ts.ClassificationResult { getClassificationsForLine(text: string, lexState: ts.EndOfLineState, classifyKeywordsInGenerics?: boolean): ts.ClassificationResult {
let result = this.shim.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics).split("\n"); const result = this.shim.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics).split("\n");
let entries: ts.ClassificationInfo[] = []; const entries: ts.ClassificationInfo[] = [];
let i = 0; let i = 0;
let position = 0; let position = 0;
for (; i < result.length - 1; i += 2) { for (; i < result.length - 1; i += 2) {
let t = entries[i / 2] = { const t = entries[i / 2] = {
length: parseInt(result[i]), length: parseInt(result[i]),
classification: parseInt(result[i + 1]) classification: parseInt(result[i + 1])
}; };
@ -286,7 +286,7 @@ namespace Harness.LanguageService {
assert.isTrue(t.length > 0, "Result length should be greater than 0, got :" + t.length); assert.isTrue(t.length > 0, "Result length should be greater than 0, got :" + t.length);
position += t.length; position += t.length;
} }
let finalLexState = parseInt(result[result.length - 1]); const finalLexState = parseInt(result[result.length - 1]);
assert.equal(position, text.length, "Expected cumulative length of all entries to match the length of the source. expected: " + text.length + ", but got: " + position); assert.equal(position, text.length, "Expected cumulative length of all entries to match the length of the source. expected: " + text.length + ", but got: " + position);
@ -298,7 +298,7 @@ namespace Harness.LanguageService {
} }
function unwrapJSONCallResult(result: string): any { function unwrapJSONCallResult(result: string): any {
let parsedResult = JSON.parse(result); const parsedResult = JSON.parse(result);
if (parsedResult.error) { if (parsedResult.error) {
throw new Error("Language Service Shim Error: " + JSON.stringify(parsedResult.error)); throw new Error("Language Service Shim Error: " + JSON.stringify(parsedResult.error));
} }
@ -312,7 +312,7 @@ namespace Harness.LanguageService {
constructor(private shim: ts.LanguageServiceShim) { constructor(private shim: ts.LanguageServiceShim) {
} }
private unwrappJSONCallResult(result: string): any { private unwrappJSONCallResult(result: string): any {
let parsedResult = JSON.parse(result); const parsedResult = JSON.parse(result);
if (parsedResult.error) { if (parsedResult.error) {
throw new Error("Language Service Shim Error: " + JSON.stringify(parsedResult.error)); throw new Error("Language Service Shim Error: " + JSON.stringify(parsedResult.error));
} }
@ -443,10 +443,10 @@ namespace Harness.LanguageService {
isLibFile: boolean; isLibFile: boolean;
}; };
let coreServicesShim = this.factory.createCoreServicesShim(this.host); const coreServicesShim = this.factory.createCoreServicesShim(this.host);
shimResult = unwrapJSONCallResult(coreServicesShim.getPreProcessedFileInfo(fileName, ts.ScriptSnapshot.fromString(fileContents))); shimResult = unwrapJSONCallResult(coreServicesShim.getPreProcessedFileInfo(fileName, ts.ScriptSnapshot.fromString(fileContents)));
let convertResult: ts.PreProcessedFileInfo = { const convertResult: ts.PreProcessedFileInfo = {
referencedFiles: [], referencedFiles: [],
importedFiles: [], importedFiles: [],
ambientExternalModules: [], ambientExternalModules: [],
@ -530,7 +530,7 @@ namespace Harness.LanguageService {
fileName = Harness.Compiler.defaultLibFileName; fileName = Harness.Compiler.defaultLibFileName;
} }
let snapshot = this.host.getScriptSnapshot(fileName); const snapshot = this.host.getScriptSnapshot(fileName);
return snapshot && snapshot.getText(0, snapshot.getLength()); return snapshot && snapshot.getText(0, snapshot.getLength());
} }
@ -612,13 +612,13 @@ namespace Harness.LanguageService {
private client: ts.server.SessionClient; private client: ts.server.SessionClient;
constructor(cancellationToken?: ts.HostCancellationToken, options?: ts.CompilerOptions) { constructor(cancellationToken?: ts.HostCancellationToken, options?: ts.CompilerOptions) {
// This is the main host that tests use to direct tests // This is the main host that tests use to direct tests
let clientHost = new SessionClientHost(cancellationToken, options); const clientHost = new SessionClientHost(cancellationToken, options);
let client = new ts.server.SessionClient(clientHost); const client = new ts.server.SessionClient(clientHost);
// This host is just a proxy for the clientHost, it uses the client // This host is just a proxy for the clientHost, it uses the client
// host to answer server queries about files on disk // host to answer server queries about files on disk
let serverHost = new SessionServerHost(clientHost); const serverHost = new SessionServerHost(clientHost);
let server = new ts.server.Session(serverHost, const server = new ts.server.Session(serverHost,
Buffer ? Buffer.byteLength : (string: string, encoding?: string) => string.length, Buffer ? Buffer.byteLength : (string: string, encoding?: string) => string.length,
process.hrtime, serverHost); process.hrtime, serverHost);

View file

@ -89,7 +89,7 @@ namespace Playback {
function memoize<T>(func: (s: string) => T): Memoized<T> { function memoize<T>(func: (s: string) => T): Memoized<T> {
let lookup: { [s: string]: T } = {}; let lookup: { [s: string]: T } = {};
let run: Memoized<T> = <Memoized<T>>((s: string) => { const run: Memoized<T> = <Memoized<T>>((s: string) => {
if (lookup.hasOwnProperty(s)) return lookup[s]; if (lookup.hasOwnProperty(s)) return lookup[s];
return lookup[s] = func(s); return lookup[s] = func(s);
}); });
@ -159,7 +159,7 @@ namespace Playback {
wrapper.endRecord = () => { wrapper.endRecord = () => {
if (recordLog !== undefined) { if (recordLog !== undefined) {
let i = 0; let i = 0;
let fn = () => recordLogFileNameBase + i + ".json"; const fn = () => recordLogFileNameBase + i + ".json";
while (underlying.fileExists(fn())) i++; while (underlying.fileExists(fn())) i++;
underlying.writeFile(fn(), JSON.stringify(recordLog)); underlying.writeFile(fn(), JSON.stringify(recordLog));
recordLog = undefined; recordLog = undefined;
@ -209,8 +209,8 @@ namespace Playback {
wrapper.readFile = recordReplay(wrapper.readFile, underlying)( wrapper.readFile = recordReplay(wrapper.readFile, underlying)(
path => { path => {
let result = underlying.readFile(path); const result = underlying.readFile(path);
let logEntry = { path, codepage: 0, result: { contents: result, codepage: 0 } }; const logEntry = { path, codepage: 0, result: { contents: result, codepage: 0 } };
recordLog.filesRead.push(logEntry); recordLog.filesRead.push(logEntry);
return result; return result;
}, },
@ -218,8 +218,8 @@ namespace Playback {
wrapper.readDirectory = recordReplay(wrapper.readDirectory, underlying)( wrapper.readDirectory = recordReplay(wrapper.readDirectory, underlying)(
(path, extension, exclude) => { (path, extension, exclude) => {
let result = (<ts.System>underlying).readDirectory(path, extension, exclude); const result = (<ts.System>underlying).readDirectory(path, extension, exclude);
let logEntry = { path, extension, exclude, result }; const logEntry = { path, extension, exclude, result };
recordLog.directoriesRead.push(logEntry); recordLog.directoriesRead.push(logEntry);
return result; return result;
}, },
@ -263,10 +263,10 @@ namespace Playback {
} }
function findResultByFields<T>(logArray: { result?: T }[], expectedFields: {}, defaultValue?: T): T { function findResultByFields<T>(logArray: { result?: T }[], expectedFields: {}, defaultValue?: T): T {
let predicate = (entry: { result?: T }) => { const predicate = (entry: { result?: T }) => {
return Object.getOwnPropertyNames(expectedFields).every((name) => (<any>entry)[name] === (<any>expectedFields)[name]); return Object.getOwnPropertyNames(expectedFields).every((name) => (<any>entry)[name] === (<any>expectedFields)[name]);
}; };
let results = logArray.filter(entry => predicate(entry)); const results = logArray.filter(entry => predicate(entry));
if (results.length === 0) { if (results.length === 0) {
if (defaultValue !== undefined) { if (defaultValue !== undefined) {
return defaultValue; return defaultValue;
@ -279,7 +279,7 @@ namespace Playback {
} }
function findResultByPath<T>(wrapper: { resolvePath(s: string): string }, logArray: { path: string; result?: T }[], expectedPath: string, defaultValue?: T): T { function findResultByPath<T>(wrapper: { resolvePath(s: string): string }, logArray: { path: string; result?: T }[], expectedPath: string, defaultValue?: T): T {
let normalizedName = ts.normalizePath(expectedPath).toLowerCase(); const normalizedName = ts.normalizePath(expectedPath).toLowerCase();
// Try to find the result through normal fileName // Try to find the result through normal fileName
for (let i = 0; i < logArray.length; i++) { for (let i = 0; i < logArray.length; i++) {
if (ts.normalizeSlashes(logArray[i].path).toLowerCase() === normalizedName) { if (ts.normalizeSlashes(logArray[i].path).toLowerCase() === normalizedName) {
@ -288,7 +288,7 @@ namespace Playback {
} }
// Fallback, try to resolve the target paths as well // Fallback, try to resolve the target paths as well
if (replayLog.pathsResolved.length > 0) { if (replayLog.pathsResolved.length > 0) {
let normalizedResolvedName = wrapper.resolvePath(expectedPath).toLowerCase(); const normalizedResolvedName = wrapper.resolvePath(expectedPath).toLowerCase();
for (let i = 0; i < logArray.length; i++) { for (let i = 0; i < logArray.length; i++) {
if (wrapper.resolvePath(logArray[i].path).toLowerCase() === normalizedResolvedName) { if (wrapper.resolvePath(logArray[i].path).toLowerCase() === normalizedResolvedName) {
return logArray[i].result; return logArray[i].result;
@ -305,9 +305,9 @@ namespace Playback {
} }
} }
let pathEquivCache: any = {}; const pathEquivCache: any = {};
function pathsAreEquivalent(left: string, right: string, wrapper: { resolvePath(s: string): string }) { function pathsAreEquivalent(left: string, right: string, wrapper: { resolvePath(s: string): string }) {
let key = left + "-~~-" + right; const key = left + "-~~-" + right;
function areSame(a: string, b: string) { function areSame(a: string, b: string) {
return ts.normalizeSlashes(a).toLowerCase() === ts.normalizeSlashes(b).toLowerCase(); return ts.normalizeSlashes(a).toLowerCase() === ts.normalizeSlashes(b).toLowerCase();
} }
@ -329,7 +329,7 @@ namespace Playback {
} }
export function wrapIO(underlying: Harness.IO): PlaybackIO { export function wrapIO(underlying: Harness.IO): PlaybackIO {
let wrapper: PlaybackIO = <any>{}; const wrapper: PlaybackIO = <any>{};
initWrapper(wrapper, underlying); initWrapper(wrapper, underlying);
wrapper.directoryName = (path): string => { throw new Error("NotSupported"); }; wrapper.directoryName = (path): string => { throw new Error("NotSupported"); };
@ -342,7 +342,7 @@ namespace Playback {
} }
export function wrapSystem(underlying: ts.System): PlaybackSystem { export function wrapSystem(underlying: ts.System): PlaybackSystem {
let wrapper: PlaybackSystem = <any>{}; const wrapper: PlaybackSystem = <any>{};
initWrapper(wrapper, underlying); initWrapper(wrapper, underlying);
return wrapper; return wrapper;
} }

View file

@ -47,7 +47,7 @@ interface BatchCompileProjectTestCaseResult extends CompileProjectFilesResult {
class ProjectRunner extends RunnerBase { class ProjectRunner extends RunnerBase {
public initializeTests() { public initializeTests() {
if (this.tests.length === 0) { if (this.tests.length === 0) {
let testFiles = this.enumerateFiles("tests/cases/project", /\.json$/, { recursive: true }); const testFiles = this.enumerateFiles("tests/cases/project", /\.json$/, { recursive: true });
testFiles.forEach(fn => { testFiles.forEach(fn => {
fn = fn.replace(/\\/g, "/"); fn = fn.replace(/\\/g, "/");
this.runProjectTestCase(fn); this.runProjectTestCase(fn);
@ -101,7 +101,7 @@ class ProjectRunner extends RunnerBase {
function cleanProjectUrl(url: string) { function cleanProjectUrl(url: string) {
let diskProjectPath = ts.normalizeSlashes(Harness.IO.resolvePath(testCase.projectRoot)); let diskProjectPath = ts.normalizeSlashes(Harness.IO.resolvePath(testCase.projectRoot));
let projectRootUrl = "file:///" + diskProjectPath; let projectRootUrl = "file:///" + diskProjectPath;
let normalizedProjectRoot = ts.normalizeSlashes(testCase.projectRoot); const normalizedProjectRoot = ts.normalizeSlashes(testCase.projectRoot);
diskProjectPath = diskProjectPath.substr(0, diskProjectPath.lastIndexOf(normalizedProjectRoot)); diskProjectPath = diskProjectPath.substr(0, diskProjectPath.lastIndexOf(normalizedProjectRoot));
projectRootUrl = projectRootUrl.substr(0, projectRootUrl.lastIndexOf(normalizedProjectRoot)); projectRootUrl = projectRootUrl.substr(0, projectRootUrl.lastIndexOf(normalizedProjectRoot));
if (url && url.length) { if (url && url.length) {
@ -130,12 +130,12 @@ class ProjectRunner extends RunnerBase {
getSourceFileTextImpl: (fileName: string) => string, getSourceFileTextImpl: (fileName: string) => string,
writeFile: (fileName: string, data: string, writeByteOrderMark: boolean) => void): CompileProjectFilesResult { writeFile: (fileName: string, data: string, writeByteOrderMark: boolean) => void): CompileProjectFilesResult {
let program = ts.createProgram(getInputFiles(), createCompilerOptions(), createCompilerHost()); const program = ts.createProgram(getInputFiles(), createCompilerOptions(), createCompilerHost());
let errors = ts.getPreEmitDiagnostics(program); let errors = ts.getPreEmitDiagnostics(program);
let emitResult = program.emit(); const emitResult = program.emit();
errors = ts.concatenate(errors, emitResult.diagnostics); errors = ts.concatenate(errors, emitResult.diagnostics);
let sourceMapData = emitResult.sourceMaps; const sourceMapData = emitResult.sourceMaps;
// Clean up source map data that will be used in baselining // Clean up source map data that will be used in baselining
if (sourceMapData) { if (sourceMapData) {
@ -181,7 +181,7 @@ class ProjectRunner extends RunnerBase {
sourceFile = languageVersion === ts.ScriptTarget.ES6 ? Harness.Compiler.defaultES6LibSourceFile : Harness.Compiler.defaultLibSourceFile; sourceFile = languageVersion === ts.ScriptTarget.ES6 ? Harness.Compiler.defaultES6LibSourceFile : Harness.Compiler.defaultLibSourceFile;
} }
else { else {
let text = getSourceFileText(fileName); const text = getSourceFileText(fileName);
if (text !== undefined) { if (text !== undefined) {
sourceFile = Harness.Compiler.createSourceFileAndAssertInvariants(fileName, text, languageVersion); sourceFile = Harness.Compiler.createSourceFileAndAssertInvariants(fileName, text, languageVersion);
} }
@ -208,9 +208,9 @@ class ProjectRunner extends RunnerBase {
function batchCompilerProjectTestCase(moduleKind: ts.ModuleKind): BatchCompileProjectTestCaseResult { function batchCompilerProjectTestCase(moduleKind: ts.ModuleKind): BatchCompileProjectTestCaseResult {
let nonSubfolderDiskFiles = 0; let nonSubfolderDiskFiles = 0;
let outputFiles: BatchCompileProjectTestCaseEmittedFile[] = []; const outputFiles: BatchCompileProjectTestCaseEmittedFile[] = [];
let projectCompilerResult = compileProjectFiles(moduleKind, () => testCase.inputFiles, getSourceFileText, writeFile); const projectCompilerResult = compileProjectFiles(moduleKind, () => testCase.inputFiles, getSourceFileText, writeFile);
return { return {
moduleKind, moduleKind,
program: projectCompilerResult.program, program: projectCompilerResult.program,
@ -236,11 +236,11 @@ class ProjectRunner extends RunnerBase {
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean) { function writeFile(fileName: string, data: string, writeByteOrderMark: boolean) {
// convert file name to rooted name // convert file name to rooted name
// if filename is not rooted - concat it with project root and then expand project root relative to current directory // if filename is not rooted - concat it with project root and then expand project root relative to current directory
let diskFileName = ts.isRootedDiskPath(fileName) const diskFileName = ts.isRootedDiskPath(fileName)
? fileName ? fileName
: Harness.IO.resolvePath(ts.normalizeSlashes(testCase.projectRoot) + "/" + ts.normalizeSlashes(fileName)); : Harness.IO.resolvePath(ts.normalizeSlashes(testCase.projectRoot) + "/" + ts.normalizeSlashes(fileName));
let currentDirectory = getCurrentDirectory(); const currentDirectory = getCurrentDirectory();
// compute file name relative to current directory (expanded project root) // compute file name relative to current directory (expanded project root)
let diskRelativeName = ts.getRelativePathToDirectoryOrUrl(currentDirectory, diskFileName, currentDirectory, Harness.Compiler.getCanonicalFileName, /*isAbsolutePathAnUrl*/ false); let diskRelativeName = ts.getRelativePathToDirectoryOrUrl(currentDirectory, diskFileName, currentDirectory, Harness.Compiler.getCanonicalFileName, /*isAbsolutePathAnUrl*/ false);
if (ts.isRootedDiskPath(diskRelativeName) || diskRelativeName.substr(0, 3) === "../") { if (ts.isRootedDiskPath(diskRelativeName) || diskRelativeName.substr(0, 3) === "../") {
@ -254,14 +254,14 @@ class ProjectRunner extends RunnerBase {
if (Harness.Compiler.isJS(fileName)) { if (Harness.Compiler.isJS(fileName)) {
// Make sure if there is URl we have it cleaned up // Make sure if there is URl we have it cleaned up
let indexOfSourceMapUrl = data.lastIndexOf("//# sourceMappingURL="); const indexOfSourceMapUrl = data.lastIndexOf("//# sourceMappingURL=");
if (indexOfSourceMapUrl !== -1) { if (indexOfSourceMapUrl !== -1) {
data = data.substring(0, indexOfSourceMapUrl + 21) + cleanProjectUrl(data.substring(indexOfSourceMapUrl + 21)); data = data.substring(0, indexOfSourceMapUrl + 21) + cleanProjectUrl(data.substring(indexOfSourceMapUrl + 21));
} }
} }
else if (Harness.Compiler.isJSMap(fileName)) { else if (Harness.Compiler.isJSMap(fileName)) {
// Make sure sources list is cleaned // Make sure sources list is cleaned
let sourceMapData = JSON.parse(data); const sourceMapData = JSON.parse(data);
for (let i = 0; i < sourceMapData.sources.length; i++) { for (let i = 0; i < sourceMapData.sources.length; i++) {
sourceMapData.sources[i] = cleanProjectUrl(sourceMapData.sources[i]); sourceMapData.sources[i] = cleanProjectUrl(sourceMapData.sources[i]);
} }
@ -269,7 +269,7 @@ class ProjectRunner extends RunnerBase {
data = JSON.stringify(sourceMapData); data = JSON.stringify(sourceMapData);
} }
let outputFilePath = getProjectOutputFolder(diskRelativeName, moduleKind); const outputFilePath = getProjectOutputFolder(diskRelativeName, moduleKind);
// Actual writing of file as in tc.ts // Actual writing of file as in tc.ts
function ensureDirectoryStructure(directoryname: string) { function ensureDirectoryStructure(directoryname: string) {
if (directoryname) { if (directoryname) {
@ -287,8 +287,8 @@ class ProjectRunner extends RunnerBase {
} }
function compileCompileDTsFiles(compilerResult: BatchCompileProjectTestCaseResult) { function compileCompileDTsFiles(compilerResult: BatchCompileProjectTestCaseResult) {
let allInputFiles: { emittedFileName: string; code: string; }[] = []; const allInputFiles: { emittedFileName: string; code: string; }[] = [];
let compilerOptions = compilerResult.program.getCompilerOptions(); const compilerOptions = compilerResult.program.getCompilerOptions();
ts.forEach(compilerResult.program.getSourceFiles(), sourceFile => { ts.forEach(compilerResult.program.getSourceFiles(), sourceFile => {
if (Harness.Compiler.isDTS(sourceFile.fileName)) { if (Harness.Compiler.isDTS(sourceFile.fileName)) {
@ -305,15 +305,15 @@ class ProjectRunner extends RunnerBase {
emitOutputFilePathWithoutExtension = ts.removeFileExtension(sourceFile.fileName); emitOutputFilePathWithoutExtension = ts.removeFileExtension(sourceFile.fileName);
} }
let outputDtsFileName = emitOutputFilePathWithoutExtension + ".d.ts"; const outputDtsFileName = emitOutputFilePathWithoutExtension + ".d.ts";
let file = findOutpuDtsFile(outputDtsFileName); const file = findOutpuDtsFile(outputDtsFileName);
if (file) { if (file) {
allInputFiles.unshift(file); allInputFiles.unshift(file);
} }
} }
else { else {
let outputDtsFileName = ts.removeFileExtension(compilerOptions.outFile || compilerOptions.out) + ".d.ts"; const outputDtsFileName = ts.removeFileExtension(compilerOptions.outFile || compilerOptions.out) + ".d.ts";
let outputDtsFile = findOutpuDtsFile(outputDtsFileName); const outputDtsFile = findOutpuDtsFile(outputDtsFileName);
if (!ts.contains(allInputFiles, outputDtsFile)) { if (!ts.contains(allInputFiles, outputDtsFile)) {
allInputFiles.unshift(outputDtsFile); allInputFiles.unshift(outputDtsFile);
} }
@ -346,7 +346,7 @@ class ProjectRunner extends RunnerBase {
} }
function getErrorsBaseline(compilerResult: CompileProjectFilesResult) { function getErrorsBaseline(compilerResult: CompileProjectFilesResult) {
let inputFiles = ts.map(ts.filter(compilerResult.program.getSourceFiles(), const inputFiles = ts.map(ts.filter(compilerResult.program.getSourceFiles(),
sourceFile => sourceFile.fileName !== "lib.d.ts"), sourceFile => sourceFile.fileName !== "lib.d.ts"),
sourceFile => { sourceFile => {
return { unitName: RunnerBase.removeFullPaths(sourceFile.fileName), content: sourceFile.text }; return { unitName: RunnerBase.removeFullPaths(sourceFile.fileName), content: sourceFile.text };
@ -355,7 +355,7 @@ class ProjectRunner extends RunnerBase {
return Harness.Compiler.getErrorBaseline(inputFiles, compilerResult.errors); return Harness.Compiler.getErrorBaseline(inputFiles, compilerResult.errors);
} }
let name = "Compiling project for " + testCase.scenario + ": testcase " + testCaseFileName; const name = "Compiling project for " + testCase.scenario + ": testcase " + testCaseFileName;
describe("Projects tests", () => { describe("Projects tests", () => {
describe(name, () => { describe(name, () => {
@ -363,7 +363,7 @@ class ProjectRunner extends RunnerBase {
let compilerResult: BatchCompileProjectTestCaseResult; let compilerResult: BatchCompileProjectTestCaseResult;
function getCompilerResolutionInfo() { function getCompilerResolutionInfo() {
let resolutionInfo: ProjectRunnerTestCaseResolutionInfo = { const resolutionInfo: ProjectRunnerTestCaseResolutionInfo = {
scenario: testCase.scenario, scenario: testCase.scenario,
projectRoot: testCase.projectRoot, projectRoot: testCase.projectRoot,
inputFiles: testCase.inputFiles, inputFiles: testCase.inputFiles,
@ -441,7 +441,7 @@ class ProjectRunner extends RunnerBase {
it("Errors in generated Dts files for (" + moduleNameToString(moduleKind) + "): " + testCaseFileName, () => { it("Errors in generated Dts files for (" + moduleNameToString(moduleKind) + "): " + testCaseFileName, () => {
if (!compilerResult.errors.length && testCase.declaration) { if (!compilerResult.errors.length && testCase.declaration) {
let dTsCompileResult = compileCompileDTsFiles(compilerResult); const dTsCompileResult = compileCompileDTsFiles(compilerResult);
if (dTsCompileResult.errors.length) { if (dTsCompileResult.errors.length) {
Harness.Baseline.runBaseline("Errors in generated Dts files for (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".dts.errors.txt", () => { Harness.Baseline.runBaseline("Errors in generated Dts files for (" + moduleNameToString(compilerResult.moduleKind) + "): " + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + ".dts.errors.txt", () => {
return getErrorsBaseline(dTsCompileResult); return getErrorsBaseline(dTsCompileResult);

View file

@ -41,13 +41,13 @@ let testConfigFile =
(Harness.IO.fileExists(testconfig) ? Harness.IO.readFile(testconfig) : ""); (Harness.IO.fileExists(testconfig) ? Harness.IO.readFile(testconfig) : "");
if (testConfigFile !== "") { if (testConfigFile !== "") {
let testConfig = JSON.parse(testConfigFile); const testConfig = JSON.parse(testConfigFile);
if (testConfig.light) { if (testConfig.light) {
Harness.lightMode = true; Harness.lightMode = true;
} }
if (testConfig.test && testConfig.test.length > 0) { if (testConfig.test && testConfig.test.length > 0) {
for (let option of testConfig.test) { for (const option of testConfig.test) {
if (!option) { if (!option) {
continue; continue;
} }

View file

@ -25,14 +25,14 @@ abstract class RunnerBase {
let fixedPath = path; let fixedPath = path;
// full paths either start with a drive letter or / for *nix, shouldn't have \ in the path at this point // full paths either start with a drive letter or / for *nix, shouldn't have \ in the path at this point
let fullPath = /(\w+:|\/)?([\w+\-\.]|\/)*\.tsx?/g; const fullPath = /(\w+:|\/)?([\w+\-\.]|\/)*\.tsx?/g;
let fullPathList = fixedPath.match(fullPath); const fullPathList = fixedPath.match(fullPath);
if (fullPathList) { if (fullPathList) {
fullPathList.forEach((match: string) => fixedPath = fixedPath.replace(match, Harness.Path.getFileName(match))); fullPathList.forEach((match: string) => fixedPath = fixedPath.replace(match, Harness.Path.getFileName(match)));
} }
// when running in the browser the 'full path' is the host name, shows up in error baselines // when running in the browser the 'full path' is the host name, shows up in error baselines
let localHost = /http:\/localhost:\d+/g; const localHost = /http:\/localhost:\d+/g;
fixedPath = fixedPath.replace(localHost, ""); fixedPath = fixedPath.replace(localHost, "");
return fixedPath; return fixedPath;
} }

View file

@ -6,9 +6,9 @@
namespace RWC { namespace RWC {
function runWithIOLog(ioLog: IOLog, fn: (oldIO: Harness.IO) => void) { function runWithIOLog(ioLog: IOLog, fn: (oldIO: Harness.IO) => void) {
let oldIO = Harness.IO; const oldIO = Harness.IO;
let wrappedIO = Playback.wrapIO(oldIO); const wrappedIO = Playback.wrapIO(oldIO);
wrappedIO.startReplayFromData(ioLog); wrappedIO.startReplayFromData(ioLog);
Harness.IO = wrappedIO; Harness.IO = wrappedIO;
@ -55,10 +55,10 @@ namespace RWC {
}); });
it("can compile", () => { it("can compile", () => {
let harnessCompiler = Harness.Compiler.getCompiler(); const harnessCompiler = Harness.Compiler.getCompiler();
let opts: ts.ParsedCommandLine; let opts: ts.ParsedCommandLine;
let ioLog: IOLog = JSON.parse(Harness.IO.readFile(jsonPath)); const ioLog: IOLog = JSON.parse(Harness.IO.readFile(jsonPath));
currentDirectory = ioLog.currentDirectory; currentDirectory = ioLog.currentDirectory;
useCustomLibraryFile = ioLog.useCustomLibraryFile; useCustomLibraryFile = ioLog.useCustomLibraryFile;
runWithIOLog(ioLog, () => { runWithIOLog(ioLog, () => {
@ -75,26 +75,26 @@ namespace RWC {
let fileNames = opts.fileNames; let fileNames = opts.fileNames;
let tsconfigFile = ts.forEach(ioLog.filesRead, f => isTsConfigFile(f) ? f : undefined); const tsconfigFile = ts.forEach(ioLog.filesRead, f => isTsConfigFile(f) ? f : undefined);
if (tsconfigFile) { if (tsconfigFile) {
let tsconfigFileContents = getHarnessCompilerInputUnit(tsconfigFile.path); const tsconfigFileContents = getHarnessCompilerInputUnit(tsconfigFile.path);
let parsedTsconfigFileContents = ts.parseConfigFileTextToJson(tsconfigFile.path, tsconfigFileContents.content); const parsedTsconfigFileContents = ts.parseConfigFileTextToJson(tsconfigFile.path, tsconfigFileContents.content);
let configParseResult = ts.parseJsonConfigFileContent(parsedTsconfigFileContents.config, Harness.IO, ts.getDirectoryPath(tsconfigFile.path)); const configParseResult = ts.parseJsonConfigFileContent(parsedTsconfigFileContents.config, Harness.IO, ts.getDirectoryPath(tsconfigFile.path));
fileNames = configParseResult.fileNames; fileNames = configParseResult.fileNames;
opts.options = ts.extend(opts.options, configParseResult.options); opts.options = ts.extend(opts.options, configParseResult.options);
} }
// Load the files // Load the files
for (let fileName of fileNames) { for (const fileName of fileNames) {
inputFiles.push(getHarnessCompilerInputUnit(fileName)); inputFiles.push(getHarnessCompilerInputUnit(fileName));
} }
// Add files to compilation // Add files to compilation
let isInInputList = (resolvedPath: string) => (inputFile: { unitName: string; content: string; }) => inputFile.unitName === resolvedPath; const isInInputList = (resolvedPath: string) => (inputFile: { unitName: string; content: string; }) => inputFile.unitName === resolvedPath;
for (let fileRead of ioLog.filesRead) { for (const fileRead of ioLog.filesRead) {
// Check if the file is already added into the set of input files. // Check if the file is already added into the set of input files.
const resolvedPath = ts.normalizeSlashes(Harness.IO.resolvePath(fileRead.path)); const resolvedPath = ts.normalizeSlashes(Harness.IO.resolvePath(fileRead.path));
let inInputList = ts.forEach(inputFiles, isInInputList(resolvedPath)); const inInputList = ts.forEach(inputFiles, isInInputList(resolvedPath));
if (isTsConfigFile(fileRead)) { if (isTsConfigFile(fileRead)) {
continue; continue;
@ -139,7 +139,7 @@ namespace RWC {
}); });
function getHarnessCompilerInputUnit(fileName: string) { function getHarnessCompilerInputUnit(fileName: string) {
let unitName = ts.normalizeSlashes(Harness.IO.resolvePath(fileName)); const unitName = ts.normalizeSlashes(Harness.IO.resolvePath(fileName));
let content: string = null; let content: string = null;
try { try {
content = Harness.IO.readFile(unitName); content = Harness.IO.readFile(unitName);
@ -201,7 +201,7 @@ namespace RWC {
it("has the expected errors in generated declaration files", () => { it("has the expected errors in generated declaration files", () => {
if (compilerOptions.declaration && !compilerResult.errors.length) { if (compilerOptions.declaration && !compilerResult.errors.length) {
Harness.Baseline.runBaseline("has the expected errors in generated declaration files", baseName + ".dts.errors.txt", () => { Harness.Baseline.runBaseline("has the expected errors in generated declaration files", baseName + ".dts.errors.txt", () => {
let declFileCompilationResult = Harness.Compiler.getCompiler().compileDeclarationFiles(inputFiles, otherFiles, compilerResult, const declFileCompilationResult = Harness.Compiler.getCompiler().compileDeclarationFiles(inputFiles, otherFiles, compilerResult,
/*settingscallback*/ undefined, compilerOptions, currentDirectory); /*settingscallback*/ undefined, compilerOptions, currentDirectory);
if (declFileCompilationResult.declResult.errors.length === 0) { if (declFileCompilationResult.declResult.errors.length === 0) {
return null; return null;
@ -227,7 +227,7 @@ class RWCRunner extends RunnerBase {
*/ */
public initializeTests(): void { public initializeTests(): void {
// Read in and evaluate the test list // Read in and evaluate the test list
let testList = Harness.IO.listFiles(RWCRunner.sourcePath, /.+\.json$/); const testList = Harness.IO.listFiles(RWCRunner.sourcePath, /.+\.json$/);
for (let i = 0; i < testList.length; i++) { for (let i = 0; i < testList.length; i++) {
this.runTest(testList[i]); this.runTest(testList[i]);
} }

View file

@ -92,7 +92,7 @@ namespace Harness.SourceMapRecoder {
} }
// 6 digit number // 6 digit number
let currentByte = base64FormatDecode(); const currentByte = base64FormatDecode();
// If msb is set, we still have more bits to continue // If msb is set, we still have more bits to continue
moreDigits = (currentByte & 32) !== 0; moreDigits = (currentByte & 32) !== 0;
@ -259,7 +259,7 @@ namespace Harness.SourceMapRecoder {
export function recordSourceMapSpan(sourceMapSpan: ts.SourceMapSpan) { export function recordSourceMapSpan(sourceMapSpan: ts.SourceMapSpan) {
// verify the decoded span is same as the new span // verify the decoded span is same as the new span
let decodeResult = SourceMapDecoder.decodeNextEncodedSourceMapSpan(); const decodeResult = SourceMapDecoder.decodeNextEncodedSourceMapSpan();
let decodedErrors: string[]; let decodedErrors: string[];
if (decodeResult.error if (decodeResult.error
|| decodeResult.sourceMapSpan.emittedLine !== sourceMapSpan.emittedLine || decodeResult.sourceMapSpan.emittedLine !== sourceMapSpan.emittedLine
@ -317,8 +317,8 @@ namespace Harness.SourceMapRecoder {
} }
function getTextOfLine(line: number, lineMap: number[], code: string) { function getTextOfLine(line: number, lineMap: number[], code: string) {
let startPos = lineMap[line]; const startPos = lineMap[line];
let endPos = lineMap[line + 1]; const endPos = lineMap[line + 1];
return code.substring(startPos, endPos); return code.substring(startPos, endPos);
} }
@ -329,7 +329,7 @@ namespace Harness.SourceMapRecoder {
} }
function writeRecordedSpans() { function writeRecordedSpans() {
let markerIds: string[] = []; const markerIds: string[] = [];
function getMarkerId(markerIndex: number) { function getMarkerId(markerIndex: number) {
let markerId = ""; let markerId = "";
@ -364,7 +364,7 @@ namespace Harness.SourceMapRecoder {
} }
function writeSourceMapMarker(currentSpan: SourceMapSpanWithDecodeErrors, index: number, endColumn = currentSpan.sourceMapSpan.emittedColumn, endContinues?: boolean) { function writeSourceMapMarker(currentSpan: SourceMapSpanWithDecodeErrors, index: number, endColumn = currentSpan.sourceMapSpan.emittedColumn, endContinues?: boolean) {
let markerId = getMarkerId(index); const markerId = getMarkerId(index);
markerIds.push(markerId); markerIds.push(markerId);
writeSourceMapIndent(prevEmittedCol, markerId); writeSourceMapIndent(prevEmittedCol, markerId);
@ -380,7 +380,7 @@ namespace Harness.SourceMapRecoder {
} }
function writeSourceMapSourceText(currentSpan: SourceMapSpanWithDecodeErrors, index: number) { function writeSourceMapSourceText(currentSpan: SourceMapSpanWithDecodeErrors, index: number) {
let sourcePos = tsLineMap[currentSpan.sourceMapSpan.sourceLine - 1] + (currentSpan.sourceMapSpan.sourceColumn - 1); const sourcePos = tsLineMap[currentSpan.sourceMapSpan.sourceLine - 1] + (currentSpan.sourceMapSpan.sourceColumn - 1);
let sourceText = ""; let sourceText = "";
if (prevWrittenSourcePos < sourcePos) { if (prevWrittenSourcePos < sourcePos) {
// Position that goes forward, get text // Position that goes forward, get text
@ -395,7 +395,7 @@ namespace Harness.SourceMapRecoder {
} }
} }
let tsCodeLineMap = ts.computeLineStarts(sourceText); const tsCodeLineMap = ts.computeLineStarts(sourceText);
for (let i = 0; i < tsCodeLineMap.length; i++) { for (let i = 0; i < tsCodeLineMap.length; i++) {
writeSourceMapIndent(prevEmittedCol, i === 0 ? markerIds[index] : " >"); writeSourceMapIndent(prevEmittedCol, i === 0 ? markerIds[index] : " >");
sourceMapRecoder.Write(getTextOfLine(i, tsCodeLineMap, sourceText)); sourceMapRecoder.Write(getTextOfLine(i, tsCodeLineMap, sourceText));
@ -412,7 +412,7 @@ namespace Harness.SourceMapRecoder {
} }
if (spansOnSingleLine.length) { if (spansOnSingleLine.length) {
let currentJsLine = spansOnSingleLine[0].sourceMapSpan.emittedLine; const currentJsLine = spansOnSingleLine[0].sourceMapSpan.emittedLine;
// Write js line // Write js line
writeJsFileLines(currentJsLine); writeJsFileLines(currentJsLine);
@ -420,7 +420,7 @@ namespace Harness.SourceMapRecoder {
// Emit markers // Emit markers
iterateSpans(writeSourceMapMarker); iterateSpans(writeSourceMapMarker);
let jsFileText = getTextOfLine(currentJsLine, jsLineMap, jsFile.code); const jsFileText = getTextOfLine(currentJsLine, jsLineMap, jsFile.code);
if (prevEmittedCol < jsFileText.length) { if (prevEmittedCol < jsFileText.length) {
// There is remaining text on this line that will be part of next source span so write marker that continues // There is remaining text on this line that will be part of next source span so write marker that continues
writeSourceMapMarker(undefined, spansOnSingleLine.length, /*endColumn*/ jsFileText.length, /*endContinues*/ true); writeSourceMapMarker(undefined, spansOnSingleLine.length, /*endColumn*/ jsFileText.length, /*endContinues*/ true);
@ -438,16 +438,16 @@ namespace Harness.SourceMapRecoder {
} }
export function getSourceMapRecord(sourceMapDataList: ts.SourceMapData[], program: ts.Program, jsFiles: Compiler.GeneratedFile[]) { export function getSourceMapRecord(sourceMapDataList: ts.SourceMapData[], program: ts.Program, jsFiles: Compiler.GeneratedFile[]) {
let sourceMapRecoder = new Compiler.WriterAggregator(); const sourceMapRecoder = new Compiler.WriterAggregator();
for (let i = 0; i < sourceMapDataList.length; i++) { for (let i = 0; i < sourceMapDataList.length; i++) {
let sourceMapData = sourceMapDataList[i]; const sourceMapData = sourceMapDataList[i];
let prevSourceFile: ts.SourceFile; let prevSourceFile: ts.SourceFile;
SourceMapSpanWriter.intializeSourceMapSpanWriter(sourceMapRecoder, sourceMapData, jsFiles[i]); SourceMapSpanWriter.intializeSourceMapSpanWriter(sourceMapRecoder, sourceMapData, jsFiles[i]);
for (let j = 0; j < sourceMapData.sourceMapDecodedMappings.length; j++) { for (let j = 0; j < sourceMapData.sourceMapDecodedMappings.length; j++) {
let decodedSourceMapping = sourceMapData.sourceMapDecodedMappings[j]; const decodedSourceMapping = sourceMapData.sourceMapDecodedMappings[j];
let currentSourceFile = program.getSourceFile(sourceMapData.inputSourceFileNames[decodedSourceMapping.sourceIndex]); const currentSourceFile = program.getSourceFile(sourceMapData.inputSourceFileNames[decodedSourceMapping.sourceIndex]);
if (currentSourceFile !== prevSourceFile) { if (currentSourceFile !== prevSourceFile) {
SourceMapSpanWriter.recordNewSourceFileSpan(decodedSourceMapping, currentSourceFile.text); SourceMapSpanWriter.recordNewSourceFileSpan(decodedSourceMapping, currentSourceFile.text);
prevSourceFile = currentSourceFile; prevSourceFile = currentSourceFile;

View file

@ -36,11 +36,11 @@ class Test262BaselineRunner extends RunnerBase {
}; };
before(() => { before(() => {
let content = Harness.IO.readFile(filePath); const content = Harness.IO.readFile(filePath);
let testFilename = ts.removeFileExtension(filePath).replace(/\//g, "_") + ".test"; const testFilename = ts.removeFileExtension(filePath).replace(/\//g, "_") + ".test";
let testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, testFilename); const testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, testFilename);
let inputFiles = testCaseContent.testUnitData.map(unit => { const inputFiles = testCaseContent.testUnitData.map(unit => {
return { unitName: Test262BaselineRunner.getTestFilePath(unit.name), content: unit.content }; return { unitName: Test262BaselineRunner.getTestFilePath(unit.name), content: unit.content };
}); });
@ -64,14 +64,14 @@ class Test262BaselineRunner extends RunnerBase {
it("has the expected emitted code", () => { it("has the expected emitted code", () => {
Harness.Baseline.runBaseline("has the expected emitted code", testState.filename + ".output.js", () => { Harness.Baseline.runBaseline("has the expected emitted code", testState.filename + ".output.js", () => {
let files = testState.compilerResult.files.filter(f => f.fileName !== Test262BaselineRunner.helpersFilePath); const files = testState.compilerResult.files.filter(f => f.fileName !== Test262BaselineRunner.helpersFilePath);
return Harness.Compiler.collateOutputs(files); return Harness.Compiler.collateOutputs(files);
}, false, Test262BaselineRunner.baselineOptions); }, false, Test262BaselineRunner.baselineOptions);
}); });
it("has the expected errors", () => { it("has the expected errors", () => {
Harness.Baseline.runBaseline("has the expected errors", testState.filename + ".errors.txt", () => { Harness.Baseline.runBaseline("has the expected errors", testState.filename + ".errors.txt", () => {
let errors = testState.compilerResult.errors; const errors = testState.compilerResult.errors;
if (errors.length === 0) { if (errors.length === 0) {
return null; return null;
} }
@ -81,13 +81,13 @@ class Test262BaselineRunner extends RunnerBase {
}); });
it("satisfies inletiants", () => { it("satisfies inletiants", () => {
let sourceFile = testState.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); const sourceFile = testState.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename));
Utils.assertInvariants(sourceFile, /*parent:*/ undefined); Utils.assertInvariants(sourceFile, /*parent:*/ undefined);
}); });
it("has the expected AST", () => { it("has the expected AST", () => {
Harness.Baseline.runBaseline("has the expected AST", testState.filename + ".AST.txt", () => { Harness.Baseline.runBaseline("has the expected AST", testState.filename + ".AST.txt", () => {
let sourceFile = testState.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); const sourceFile = testState.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename));
return Utils.sourceFileToJSON(sourceFile); return Utils.sourceFileToJSON(sourceFile);
}, false, Test262BaselineRunner.baselineOptions); }, false, Test262BaselineRunner.baselineOptions);
}); });
@ -97,7 +97,7 @@ class Test262BaselineRunner extends RunnerBase {
public initializeTests() { public initializeTests() {
// this will set up a series of describe/it blocks to run between the setup and cleanup phases // this will set up a series of describe/it blocks to run between the setup and cleanup phases
if (this.tests.length === 0) { if (this.tests.length === 0) {
let testFiles = this.enumerateFiles(Test262BaselineRunner.basePath, Test262BaselineRunner.testFileExtensionRegex, { recursive: true }); const testFiles = this.enumerateFiles(Test262BaselineRunner.basePath, Test262BaselineRunner.testFileExtensionRegex, { recursive: true });
testFiles.forEach(fn => { testFiles.forEach(fn => {
this.runTest(ts.normalizePath(fn)); this.runTest(ts.normalizePath(fn));
}); });

View file

@ -21,7 +21,7 @@ class TypeWriterWalker {
} }
public getTypeAndSymbols(fileName: string): TypeWriterResult[] { public getTypeAndSymbols(fileName: string): TypeWriterResult[] {
let sourceFile = this.program.getSourceFile(fileName); const sourceFile = this.program.getSourceFile(fileName);
this.currentSourceFile = sourceFile; this.currentSourceFile = sourceFile;
this.results = []; this.results = [];
this.visitNode(sourceFile); this.visitNode(sourceFile);
@ -37,28 +37,28 @@ class TypeWriterWalker {
} }
private logTypeAndSymbol(node: ts.Node): void { private logTypeAndSymbol(node: ts.Node): void {
let actualPos = ts.skipTrivia(this.currentSourceFile.text, node.pos); const actualPos = ts.skipTrivia(this.currentSourceFile.text, node.pos);
let lineAndCharacter = this.currentSourceFile.getLineAndCharacterOfPosition(actualPos); const lineAndCharacter = this.currentSourceFile.getLineAndCharacterOfPosition(actualPos);
let sourceText = ts.getTextOfNodeFromSourceText(this.currentSourceFile.text, node); const sourceText = ts.getTextOfNodeFromSourceText(this.currentSourceFile.text, node);
// Workaround to ensure we output 'C' instead of 'typeof C' for base class expressions // Workaround to ensure we output 'C' instead of 'typeof C' for base class expressions
// let type = this.checker.getTypeAtLocation(node); // let type = this.checker.getTypeAtLocation(node);
let type = node.parent && ts.isExpressionWithTypeArgumentsInClassExtendsClause(node.parent) && this.checker.getTypeAtLocation(node.parent) || this.checker.getTypeAtLocation(node); const type = node.parent && ts.isExpressionWithTypeArgumentsInClassExtendsClause(node.parent) && this.checker.getTypeAtLocation(node.parent) || this.checker.getTypeAtLocation(node);
ts.Debug.assert(type !== undefined, "type doesn't exist"); ts.Debug.assert(type !== undefined, "type doesn't exist");
let symbol = this.checker.getSymbolAtLocation(node); const symbol = this.checker.getSymbolAtLocation(node);
let typeString = this.checker.typeToString(type, node.parent, ts.TypeFormatFlags.NoTruncation); const typeString = this.checker.typeToString(type, node.parent, ts.TypeFormatFlags.NoTruncation);
let symbolString: string; let symbolString: string;
if (symbol) { if (symbol) {
symbolString = "Symbol(" + this.checker.symbolToString(symbol, node.parent); symbolString = "Symbol(" + this.checker.symbolToString(symbol, node.parent);
if (symbol.declarations) { if (symbol.declarations) {
for (let declaration of symbol.declarations) { for (const declaration of symbol.declarations) {
symbolString += ", "; symbolString += ", ";
let declSourceFile = declaration.getSourceFile(); const declSourceFile = declaration.getSourceFile();
let declLineAndCharacter = declSourceFile.getLineAndCharacterOfPosition(declaration.pos); const declLineAndCharacter = declSourceFile.getLineAndCharacterOfPosition(declaration.pos);
let fileName = ts.getBaseFileName(declSourceFile.fileName); const fileName = ts.getBaseFileName(declSourceFile.fileName);
let isLibFile = /lib(.*)\.d\.ts/i.test(fileName); const isLibFile = /lib(.*)\.d\.ts/i.test(fileName);
symbolString += `Decl(${ fileName }, ${ isLibFile ? "--" : declLineAndCharacter.line }, ${ isLibFile ? "--" : declLineAndCharacter.character })`; symbolString += `Decl(${ fileName }, ${ isLibFile ? "--" : declLineAndCharacter.line }, ${ isLibFile ? "--" : declLineAndCharacter.character })`;
} }
} }

8
src/lib/README.md Normal file
View file

@ -0,0 +1,8 @@
# Read this!
The files within this directory are used to generate `lib.d.ts` and `lib.es6.d.ts`.
## Generated files
Any files ending in `.generated.d.ts` aren't mean to be edited by hand.
If you need to make changes to such files, make a change to the input files for our [library generator](https://github.com/Microsoft/TSJS-lib-generator).

View file

@ -105,19 +105,19 @@ namespace ts.server {
} }
resolveModuleNames(moduleNames: string[], containingFile: string): ResolvedModule[] { resolveModuleNames(moduleNames: string[], containingFile: string): ResolvedModule[] {
let path = toPath(containingFile, this.host.getCurrentDirectory(), this.getCanonicalFileName); const path = toPath(containingFile, this.host.getCurrentDirectory(), this.getCanonicalFileName);
let currentResolutionsInFile = this.resolvedModuleNames.get(path); const currentResolutionsInFile = this.resolvedModuleNames.get(path);
let newResolutions: Map<TimestampedResolvedModule> = {}; const newResolutions: Map<TimestampedResolvedModule> = {};
let resolvedModules: ResolvedModule[] = []; const resolvedModules: ResolvedModule[] = [];
let compilerOptions = this.getCompilationSettings(); const compilerOptions = this.getCompilationSettings();
for (let moduleName of moduleNames) { for (const moduleName of moduleNames) {
// check if this is a duplicate entry in the list // check if this is a duplicate entry in the list
let resolution = lookUp(newResolutions, moduleName); let resolution = lookUp(newResolutions, moduleName);
if (!resolution) { if (!resolution) {
let existingResolution = currentResolutionsInFile && ts.lookUp(currentResolutionsInFile, moduleName); const existingResolution = currentResolutionsInFile && ts.lookUp(currentResolutionsInFile, moduleName);
if (moduleResolutionIsValid(existingResolution)) { if (moduleResolutionIsValid(existingResolution)) {
// ok, it is safe to use existing module resolution results // ok, it is safe to use existing module resolution results
resolution = existingResolution; resolution = existingResolution;
@ -211,7 +211,7 @@ namespace ts.server {
} }
getScriptInfo(filename: string): ScriptInfo { getScriptInfo(filename: string): ScriptInfo {
let path = toPath(filename, this.host.getCurrentDirectory(), this.getCanonicalFileName); const path = toPath(filename, this.host.getCurrentDirectory(), this.getCanonicalFileName);
let scriptInfo = this.filenameToScript.get(path); let scriptInfo = this.filenameToScript.get(path);
if (!scriptInfo) { if (!scriptInfo) {
scriptInfo = this.project.openReferencedFile(filename); scriptInfo = this.project.openReferencedFile(filename);
@ -282,7 +282,7 @@ namespace ts.server {
* @param line 1 based index * @param line 1 based index
*/ */
lineToTextSpan(filename: string, line: number): ts.TextSpan { lineToTextSpan(filename: string, line: number): ts.TextSpan {
let path = toPath(filename, this.host.getCurrentDirectory(), this.getCanonicalFileName); const path = toPath(filename, this.host.getCurrentDirectory(), this.getCanonicalFileName);
const script: ScriptInfo = this.filenameToScript.get(path); const script: ScriptInfo = this.filenameToScript.get(path);
const index = script.snap().index; const index = script.snap().index;
@ -303,7 +303,7 @@ namespace ts.server {
* @param offset 1 based index * @param offset 1 based index
*/ */
lineOffsetToPosition(filename: string, line: number, offset: number): number { lineOffsetToPosition(filename: string, line: number, offset: number): number {
let path = toPath(filename, this.host.getCurrentDirectory(), this.getCanonicalFileName); const path = toPath(filename, this.host.getCurrentDirectory(), this.getCanonicalFileName);
const script: ScriptInfo = this.filenameToScript.get(path); const script: ScriptInfo = this.filenameToScript.get(path);
const index = script.snap().index; const index = script.snap().index;
@ -317,7 +317,7 @@ namespace ts.server {
* @param offset 1-based index * @param offset 1-based index
*/ */
positionToLineOffset(filename: string, position: number): ILineInfo { positionToLineOffset(filename: string, position: number): ILineInfo {
let path = toPath(filename, this.host.getCurrentDirectory(), this.getCanonicalFileName); const path = toPath(filename, this.host.getCurrentDirectory(), this.getCanonicalFileName);
const script: ScriptInfo = this.filenameToScript.get(path); const script: ScriptInfo = this.filenameToScript.get(path);
const index = script.snap().index; const index = script.snap().index;
const lineOffset = index.charOffsetToLineNumberAndPos(position); const lineOffset = index.charOffsetToLineNumberAndPos(position);
@ -578,9 +578,9 @@ namespace ts.server {
} }
handleProjectFilelistChanges(project: Project) { handleProjectFilelistChanges(project: Project) {
let { succeeded, projectOptions, error } = this.configFileToProjectOptions(project.projectFilename); const { succeeded, projectOptions, error } = this.configFileToProjectOptions(project.projectFilename);
let newRootFiles = projectOptions.files.map((f => this.getCanonicalFileName(f))); const newRootFiles = projectOptions.files.map((f => this.getCanonicalFileName(f)));
let currentRootFiles = project.getRootFiles().map((f => this.getCanonicalFileName(f))); const currentRootFiles = project.getRootFiles().map((f => this.getCanonicalFileName(f)));
// We check if the project file list has changed. If so, we update the project. // We check if the project file list has changed. If so, we update the project.
if (!arrayIsEqualTo(currentRootFiles && currentRootFiles.sort(), newRootFiles && newRootFiles.sort())) { if (!arrayIsEqualTo(currentRootFiles && currentRootFiles.sort(), newRootFiles && newRootFiles.sort())) {
@ -606,13 +606,13 @@ namespace ts.server {
this.log("Detected newly added tsconfig file: " + fileName); this.log("Detected newly added tsconfig file: " + fileName);
let { succeeded, projectOptions, error } = this.configFileToProjectOptions(fileName); const { succeeded, projectOptions, error } = this.configFileToProjectOptions(fileName);
let rootFilesInTsconfig = projectOptions.files.map(f => this.getCanonicalFileName(f)); const rootFilesInTsconfig = projectOptions.files.map(f => this.getCanonicalFileName(f));
let openFileRoots = this.openFileRoots.map(s => this.getCanonicalFileName(s.fileName)); const openFileRoots = this.openFileRoots.map(s => this.getCanonicalFileName(s.fileName));
// We should only care about the new tsconfig file if it contains any // We should only care about the new tsconfig file if it contains any
// opened root files of existing inferred projects // opened root files of existing inferred projects
for (let openFileRoot of openFileRoots) { for (const openFileRoot of openFileRoots) {
if (rootFilesInTsconfig.indexOf(openFileRoot) >= 0) { if (rootFilesInTsconfig.indexOf(openFileRoot) >= 0) {
this.reloadProjects(); this.reloadProjects();
return; return;
@ -621,7 +621,7 @@ namespace ts.server {
} }
getCanonicalFileName(fileName: string) { getCanonicalFileName(fileName: string) {
let name = this.host.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); const name = this.host.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
return ts.normalizePath(name); return ts.normalizePath(name);
} }
@ -737,7 +737,7 @@ namespace ts.server {
this.configuredProjects = copyListRemovingItem(project, this.configuredProjects); this.configuredProjects = copyListRemovingItem(project, this.configuredProjects);
} }
else { else {
for (let directory of project.directoriesWatchedForTsconfig) { for (const directory of project.directoriesWatchedForTsconfig) {
// if the ref count for this directory watcher drops to 0, it's time to close it // if the ref count for this directory watcher drops to 0, it's time to close it
if (!(--project.projectService.directoryWatchersRefCount[directory])) { if (!(--project.projectService.directoryWatchersRefCount[directory])) {
this.log("Close directory watcher for: " + directory); this.log("Close directory watcher for: " + directory);
@ -748,9 +748,9 @@ namespace ts.server {
this.inferredProjects = copyListRemovingItem(project, this.inferredProjects); this.inferredProjects = copyListRemovingItem(project, this.inferredProjects);
} }
let fileNames = project.getFileNames(); const fileNames = project.getFileNames();
for (let fileName of fileNames) { for (const fileName of fileNames) {
let info = this.getScriptInfo(fileName); const info = this.getScriptInfo(fileName);
if (info.defaultProject == project) { if (info.defaultProject == project) {
info.defaultProject = undefined; info.defaultProject = undefined;
} }
@ -759,7 +759,7 @@ namespace ts.server {
setConfiguredProjectRoot(info: ScriptInfo) { setConfiguredProjectRoot(info: ScriptInfo) {
for (let i = 0, len = this.configuredProjects.length; i < len; i++) { for (let i = 0, len = this.configuredProjects.length; i < len; i++) {
let configuredProject = this.configuredProjects[i]; const configuredProject = this.configuredProjects[i];
if (configuredProject.isRoot(info)) { if (configuredProject.isRoot(info)) {
info.defaultProject = configuredProject; info.defaultProject = configuredProject;
configuredProject.addOpenRef(); configuredProject.addOpenRef();
@ -903,7 +903,7 @@ namespace ts.server {
reloadProjects() { reloadProjects() {
this.log("reload projects."); this.log("reload projects.");
// First check if there is new tsconfig file added for inferred project roots // First check if there is new tsconfig file added for inferred project roots
for (let info of this.openFileRoots) { for (const info of this.openFileRoots) {
this.openOrUpdateConfiguredProjectForFile(info.fileName); this.openOrUpdateConfiguredProjectForFile(info.fileName);
} }
this.updateProjectStructure(); this.updateProjectStructure();
@ -918,10 +918,10 @@ namespace ts.server {
this.log("updating project structure from ...", "Info"); this.log("updating project structure from ...", "Info");
this.printProjects(); this.printProjects();
let unattachedOpenFiles: ScriptInfo[] = []; const unattachedOpenFiles: ScriptInfo[] = [];
let openFileRootsConfigured: ScriptInfo[] = []; const openFileRootsConfigured: ScriptInfo[] = [];
for (let info of this.openFileRootsConfigured) { for (const info of this.openFileRootsConfigured) {
let project = info.defaultProject; const project = info.defaultProject;
if (!project || !(project.getSourceFile(info))) { if (!project || !(project.getSourceFile(info))) {
info.defaultProject = undefined; info.defaultProject = undefined;
unattachedOpenFiles.push(info); unattachedOpenFiles.push(info);
@ -1016,7 +1016,6 @@ namespace ts.server {
} }
} }
if (content !== undefined) { if (content !== undefined) {
let indentSize: number;
info = new ScriptInfo(this.host, fileName, content, openedByClient); info = new ScriptInfo(this.host, fileName, content, openedByClient);
info.setFormatOptions(this.getFormatCodeOptions()); info.setFormatOptions(this.getFormatCodeOptions());
this.filenameToScriptInfo[fileName] = info; this.filenameToScriptInfo[fileName] = info;
@ -1071,12 +1070,12 @@ namespace ts.server {
* the tsconfig file content and update the project; otherwise we create a new one. * the tsconfig file content and update the project; otherwise we create a new one.
*/ */
openOrUpdateConfiguredProjectForFile(fileName: string) { openOrUpdateConfiguredProjectForFile(fileName: string) {
let searchPath = ts.normalizePath(getDirectoryPath(fileName)); const searchPath = ts.normalizePath(getDirectoryPath(fileName));
this.log("Search path: " + searchPath, "Info"); this.log("Search path: " + searchPath, "Info");
let configFileName = this.findConfigFile(searchPath); const configFileName = this.findConfigFile(searchPath);
if (configFileName) { if (configFileName) {
this.log("Config file name: " + configFileName, "Info"); this.log("Config file name: " + configFileName, "Info");
let project = this.findConfiguredProjectByConfigFile(configFileName); const project = this.findConfiguredProjectByConfigFile(configFileName);
if (!project) { if (!project) {
const configResult = this.openConfigFile(configFileName, fileName); const configResult = this.openConfigFile(configFileName, fileName);
if (!configResult.success) { if (!configResult.success) {
@ -1215,15 +1214,15 @@ namespace ts.server {
} }
openConfigFile(configFilename: string, clientFileName?: string): ProjectOpenResult { openConfigFile(configFilename: string, clientFileName?: string): ProjectOpenResult {
let { succeeded, projectOptions, error } = this.configFileToProjectOptions(configFilename); const { succeeded, projectOptions, error } = this.configFileToProjectOptions(configFilename);
if (!succeeded) { if (!succeeded) {
return error; return error;
} }
else { else {
let project = this.createProject(configFilename, projectOptions); const project = this.createProject(configFilename, projectOptions);
for (let rootFilename of projectOptions.files) { for (const rootFilename of projectOptions.files) {
if (this.host.fileExists(rootFilename)) { if (this.host.fileExists(rootFilename)) {
let info = this.openFile(rootFilename, /*openedByClient*/ clientFileName == rootFilename); const info = this.openFile(rootFilename, /*openedByClient*/ clientFileName == rootFilename);
project.addRoot(info); project.addRoot(info);
} }
else { else {
@ -1248,24 +1247,24 @@ namespace ts.server {
this.removeProject(project); this.removeProject(project);
} }
else { else {
let { succeeded, projectOptions, error } = this.configFileToProjectOptions(project.projectFilename); const { succeeded, projectOptions, error } = this.configFileToProjectOptions(project.projectFilename);
if (!succeeded) { if (!succeeded) {
return error; return error;
} }
else { else {
let oldFileNames = project.compilerService.host.roots.map(info => info.fileName); const oldFileNames = project.compilerService.host.roots.map(info => info.fileName);
let newFileNames = projectOptions.files; const newFileNames = projectOptions.files;
let fileNamesToRemove = oldFileNames.filter(f => newFileNames.indexOf(f) < 0); const fileNamesToRemove = oldFileNames.filter(f => newFileNames.indexOf(f) < 0);
let fileNamesToAdd = newFileNames.filter(f => oldFileNames.indexOf(f) < 0); const fileNamesToAdd = newFileNames.filter(f => oldFileNames.indexOf(f) < 0);
for (let fileName of fileNamesToRemove) { for (const fileName of fileNamesToRemove) {
let info = this.getScriptInfo(fileName); const info = this.getScriptInfo(fileName);
if (info) { if (info) {
project.removeRoot(info); project.removeRoot(info);
} }
} }
for (let fileName of fileNamesToAdd) { for (const fileName of fileNamesToAdd) {
let info = this.getScriptInfo(fileName); let info = this.getScriptInfo(fileName);
if (!info) { if (!info) {
info = this.openFile(fileName, false); info = this.openFile(fileName, false);

View file

@ -157,7 +157,7 @@ namespace ts.server {
const logger = createLoggerFromEnv(); const logger = createLoggerFromEnv();
let pending: string[] = []; const pending: string[] = [];
let canWrite = true; let canWrite = true;
function writeMessage(s: string) { function writeMessage(s: string) {
if (!canWrite) { if (!canWrite) {

View file

@ -338,25 +338,25 @@ namespace ts.server {
private getOccurrences(line: number, offset: number, fileName: string): protocol.OccurrencesResponseItem[] { private getOccurrences(line: number, offset: number, fileName: string): protocol.OccurrencesResponseItem[] {
fileName = ts.normalizePath(fileName); fileName = ts.normalizePath(fileName);
let project = this.projectService.getProjectForFile(fileName); const project = this.projectService.getProjectForFile(fileName);
if (!project) { if (!project) {
throw Errors.NoProject; throw Errors.NoProject;
} }
let { compilerService } = project; const { compilerService } = project;
let position = compilerService.host.lineOffsetToPosition(fileName, line, offset); const position = compilerService.host.lineOffsetToPosition(fileName, line, offset);
let occurrences = compilerService.languageService.getOccurrencesAtPosition(fileName, position); const occurrences = compilerService.languageService.getOccurrencesAtPosition(fileName, position);
if (!occurrences) { if (!occurrences) {
return undefined; return undefined;
} }
return occurrences.map(occurrence => { return occurrences.map(occurrence => {
let { fileName, isWriteAccess, textSpan } = occurrence; const { fileName, isWriteAccess, textSpan } = occurrence;
let start = compilerService.host.positionToLineOffset(fileName, textSpan.start); const start = compilerService.host.positionToLineOffset(fileName, textSpan.start);
let end = compilerService.host.positionToLineOffset(fileName, ts.textSpanEnd(textSpan)); const end = compilerService.host.positionToLineOffset(fileName, ts.textSpanEnd(textSpan));
return { return {
start, start,
end, end,
@ -368,16 +368,16 @@ namespace ts.server {
private getDocumentHighlights(line: number, offset: number, fileName: string, filesToSearch: string[]): protocol.DocumentHighlightsItem[] { private getDocumentHighlights(line: number, offset: number, fileName: string, filesToSearch: string[]): protocol.DocumentHighlightsItem[] {
fileName = ts.normalizePath(fileName); fileName = ts.normalizePath(fileName);
let project = this.projectService.getProjectForFile(fileName); const project = this.projectService.getProjectForFile(fileName);
if (!project) { if (!project) {
throw Errors.NoProject; throw Errors.NoProject;
} }
let { compilerService } = project; const { compilerService } = project;
let position = compilerService.host.lineOffsetToPosition(fileName, line, offset); const position = compilerService.host.lineOffsetToPosition(fileName, line, offset);
let documentHighlights = compilerService.languageService.getDocumentHighlights(fileName, position, filesToSearch); const documentHighlights = compilerService.languageService.getDocumentHighlights(fileName, position, filesToSearch);
if (!documentHighlights) { if (!documentHighlights) {
return undefined; return undefined;
@ -386,7 +386,7 @@ namespace ts.server {
return documentHighlights.map(convertToDocumentHighlightsItem); return documentHighlights.map(convertToDocumentHighlightsItem);
function convertToDocumentHighlightsItem(documentHighlights: ts.DocumentHighlights): ts.server.protocol.DocumentHighlightsItem { function convertToDocumentHighlightsItem(documentHighlights: ts.DocumentHighlights): ts.server.protocol.DocumentHighlightsItem {
let { fileName, highlightSpans } = documentHighlights; const { fileName, highlightSpans } = documentHighlights;
return { return {
file: fileName, file: fileName,
@ -394,9 +394,9 @@ namespace ts.server {
}; };
function convertHighlightSpan(highlightSpan: ts.HighlightSpan): ts.server.protocol.HighlightSpan { function convertHighlightSpan(highlightSpan: ts.HighlightSpan): ts.server.protocol.HighlightSpan {
let { textSpan, kind } = highlightSpan; const { textSpan, kind } = highlightSpan;
let start = compilerService.host.positionToLineOffset(fileName, textSpan.start); const start = compilerService.host.positionToLineOffset(fileName, textSpan.start);
let end = compilerService.host.positionToLineOffset(fileName, ts.textSpanEnd(textSpan)); const end = compilerService.host.positionToLineOffset(fileName, ts.textSpanEnd(textSpan));
return { start, end, kind }; return { start, end, kind };
} }
} }
@ -404,9 +404,9 @@ namespace ts.server {
private getProjectInfo(fileName: string, needFileNameList: boolean): protocol.ProjectInfo { private getProjectInfo(fileName: string, needFileNameList: boolean): protocol.ProjectInfo {
fileName = ts.normalizePath(fileName); fileName = ts.normalizePath(fileName);
let project = this.projectService.getProjectForFile(fileName); const project = this.projectService.getProjectForFile(fileName);
let projectInfo: protocol.ProjectInfo = { const projectInfo: protocol.ProjectInfo = {
configFileName: project.projectFilename configFileName: project.projectFilename
}; };
@ -640,7 +640,7 @@ namespace ts.server {
} }
// i points to the first non whitespace character // i points to the first non whitespace character
if (preferredIndent !== hasIndent) { if (preferredIndent !== hasIndent) {
let firstNoWhiteSpacePosition = lineInfo.offset + i; const firstNoWhiteSpacePosition = lineInfo.offset + i;
edits.push({ edits.push({
span: ts.createTextSpanFromBounds(lineInfo.offset, firstNoWhiteSpacePosition), span: ts.createTextSpanFromBounds(lineInfo.offset, firstNoWhiteSpacePosition),
newText: generateIndentString(preferredIndent, editorOptions) newText: generateIndentString(preferredIndent, editorOptions)
@ -897,22 +897,22 @@ namespace ts.server {
} }
getDiagnosticsForProject(delay: number, fileName: string) { getDiagnosticsForProject(delay: number, fileName: string) {
let { configFileName, fileNames: fileNamesInProject } = this.getProjectInfo(fileName, true); const { configFileName, fileNames } = this.getProjectInfo(fileName, true);
// No need to analyze lib.d.ts // No need to analyze lib.d.ts
fileNamesInProject = fileNamesInProject.filter((value, index, array) => value.indexOf("lib.d.ts") < 0); let fileNamesInProject = fileNames.filter((value, index, array) => value.indexOf("lib.d.ts") < 0);
// Sort the file name list to make the recently touched files come first // Sort the file name list to make the recently touched files come first
let highPriorityFiles: string[] = []; const highPriorityFiles: string[] = [];
let mediumPriorityFiles: string[] = []; const mediumPriorityFiles: string[] = [];
let lowPriorityFiles: string[] = []; const lowPriorityFiles: string[] = [];
let veryLowPriorityFiles: string[] = []; const veryLowPriorityFiles: string[] = [];
let normalizedFileName = ts.normalizePath(fileName); const normalizedFileName = ts.normalizePath(fileName);
let project = this.projectService.getProjectForFile(normalizedFileName); const project = this.projectService.getProjectForFile(normalizedFileName);
for (let fileNameInProject of fileNamesInProject) { for (const fileNameInProject of fileNamesInProject) {
if (this.getCanonicalFileName(fileNameInProject) == this.getCanonicalFileName(fileName)) if (this.getCanonicalFileName(fileNameInProject) == this.getCanonicalFileName(fileName))
highPriorityFiles.push(fileNameInProject); highPriorityFiles.push(fileNameInProject);
else { else {
let info = this.projectService.getScriptInfo(fileNameInProject); const info = this.projectService.getScriptInfo(fileNameInProject);
if (!info.isOpen) { if (!info.isOpen) {
if (fileNameInProject.indexOf(".d.ts") > 0) if (fileNameInProject.indexOf(".d.ts") > 0)
veryLowPriorityFiles.push(fileNameInProject); veryLowPriorityFiles.push(fileNameInProject);
@ -927,8 +927,8 @@ namespace ts.server {
fileNamesInProject = highPriorityFiles.concat(mediumPriorityFiles).concat(lowPriorityFiles).concat(veryLowPriorityFiles); fileNamesInProject = highPriorityFiles.concat(mediumPriorityFiles).concat(lowPriorityFiles).concat(veryLowPriorityFiles);
if (fileNamesInProject.length > 0) { if (fileNamesInProject.length > 0) {
let checkList = fileNamesInProject.map<PendingErrorCheck>((fileName: string) => { const checkList = fileNamesInProject.map<PendingErrorCheck>((fileName: string) => {
let normalizedFileName = ts.normalizePath(fileName); const normalizedFileName = ts.normalizePath(fileName);
return { fileName: normalizedFileName, project }; return { fileName: normalizedFileName, project };
}); });
// Project level error analysis runs on background files too, therefore // Project level error analysis runs on background files too, therefore
@ -938,7 +938,7 @@ namespace ts.server {
} }
getCanonicalFileName(fileName: string) { getCanonicalFileName(fileName: string) {
let name = this.host.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); const name = this.host.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
return ts.normalizePath(name); return ts.normalizePath(name);
} }
@ -1001,7 +1001,7 @@ namespace ts.server {
return {response: this.getDiagnostics(geterrArgs.delay, geterrArgs.files), responseRequired: false}; return {response: this.getDiagnostics(geterrArgs.delay, geterrArgs.files), responseRequired: false};
}, },
[CommandNames.GeterrForProject]: (request: protocol.Request) => { [CommandNames.GeterrForProject]: (request: protocol.Request) => {
let { file, delay } = <protocol.GeterrForProjectRequestArgs>request.arguments; const { file, delay } = <protocol.GeterrForProjectRequestArgs>request.arguments;
return {response: this.getDiagnosticsForProject(delay, file), responseRequired: false}; return {response: this.getDiagnosticsForProject(delay, file), responseRequired: false};
}, },
[CommandNames.Change]: (request: protocol.Request) => { [CommandNames.Change]: (request: protocol.Request) => {

View file

@ -174,7 +174,7 @@ namespace ts {
let jsDocCompletionEntries: CompletionEntry[]; let jsDocCompletionEntries: CompletionEntry[];
function createNode(kind: SyntaxKind, pos: number, end: number, flags: NodeFlags, parent?: Node): NodeObject { function createNode(kind: SyntaxKind, pos: number, end: number, flags: NodeFlags, parent?: Node): NodeObject {
let node = <NodeObject> new (getNodeConstructor(kind))(pos, end); let node = new NodeObject(kind, pos, end);
node.flags = flags; node.flags = flags;
node.parent = parent; node.parent = parent;
return node; return node;
@ -188,6 +188,14 @@ namespace ts {
public parent: Node; public parent: Node;
private _children: Node[]; private _children: Node[];
constructor(kind: SyntaxKind, pos: number, end: number) {
this.kind = kind;
this.pos = pos;
this.end = end;
this.flags = NodeFlags.None;
this.parent = undefined;
}
public getSourceFile(): SourceFile { public getSourceFile(): SourceFile {
return getSourceFileOfNode(this); return getSourceFileOfNode(this);
} }
@ -805,6 +813,10 @@ namespace ts {
public imports: LiteralExpression[]; public imports: LiteralExpression[];
private namedDeclarations: Map<Declaration[]>; private namedDeclarations: Map<Declaration[]>;
constructor(kind: SyntaxKind, pos: number, end: number) {
super(kind, pos, end)
}
public update(newText: string, textChangeRange: TextChangeRange): SourceFile { public update(newText: string, textChangeRange: TextChangeRange): SourceFile {
return updateSourceFile(this, newText, textChangeRange); return updateSourceFile(this, newText, textChangeRange);
} }
@ -7970,18 +7982,8 @@ namespace ts {
function initializeServices() { function initializeServices() {
objectAllocator = { objectAllocator = {
getNodeConstructor: kind => { getNodeConstructor: () => NodeObject,
function Node(pos: number, end: number) { getSourceFileConstructor: () => SourceFileObject,
this.pos = pos;
this.end = end;
this.flags = NodeFlags.None;
this.parent = undefined;
}
let proto = kind === SyntaxKind.SourceFile ? new SourceFileObject() : new NodeObject();
proto.kind = kind;
Node.prototype = proto;
return <any>Node;
},
getSymbolConstructor: () => SymbolObject, getSymbolConstructor: () => SymbolObject,
getTypeConstructor: () => TypeObject, getTypeConstructor: () => TypeObject,
getSignatureConstructor: () => SignatureObject, getSignatureConstructor: () => SignatureObject,

View file

@ -1032,7 +1032,7 @@ namespace ts {
public createLanguageServiceShim(host: LanguageServiceShimHost): LanguageServiceShim { public createLanguageServiceShim(host: LanguageServiceShimHost): LanguageServiceShim {
try { try {
if (this.documentRegistry === undefined) { if (this.documentRegistry === undefined) {
this.documentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); this.documentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory());
} }
var hostAdapter = new LanguageServiceShimHostAdapter(host); var hostAdapter = new LanguageServiceShimHostAdapter(host);
var languageService = createLanguageService(hostAdapter, this.documentRegistry); var languageService = createLanguageService(hostAdapter, this.documentRegistry);
@ -1068,7 +1068,7 @@ namespace ts {
public close(): void { public close(): void {
// Forget all the registered shims // Forget all the registered shims
this._shims = []; this._shims = [];
this.documentRegistry = createDocumentRegistry(); this.documentRegistry = undefined;
} }
public registerShim(shim: Shim): void { public registerShim(shim: Shim): void {

View file

@ -4,6 +4,7 @@ tests/cases/compiler/fuzzy.ts(21,20): error TS2322: Type '{ anything: number; on
Types of property 'oneI' are incompatible. Types of property 'oneI' are incompatible.
Type 'this' is not assignable to type 'I'. Type 'this' is not assignable to type 'I'.
Type 'C' is not assignable to type 'I'. Type 'C' is not assignable to type 'I'.
Property 'alsoWorks' is missing in type 'C'.
tests/cases/compiler/fuzzy.ts(25,20): error TS2352: Neither type '{ oneI: this; }' nor type 'R' is assignable to the other. tests/cases/compiler/fuzzy.ts(25,20): error TS2352: Neither type '{ oneI: this; }' nor type 'R' is assignable to the other.
Property 'anything' is missing in type '{ oneI: this; }'. Property 'anything' is missing in type '{ oneI: this; }'.
@ -38,6 +39,7 @@ tests/cases/compiler/fuzzy.ts(25,20): error TS2352: Neither type '{ oneI: this;
!!! error TS2322: Types of property 'oneI' are incompatible. !!! error TS2322: Types of property 'oneI' are incompatible.
!!! error TS2322: Type 'this' is not assignable to type 'I'. !!! error TS2322: Type 'this' is not assignable to type 'I'.
!!! error TS2322: Type 'C' is not assignable to type 'I'. !!! error TS2322: Type 'C' is not assignable to type 'I'.
!!! error TS2322: Property 'alsoWorks' is missing in type 'C'.
} }
worksToo():R { worksToo():R {

View file

@ -63,7 +63,7 @@ if (elementA instanceof FileMatch && elementB instanceof FileMatch) {
} else if (elementA instanceof Match && elementB instanceof Match) { } else if (elementA instanceof Match && elementB instanceof Match) {
>elementA instanceof Match && elementB instanceof Match : boolean >elementA instanceof Match && elementB instanceof Match : boolean
>elementA instanceof Match : boolean >elementA instanceof Match : boolean
>elementA : FileMatch | Match >elementA : Match | FileMatch
>Match : typeof Match >Match : typeof Match
>elementB instanceof Match : boolean >elementB instanceof Match : boolean
>elementB : FileMatch | Match >elementB : FileMatch | Match

View file

@ -0,0 +1,10 @@
//// [noReachabilityErrorsOnEmptyStatement.ts]
function foo() {
return 1;;
}
//// [noReachabilityErrorsOnEmptyStatement.js]
function foo() {
return 1;
;
}

View file

@ -0,0 +1,6 @@
=== tests/cases/compiler/noReachabilityErrorsOnEmptyStatement.ts ===
function foo() {
>foo : Symbol(foo, Decl(noReachabilityErrorsOnEmptyStatement.ts, 0, 0))
return 1;;
}

View file

@ -0,0 +1,7 @@
=== tests/cases/compiler/noReachabilityErrorsOnEmptyStatement.ts ===
function foo() {
>foo : () => number
return 1;;
>1 : number
}

View file

@ -1,19 +1,7 @@
tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(3,12): error TS4050: Return type of public static method from exported class has or is using name 'Widget1' from external module "tests/cases/compiler/privacyFunctionReturnTypeDeclFile_Widgets" but cannot be named. tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(3,12): error TS4050: Return type of public static method from exported class has or is using name 'Widget1' from external module "tests/cases/compiler/privacyFunctionReturnTypeDeclFile_Widgets" but cannot be named.
tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(7,49): error TS7027: Unreachable code detected.
tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(9,5): error TS4053: Return type of public method from exported class has or is using name 'Widget1' from external module "tests/cases/compiler/privacyFunctionReturnTypeDeclFile_Widgets" but cannot be named. tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(9,5): error TS4053: Return type of public method from exported class has or is using name 'Widget1' from external module "tests/cases/compiler/privacyFunctionReturnTypeDeclFile_Widgets" but cannot be named.
tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(10,49): error TS7027: Unreachable code detected.
tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(13,49): error TS7027: Unreachable code detected.
tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(15,12): error TS4050: Return type of public static method from exported class has or is using name 'Widget3' from external module "GlobalWidgets" but cannot be named. tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(15,12): error TS4050: Return type of public static method from exported class has or is using name 'Widget3' from external module "GlobalWidgets" but cannot be named.
tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(19,49): error TS7027: Unreachable code detected.
tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(21,5): error TS4053: Return type of public method from exported class has or is using name 'Widget3' from external module "GlobalWidgets" but cannot be named. tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(21,5): error TS4053: Return type of public method from exported class has or is using name 'Widget3' from external module "GlobalWidgets" but cannot be named.
tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(22,49): error TS7027: Unreachable code detected.
tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(25,49): error TS7027: Unreachable code detected.
tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(34,49): error TS7027: Unreachable code detected.
tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(37,49): error TS7027: Unreachable code detected.
tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(40,49): error TS7027: Unreachable code detected.
tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(46,49): error TS7027: Unreachable code detected.
tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(49,49): error TS7027: Unreachable code detected.
tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(52,49): error TS7027: Unreachable code detected.
tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(56,17): error TS4058: Return type of exported function has or is using name 'Widget1' from external module "tests/cases/compiler/privacyFunctionReturnTypeDeclFile_Widgets" but cannot be named. tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(56,17): error TS4058: Return type of exported function has or is using name 'Widget1' from external module "tests/cases/compiler/privacyFunctionReturnTypeDeclFile_Widgets" but cannot be named.
tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(62,17): error TS4058: Return type of exported function has or is using name 'Widget3' from external module "GlobalWidgets" but cannot be named. tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(62,17): error TS4058: Return type of exported function has or is using name 'Widget3' from external module "GlobalWidgets" but cannot be named.
tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(70,12): error TS4050: Return type of public static method from exported class has or is using name 'SpecializedWidget.Widget2' from external module "tests/cases/compiler/privacyFunctionReturnTypeDeclFile_Widgets" but cannot be named. tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(70,12): error TS4050: Return type of public static method from exported class has or is using name 'SpecializedWidget.Widget2' from external module "tests/cases/compiler/privacyFunctionReturnTypeDeclFile_Widgets" but cannot be named.
@ -24,7 +12,7 @@ tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(83,17): error
tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(86,17): error TS4058: Return type of exported function has or is using name 'SpecializedGlobalWidget.Widget4' from external module "GlobalWidgets" but cannot be named. tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(86,17): error TS4058: Return type of exported function has or is using name 'SpecializedGlobalWidget.Widget4' from external module "GlobalWidgets" but cannot be named.
==== tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts (24 errors) ==== ==== tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts (12 errors) ====
import exporter = require("./privacyFunctionReturnTypeDeclFile_exporter"); import exporter = require("./privacyFunctionReturnTypeDeclFile_exporter");
export class publicClassWithWithPrivateParmeterTypes { export class publicClassWithWithPrivateParmeterTypes {
static myPublicStaticMethod() { // Error static myPublicStaticMethod() { // Error
@ -34,20 +22,14 @@ tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(86,17): error
} }
private static myPrivateStaticMethod() { private static myPrivateStaticMethod() {
return exporter.createExportedWidget1();; return exporter.createExportedWidget1();;
~
!!! error TS7027: Unreachable code detected.
} }
myPublicMethod() { // Error myPublicMethod() { // Error
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
!!! error TS4053: Return type of public method from exported class has or is using name 'Widget1' from external module "tests/cases/compiler/privacyFunctionReturnTypeDeclFile_Widgets" but cannot be named. !!! error TS4053: Return type of public method from exported class has or is using name 'Widget1' from external module "tests/cases/compiler/privacyFunctionReturnTypeDeclFile_Widgets" but cannot be named.
return exporter.createExportedWidget1();; return exporter.createExportedWidget1();;
~
!!! error TS7027: Unreachable code detected.
} }
private myPrivateMethod() { private myPrivateMethod() {
return exporter.createExportedWidget1();; return exporter.createExportedWidget1();;
~
!!! error TS7027: Unreachable code detected.
} }
static myPublicStaticMethod1() { // Error static myPublicStaticMethod1() { // Error
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
@ -56,20 +38,14 @@ tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(86,17): error
} }
private static myPrivateStaticMethod1() { private static myPrivateStaticMethod1() {
return exporter.createExportedWidget3();; return exporter.createExportedWidget3();;
~
!!! error TS7027: Unreachable code detected.
} }
myPublicMethod1() { // Error myPublicMethod1() { // Error
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
!!! error TS4053: Return type of public method from exported class has or is using name 'Widget3' from external module "GlobalWidgets" but cannot be named. !!! error TS4053: Return type of public method from exported class has or is using name 'Widget3' from external module "GlobalWidgets" but cannot be named.
return exporter.createExportedWidget3();; return exporter.createExportedWidget3();;
~
!!! error TS7027: Unreachable code detected.
} }
private myPrivateMethod1() { private myPrivateMethod1() {
return exporter.createExportedWidget3();; return exporter.createExportedWidget3();;
~
!!! error TS7027: Unreachable code detected.
} }
} }
@ -79,36 +55,24 @@ tests/cases/compiler/privacyFunctionReturnTypeDeclFile_consumer.ts(86,17): error
} }
private static myPrivateStaticMethod() { private static myPrivateStaticMethod() {
return exporter.createExportedWidget1();; return exporter.createExportedWidget1();;
~
!!! error TS7027: Unreachable code detected.
} }
myPublicMethod() { myPublicMethod() {
return exporter.createExportedWidget1();; return exporter.createExportedWidget1();;
~
!!! error TS7027: Unreachable code detected.
} }
private myPrivateMethod() { private myPrivateMethod() {
return exporter.createExportedWidget1();; return exporter.createExportedWidget1();;
~
!!! error TS7027: Unreachable code detected.
} }
static myPublicStaticMethod1() { static myPublicStaticMethod1() {
return exporter.createExportedWidget3(); return exporter.createExportedWidget3();
} }
private static myPrivateStaticMethod1() { private static myPrivateStaticMethod1() {
return exporter.createExportedWidget3();; return exporter.createExportedWidget3();;
~
!!! error TS7027: Unreachable code detected.
} }
myPublicMethod1() { myPublicMethod1() {
return exporter.createExportedWidget3();; return exporter.createExportedWidget3();;
~
!!! error TS7027: Unreachable code detected.
} }
private myPrivateMethod1() { private myPrivateMethod1() {
return exporter.createExportedWidget3();; return exporter.createExportedWidget3();;
~
!!! error TS7027: Unreachable code detected.
} }
} }

View file

@ -0,0 +1,50 @@
//// [thisTypeAndConstraints.ts]
class A {
self() {
return this;
}
}
function f<T extends A>(x: T) {
function g<U extends T>(x: U) {
x = x.self();
}
x = x.self();
}
class B<T extends A> {
foo(x: T) {
x = x.self();
}
bar<U extends T>(x: U) {
x = x.self();
}
}
//// [thisTypeAndConstraints.js]
var A = (function () {
function A() {
}
A.prototype.self = function () {
return this;
};
return A;
})();
function f(x) {
function g(x) {
x = x.self();
}
x = x.self();
}
var B = (function () {
function B() {
}
B.prototype.foo = function (x) {
x = x.self();
};
B.prototype.bar = function (x) {
x = x.self();
};
return B;
})();

View file

@ -0,0 +1,70 @@
=== tests/cases/conformance/types/thisType/thisTypeAndConstraints.ts ===
class A {
>A : Symbol(A, Decl(thisTypeAndConstraints.ts, 0, 0))
self() {
>self : Symbol(self, Decl(thisTypeAndConstraints.ts, 0, 9))
return this;
>this : Symbol(A, Decl(thisTypeAndConstraints.ts, 0, 0))
}
}
function f<T extends A>(x: T) {
>f : Symbol(f, Decl(thisTypeAndConstraints.ts, 4, 1))
>T : Symbol(T, Decl(thisTypeAndConstraints.ts, 6, 11))
>A : Symbol(A, Decl(thisTypeAndConstraints.ts, 0, 0))
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 6, 24))
>T : Symbol(T, Decl(thisTypeAndConstraints.ts, 6, 11))
function g<U extends T>(x: U) {
>g : Symbol(g, Decl(thisTypeAndConstraints.ts, 6, 31))
>U : Symbol(U, Decl(thisTypeAndConstraints.ts, 7, 15))
>T : Symbol(T, Decl(thisTypeAndConstraints.ts, 6, 11))
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 7, 28))
>U : Symbol(U, Decl(thisTypeAndConstraints.ts, 7, 15))
x = x.self();
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 7, 28))
>x.self : Symbol(A.self, Decl(thisTypeAndConstraints.ts, 0, 9))
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 7, 28))
>self : Symbol(A.self, Decl(thisTypeAndConstraints.ts, 0, 9))
}
x = x.self();
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 6, 24))
>x.self : Symbol(A.self, Decl(thisTypeAndConstraints.ts, 0, 9))
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 6, 24))
>self : Symbol(A.self, Decl(thisTypeAndConstraints.ts, 0, 9))
}
class B<T extends A> {
>B : Symbol(B, Decl(thisTypeAndConstraints.ts, 11, 1))
>T : Symbol(T, Decl(thisTypeAndConstraints.ts, 13, 8))
>A : Symbol(A, Decl(thisTypeAndConstraints.ts, 0, 0))
foo(x: T) {
>foo : Symbol(foo, Decl(thisTypeAndConstraints.ts, 13, 22))
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 14, 8))
>T : Symbol(T, Decl(thisTypeAndConstraints.ts, 13, 8))
x = x.self();
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 14, 8))
>x.self : Symbol(A.self, Decl(thisTypeAndConstraints.ts, 0, 9))
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 14, 8))
>self : Symbol(A.self, Decl(thisTypeAndConstraints.ts, 0, 9))
}
bar<U extends T>(x: U) {
>bar : Symbol(bar, Decl(thisTypeAndConstraints.ts, 16, 5))
>U : Symbol(U, Decl(thisTypeAndConstraints.ts, 17, 8))
>T : Symbol(T, Decl(thisTypeAndConstraints.ts, 13, 8))
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 17, 21))
>U : Symbol(U, Decl(thisTypeAndConstraints.ts, 17, 8))
x = x.self();
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 17, 21))
>x.self : Symbol(A.self, Decl(thisTypeAndConstraints.ts, 0, 9))
>x : Symbol(x, Decl(thisTypeAndConstraints.ts, 17, 21))
>self : Symbol(A.self, Decl(thisTypeAndConstraints.ts, 0, 9))
}
}

View file

@ -0,0 +1,78 @@
=== tests/cases/conformance/types/thisType/thisTypeAndConstraints.ts ===
class A {
>A : A
self() {
>self : () => this
return this;
>this : this
}
}
function f<T extends A>(x: T) {
>f : <T extends A>(x: T) => void
>T : T
>A : A
>x : T
>T : T
function g<U extends T>(x: U) {
>g : <U extends T>(x: U) => void
>U : U
>T : T
>x : U
>U : U
x = x.self();
>x = x.self() : U
>x : U
>x.self() : U
>x.self : () => U
>x : U
>self : () => U
}
x = x.self();
>x = x.self() : T
>x : T
>x.self() : T
>x.self : () => T
>x : T
>self : () => T
}
class B<T extends A> {
>B : B<T>
>T : T
>A : A
foo(x: T) {
>foo : (x: T) => void
>x : T
>T : T
x = x.self();
>x = x.self() : T
>x : T
>x.self() : T
>x.self : () => T
>x : T
>self : () => T
}
bar<U extends T>(x: U) {
>bar : <U extends T>(x: U) => void
>U : U
>T : T
>x : U
>U : U
x = x.self();
>x = x.self() : U
>x : U
>x.self() : U
>x.self : () => U
>x : U
>self : () => U
}
}

View file

@ -1,57 +0,0 @@
tests/cases/conformance/types/thisType/thisTypeInClasses.ts(4,20): error TS2526: A 'this' type is available only in a non-static member of a class or interface.
==== tests/cases/conformance/types/thisType/thisTypeInClasses.ts (1 errors) ====
class C1 {
x: this;
f(x: this): this { return undefined; }
constructor(x: this) { }
~~~~
!!! error TS2526: A 'this' type is available only in a non-static member of a class or interface.
}
class C2 {
[x: string]: this;
}
interface Foo<T> {
x: T;
y: this;
}
class C3 {
a: this[];
b: [this, this];
c: this | Date;
d: this & Date;
e: (((this)));
f: (x: this) => this;
g: new (x: this) => this;
h: Foo<this>;
i: Foo<this | (() => this)>;
j: (x: any) => x is this;
}
declare class C4 {
x: this;
f(x: this): this;
}
class C5 {
foo() {
let f1 = (x: this): this => this;
let f2 = (x: this) => this;
let f3 = (x: this) => (y: this) => this;
let f4 = (x: this) => {
let g = (y: this) => {
return () => this;
}
return g(this);
}
}
bar() {
let x1 = <this>undefined;
let x2 = undefined as this;
}
}

View file

@ -2,7 +2,6 @@
class C1 { class C1 {
x: this; x: this;
f(x: this): this { return undefined; } f(x: this): this { return undefined; }
constructor(x: this) { }
} }
class C2 { class C2 {
@ -53,7 +52,7 @@ class C5 {
//// [thisTypeInClasses.js] //// [thisTypeInClasses.js]
var C1 = (function () { var C1 = (function () {
function C1(x) { function C1() {
} }
C1.prototype.f = function (x) { return undefined; }; C1.prototype.f = function (x) { return undefined; };
return C1; return C1;

View file

@ -9,131 +9,128 @@ class C1 {
>f : Symbol(f, Decl(thisTypeInClasses.ts, 1, 12)) >f : Symbol(f, Decl(thisTypeInClasses.ts, 1, 12))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 2, 6)) >x : Symbol(x, Decl(thisTypeInClasses.ts, 2, 6))
>undefined : Symbol(undefined) >undefined : Symbol(undefined)
constructor(x: this) { }
>x : Symbol(x, Decl(thisTypeInClasses.ts, 3, 16))
} }
class C2 { class C2 {
>C2 : Symbol(C2, Decl(thisTypeInClasses.ts, 4, 1)) >C2 : Symbol(C2, Decl(thisTypeInClasses.ts, 3, 1))
[x: string]: this; [x: string]: this;
>x : Symbol(x, Decl(thisTypeInClasses.ts, 7, 5)) >x : Symbol(x, Decl(thisTypeInClasses.ts, 6, 5))
} }
interface Foo<T> { interface Foo<T> {
>Foo : Symbol(Foo, Decl(thisTypeInClasses.ts, 8, 1)) >Foo : Symbol(Foo, Decl(thisTypeInClasses.ts, 7, 1))
>T : Symbol(T, Decl(thisTypeInClasses.ts, 10, 14)) >T : Symbol(T, Decl(thisTypeInClasses.ts, 9, 14))
x: T; x: T;
>x : Symbol(x, Decl(thisTypeInClasses.ts, 10, 18)) >x : Symbol(x, Decl(thisTypeInClasses.ts, 9, 18))
>T : Symbol(T, Decl(thisTypeInClasses.ts, 10, 14)) >T : Symbol(T, Decl(thisTypeInClasses.ts, 9, 14))
y: this; y: this;
>y : Symbol(y, Decl(thisTypeInClasses.ts, 11, 9)) >y : Symbol(y, Decl(thisTypeInClasses.ts, 10, 9))
} }
class C3 { class C3 {
>C3 : Symbol(C3, Decl(thisTypeInClasses.ts, 13, 1)) >C3 : Symbol(C3, Decl(thisTypeInClasses.ts, 12, 1))
a: this[]; a: this[];
>a : Symbol(a, Decl(thisTypeInClasses.ts, 15, 10)) >a : Symbol(a, Decl(thisTypeInClasses.ts, 14, 10))
b: [this, this]; b: [this, this];
>b : Symbol(b, Decl(thisTypeInClasses.ts, 16, 14)) >b : Symbol(b, Decl(thisTypeInClasses.ts, 15, 14))
c: this | Date; c: this | Date;
>c : Symbol(c, Decl(thisTypeInClasses.ts, 17, 20)) >c : Symbol(c, Decl(thisTypeInClasses.ts, 16, 20))
>Date : Symbol(Date, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >Date : Symbol(Date, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
d: this & Date; d: this & Date;
>d : Symbol(d, Decl(thisTypeInClasses.ts, 18, 19)) >d : Symbol(d, Decl(thisTypeInClasses.ts, 17, 19))
>Date : Symbol(Date, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >Date : Symbol(Date, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
e: (((this))); e: (((this)));
>e : Symbol(e, Decl(thisTypeInClasses.ts, 19, 19)) >e : Symbol(e, Decl(thisTypeInClasses.ts, 18, 19))
f: (x: this) => this; f: (x: this) => this;
>f : Symbol(f, Decl(thisTypeInClasses.ts, 20, 18)) >f : Symbol(f, Decl(thisTypeInClasses.ts, 19, 18))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 21, 8)) >x : Symbol(x, Decl(thisTypeInClasses.ts, 20, 8))
g: new (x: this) => this; g: new (x: this) => this;
>g : Symbol(g, Decl(thisTypeInClasses.ts, 21, 25)) >g : Symbol(g, Decl(thisTypeInClasses.ts, 20, 25))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 22, 12)) >x : Symbol(x, Decl(thisTypeInClasses.ts, 21, 12))
h: Foo<this>; h: Foo<this>;
>h : Symbol(h, Decl(thisTypeInClasses.ts, 22, 29)) >h : Symbol(h, Decl(thisTypeInClasses.ts, 21, 29))
>Foo : Symbol(Foo, Decl(thisTypeInClasses.ts, 8, 1)) >Foo : Symbol(Foo, Decl(thisTypeInClasses.ts, 7, 1))
i: Foo<this | (() => this)>; i: Foo<this | (() => this)>;
>i : Symbol(i, Decl(thisTypeInClasses.ts, 23, 17)) >i : Symbol(i, Decl(thisTypeInClasses.ts, 22, 17))
>Foo : Symbol(Foo, Decl(thisTypeInClasses.ts, 8, 1)) >Foo : Symbol(Foo, Decl(thisTypeInClasses.ts, 7, 1))
j: (x: any) => x is this; j: (x: any) => x is this;
>j : Symbol(j, Decl(thisTypeInClasses.ts, 24, 32)) >j : Symbol(j, Decl(thisTypeInClasses.ts, 23, 32))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 25, 8)) >x : Symbol(x, Decl(thisTypeInClasses.ts, 24, 8))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 25, 8)) >x : Symbol(x, Decl(thisTypeInClasses.ts, 24, 8))
} }
declare class C4 { declare class C4 {
>C4 : Symbol(C4, Decl(thisTypeInClasses.ts, 26, 1)) >C4 : Symbol(C4, Decl(thisTypeInClasses.ts, 25, 1))
x: this; x: this;
>x : Symbol(x, Decl(thisTypeInClasses.ts, 28, 18)) >x : Symbol(x, Decl(thisTypeInClasses.ts, 27, 18))
f(x: this): this; f(x: this): this;
>f : Symbol(f, Decl(thisTypeInClasses.ts, 29, 12)) >f : Symbol(f, Decl(thisTypeInClasses.ts, 28, 12))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 30, 6)) >x : Symbol(x, Decl(thisTypeInClasses.ts, 29, 6))
} }
class C5 { class C5 {
>C5 : Symbol(C5, Decl(thisTypeInClasses.ts, 31, 1)) >C5 : Symbol(C5, Decl(thisTypeInClasses.ts, 30, 1))
foo() { foo() {
>foo : Symbol(foo, Decl(thisTypeInClasses.ts, 33, 10)) >foo : Symbol(foo, Decl(thisTypeInClasses.ts, 32, 10))
let f1 = (x: this): this => this; let f1 = (x: this): this => this;
>f1 : Symbol(f1, Decl(thisTypeInClasses.ts, 35, 11)) >f1 : Symbol(f1, Decl(thisTypeInClasses.ts, 34, 11))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 35, 18)) >x : Symbol(x, Decl(thisTypeInClasses.ts, 34, 18))
>this : Symbol(C5, Decl(thisTypeInClasses.ts, 31, 1)) >this : Symbol(C5, Decl(thisTypeInClasses.ts, 30, 1))
>this : Symbol(C5, Decl(thisTypeInClasses.ts, 31, 1)) >this : Symbol(C5, Decl(thisTypeInClasses.ts, 30, 1))
let f2 = (x: this) => this; let f2 = (x: this) => this;
>f2 : Symbol(f2, Decl(thisTypeInClasses.ts, 36, 11)) >f2 : Symbol(f2, Decl(thisTypeInClasses.ts, 35, 11))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 36, 18)) >x : Symbol(x, Decl(thisTypeInClasses.ts, 35, 18))
>this : Symbol(C5, Decl(thisTypeInClasses.ts, 31, 1)) >this : Symbol(C5, Decl(thisTypeInClasses.ts, 30, 1))
let f3 = (x: this) => (y: this) => this; let f3 = (x: this) => (y: this) => this;
>f3 : Symbol(f3, Decl(thisTypeInClasses.ts, 37, 11)) >f3 : Symbol(f3, Decl(thisTypeInClasses.ts, 36, 11))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 37, 18)) >x : Symbol(x, Decl(thisTypeInClasses.ts, 36, 18))
>y : Symbol(y, Decl(thisTypeInClasses.ts, 37, 31)) >y : Symbol(y, Decl(thisTypeInClasses.ts, 36, 31))
>this : Symbol(C5, Decl(thisTypeInClasses.ts, 31, 1)) >this : Symbol(C5, Decl(thisTypeInClasses.ts, 30, 1))
let f4 = (x: this) => { let f4 = (x: this) => {
>f4 : Symbol(f4, Decl(thisTypeInClasses.ts, 38, 11)) >f4 : Symbol(f4, Decl(thisTypeInClasses.ts, 37, 11))
>x : Symbol(x, Decl(thisTypeInClasses.ts, 38, 18)) >x : Symbol(x, Decl(thisTypeInClasses.ts, 37, 18))
let g = (y: this) => { let g = (y: this) => {
>g : Symbol(g, Decl(thisTypeInClasses.ts, 39, 15)) >g : Symbol(g, Decl(thisTypeInClasses.ts, 38, 15))
>y : Symbol(y, Decl(thisTypeInClasses.ts, 39, 21)) >y : Symbol(y, Decl(thisTypeInClasses.ts, 38, 21))
return () => this; return () => this;
>this : Symbol(C5, Decl(thisTypeInClasses.ts, 31, 1)) >this : Symbol(C5, Decl(thisTypeInClasses.ts, 30, 1))
} }
return g(this); return g(this);
>g : Symbol(g, Decl(thisTypeInClasses.ts, 39, 15)) >g : Symbol(g, Decl(thisTypeInClasses.ts, 38, 15))
>this : Symbol(C5, Decl(thisTypeInClasses.ts, 31, 1)) >this : Symbol(C5, Decl(thisTypeInClasses.ts, 30, 1))
} }
} }
bar() { bar() {
>bar : Symbol(bar, Decl(thisTypeInClasses.ts, 44, 5)) >bar : Symbol(bar, Decl(thisTypeInClasses.ts, 43, 5))
let x1 = <this>undefined; let x1 = <this>undefined;
>x1 : Symbol(x1, Decl(thisTypeInClasses.ts, 46, 11)) >x1 : Symbol(x1, Decl(thisTypeInClasses.ts, 45, 11))
>undefined : Symbol(undefined) >undefined : Symbol(undefined)
let x2 = undefined as this; let x2 = undefined as this;
>x2 : Symbol(x2, Decl(thisTypeInClasses.ts, 47, 11)) >x2 : Symbol(x2, Decl(thisTypeInClasses.ts, 46, 11))
>undefined : Symbol(undefined) >undefined : Symbol(undefined)
} }
} }

View file

@ -9,9 +9,6 @@ class C1 {
>f : (x: this) => this >f : (x: this) => this
>x : this >x : this
>undefined : undefined >undefined : undefined
constructor(x: this) { }
>x : this
} }
class C2 { class C2 {

View file

@ -14,21 +14,58 @@ class C2 {
class D1 extends C1 { class D1 extends C1 {
p3: number; p3: number;
} }
class C3 {
p4: number;
}
var str: string; var str: string;
var num: number; var num: number;
var strOrNum: string | number; var strOrNum: string | number;
var c1Orc2: C1 | C2; var ctor1: C1 | C2;
str = c1Orc2 instanceof C1 && c1Orc2.p1; // C1 str = ctor1 instanceof C1 && ctor1.p1; // C1
num = c1Orc2 instanceof C2 && c1Orc2.p2; // C2 num = ctor1 instanceof C2 && ctor1.p2; // C2
str = c1Orc2 instanceof D1 && c1Orc2.p1; // D1 str = ctor1 instanceof D1 && ctor1.p1; // D1
num = c1Orc2 instanceof D1 && c1Orc2.p3; // D1 num = ctor1 instanceof D1 && ctor1.p3; // D1
var c2Ord1: C2 | D1; var ctor2: C2 | D1;
num = c2Ord1 instanceof C2 && c2Ord1.p2; // C2 num = ctor2 instanceof C2 && ctor2.p2; // C2
num = c2Ord1 instanceof D1 && c2Ord1.p3; // D1 num = ctor2 instanceof D1 && ctor2.p3; // D1
str = c2Ord1 instanceof D1 && c2Ord1.p1; // D1 str = ctor2 instanceof D1 && ctor2.p1; // D1
var r2: D1 | C2 = c2Ord1 instanceof C1 && c2Ord1; // C2 | D1 var r2: D1 | C2 = ctor2 instanceof C1 && ctor2; // C2 | D1
var ctor3: C1 | C2;
if (ctor3 instanceof C1) {
ctor3.p1; // C1
}
else {
ctor3.p2; // C2
}
var ctor4: C1 | C2 | C3;
if (ctor4 instanceof C1) {
ctor4.p1; // C1
}
else if (ctor4 instanceof C2) {
ctor4.p2; // C2
}
else {
ctor4.p4; // C3
}
var ctor5: C1 | D1 | C2;
if (ctor5 instanceof C1) {
ctor5.p1; // C1
}
else {
ctor5.p2; // C2
}
var ctor6: C1 | C2 | C3;
if (ctor6 instanceof C1 || ctor6 instanceof C2) {
}
else {
ctor6.p4; // C3
}
//// [typeGuardOfFormInstanceOf.js] //// [typeGuardOfFormInstanceOf.js]
// A type guard of the form x instanceof C, where C is of a subtype of the global type 'Function' // A type guard of the form x instanceof C, where C is of a subtype of the global type 'Function'
@ -58,16 +95,51 @@ var D1 = (function (_super) {
} }
return D1; return D1;
})(C1); })(C1);
var C3 = (function () {
function C3() {
}
return C3;
})();
var str; var str;
var num; var num;
var strOrNum; var strOrNum;
var c1Orc2; var ctor1;
str = c1Orc2 instanceof C1 && c1Orc2.p1; // C1 str = ctor1 instanceof C1 && ctor1.p1; // C1
num = c1Orc2 instanceof C2 && c1Orc2.p2; // C2 num = ctor1 instanceof C2 && ctor1.p2; // C2
str = c1Orc2 instanceof D1 && c1Orc2.p1; // D1 str = ctor1 instanceof D1 && ctor1.p1; // D1
num = c1Orc2 instanceof D1 && c1Orc2.p3; // D1 num = ctor1 instanceof D1 && ctor1.p3; // D1
var c2Ord1; var ctor2;
num = c2Ord1 instanceof C2 && c2Ord1.p2; // C2 num = ctor2 instanceof C2 && ctor2.p2; // C2
num = c2Ord1 instanceof D1 && c2Ord1.p3; // D1 num = ctor2 instanceof D1 && ctor2.p3; // D1
str = c2Ord1 instanceof D1 && c2Ord1.p1; // D1 str = ctor2 instanceof D1 && ctor2.p1; // D1
var r2 = c2Ord1 instanceof C1 && c2Ord1; // C2 | D1 var r2 = ctor2 instanceof C1 && ctor2; // C2 | D1
var ctor3;
if (ctor3 instanceof C1) {
ctor3.p1; // C1
}
else {
ctor3.p2; // C2
}
var ctor4;
if (ctor4 instanceof C1) {
ctor4.p1; // C1
}
else if (ctor4 instanceof C2) {
ctor4.p2; // C2
}
else {
ctor4.p4; // C3
}
var ctor5;
if (ctor5 instanceof C1) {
ctor5.p1; // C1
}
else {
ctor5.p2; // C2
}
var ctor6;
if (ctor6 instanceof C1 || ctor6 instanceof C2) {
}
else {
ctor6.p4; // C3
}

View file

@ -24,86 +24,184 @@ class D1 extends C1 {
p3: number; p3: number;
>p3 : Symbol(p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21)) >p3 : Symbol(p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21))
} }
class C3 {
>C3 : Symbol(C3, Decl(typeGuardOfFormInstanceOf.ts, 14, 1))
p4: number;
>p4 : Symbol(p4, Decl(typeGuardOfFormInstanceOf.ts, 15, 10))
}
var str: string; var str: string;
>str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 15, 3)) >str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 18, 3))
var num: number; var num: number;
>num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 16, 3)) >num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 19, 3))
var strOrNum: string | number; var strOrNum: string | number;
>strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormInstanceOf.ts, 17, 3)) >strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormInstanceOf.ts, 20, 3))
var c1Orc2: C1 | C2; var ctor1: C1 | C2;
>c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) >ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3))
>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0)) >C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0))
>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1)) >C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1))
str = c1Orc2 instanceof C1 && c1Orc2.p1; // C1 str = ctor1 instanceof C1 && ctor1.p1; // C1
>str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 15, 3)) >str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 18, 3))
>c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) >ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3))
>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0)) >C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0))
>c1Orc2.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10)) >ctor1.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
>c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) >ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3))
>p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10)) >p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
num = c1Orc2 instanceof C2 && c1Orc2.p2; // C2 num = ctor1 instanceof C2 && ctor1.p2; // C2
>num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 16, 3)) >num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 19, 3))
>c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) >ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3))
>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1)) >C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1))
>c1Orc2.p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10)) >ctor1.p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10))
>c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) >ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3))
>p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10)) >p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10))
str = c1Orc2 instanceof D1 && c1Orc2.p1; // D1 str = ctor1 instanceof D1 && ctor1.p1; // D1
>str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 15, 3)) >str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 18, 3))
>c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) >ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3))
>D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1)) >D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1))
>c1Orc2.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10)) >ctor1.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
>c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) >ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3))
>p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10)) >p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
num = c1Orc2 instanceof D1 && c1Orc2.p3; // D1 num = ctor1 instanceof D1 && ctor1.p3; // D1
>num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 16, 3)) >num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 19, 3))
>c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) >ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3))
>D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1)) >D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1))
>c1Orc2.p3 : Symbol(D1.p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21)) >ctor1.p3 : Symbol(D1.p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21))
>c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) >ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3))
>p3 : Symbol(D1.p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21)) >p3 : Symbol(D1.p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21))
var c2Ord1: C2 | D1; var ctor2: C2 | D1;
>c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3)) >ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3))
>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1)) >C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1))
>D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1)) >D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1))
num = c2Ord1 instanceof C2 && c2Ord1.p2; // C2 num = ctor2 instanceof C2 && ctor2.p2; // C2
>num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 16, 3)) >num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 19, 3))
>c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3)) >ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3))
>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1)) >C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1))
>c2Ord1.p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10)) >ctor2.p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10))
>c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3)) >ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3))
>p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10)) >p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10))
num = c2Ord1 instanceof D1 && c2Ord1.p3; // D1 num = ctor2 instanceof D1 && ctor2.p3; // D1
>num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 16, 3)) >num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 19, 3))
>c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3)) >ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3))
>D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1)) >D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1))
>c2Ord1.p3 : Symbol(D1.p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21)) >ctor2.p3 : Symbol(D1.p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21))
>c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3)) >ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3))
>p3 : Symbol(D1.p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21)) >p3 : Symbol(D1.p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21))
str = c2Ord1 instanceof D1 && c2Ord1.p1; // D1 str = ctor2 instanceof D1 && ctor2.p1; // D1
>str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 15, 3)) >str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 18, 3))
>c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3)) >ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3))
>D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1)) >D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1))
>c2Ord1.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10)) >ctor2.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
>c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3)) >ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3))
>p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10)) >p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
var r2: D1 | C2 = c2Ord1 instanceof C1 && c2Ord1; // C2 | D1 var r2: D1 | C2 = ctor2 instanceof C1 && ctor2; // C2 | D1
>r2 : Symbol(r2, Decl(typeGuardOfFormInstanceOf.ts, 29, 3)) >r2 : Symbol(r2, Decl(typeGuardOfFormInstanceOf.ts, 32, 3))
>D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1)) >D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1))
>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1)) >C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1))
>c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3)) >ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3))
>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0)) >C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0))
>c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3)) >ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3))
var ctor3: C1 | C2;
>ctor3 : Symbol(ctor3, Decl(typeGuardOfFormInstanceOf.ts, 34, 3))
>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0))
>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1))
if (ctor3 instanceof C1) {
>ctor3 : Symbol(ctor3, Decl(typeGuardOfFormInstanceOf.ts, 34, 3))
>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0))
ctor3.p1; // C1
>ctor3.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
>ctor3 : Symbol(ctor3, Decl(typeGuardOfFormInstanceOf.ts, 34, 3))
>p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
}
else {
ctor3.p2; // C2
>ctor3.p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10))
>ctor3 : Symbol(ctor3, Decl(typeGuardOfFormInstanceOf.ts, 34, 3))
>p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10))
}
var ctor4: C1 | C2 | C3;
>ctor4 : Symbol(ctor4, Decl(typeGuardOfFormInstanceOf.ts, 42, 3))
>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0))
>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1))
>C3 : Symbol(C3, Decl(typeGuardOfFormInstanceOf.ts, 14, 1))
if (ctor4 instanceof C1) {
>ctor4 : Symbol(ctor4, Decl(typeGuardOfFormInstanceOf.ts, 42, 3))
>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0))
ctor4.p1; // C1
>ctor4.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
>ctor4 : Symbol(ctor4, Decl(typeGuardOfFormInstanceOf.ts, 42, 3))
>p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
}
else if (ctor4 instanceof C2) {
>ctor4 : Symbol(ctor4, Decl(typeGuardOfFormInstanceOf.ts, 42, 3))
>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1))
ctor4.p2; // C2
>ctor4.p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10))
>ctor4 : Symbol(ctor4, Decl(typeGuardOfFormInstanceOf.ts, 42, 3))
>p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10))
}
else {
ctor4.p4; // C3
>ctor4.p4 : Symbol(C3.p4, Decl(typeGuardOfFormInstanceOf.ts, 15, 10))
>ctor4 : Symbol(ctor4, Decl(typeGuardOfFormInstanceOf.ts, 42, 3))
>p4 : Symbol(C3.p4, Decl(typeGuardOfFormInstanceOf.ts, 15, 10))
}
var ctor5: C1 | D1 | C2;
>ctor5 : Symbol(ctor5, Decl(typeGuardOfFormInstanceOf.ts, 53, 3))
>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0))
>D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1))
>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1))
if (ctor5 instanceof C1) {
>ctor5 : Symbol(ctor5, Decl(typeGuardOfFormInstanceOf.ts, 53, 3))
>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0))
ctor5.p1; // C1
>ctor5.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
>ctor5 : Symbol(ctor5, Decl(typeGuardOfFormInstanceOf.ts, 53, 3))
>p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10))
}
else {
ctor5.p2; // C2
>ctor5.p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10))
>ctor5 : Symbol(ctor5, Decl(typeGuardOfFormInstanceOf.ts, 53, 3))
>p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10))
}
var ctor6: C1 | C2 | C3;
>ctor6 : Symbol(ctor6, Decl(typeGuardOfFormInstanceOf.ts, 61, 3))
>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0))
>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1))
>C3 : Symbol(C3, Decl(typeGuardOfFormInstanceOf.ts, 14, 1))
if (ctor6 instanceof C1 || ctor6 instanceof C2) {
>ctor6 : Symbol(ctor6, Decl(typeGuardOfFormInstanceOf.ts, 61, 3))
>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0))
>ctor6 : Symbol(ctor6, Decl(typeGuardOfFormInstanceOf.ts, 61, 3))
>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1))
}
else {
ctor6.p4; // C3
>ctor6.p4 : Symbol(C3.p4, Decl(typeGuardOfFormInstanceOf.ts, 15, 10))
>ctor6 : Symbol(ctor6, Decl(typeGuardOfFormInstanceOf.ts, 61, 3))
>p4 : Symbol(C3.p4, Decl(typeGuardOfFormInstanceOf.ts, 15, 10))
}

View file

@ -24,6 +24,12 @@ class D1 extends C1 {
p3: number; p3: number;
>p3 : number >p3 : number
} }
class C3 {
>C3 : C3
p4: number;
>p4 : number
}
var str: string; var str: string;
>str : string >str : string
@ -33,100 +39,199 @@ var num: number;
var strOrNum: string | number; var strOrNum: string | number;
>strOrNum : string | number >strOrNum : string | number
var c1Orc2: C1 | C2; var ctor1: C1 | C2;
>c1Orc2 : C1 | C2 >ctor1 : C1 | C2
>C1 : C1 >C1 : C1
>C2 : C2 >C2 : C2
str = c1Orc2 instanceof C1 && c1Orc2.p1; // C1 str = ctor1 instanceof C1 && ctor1.p1; // C1
>str = c1Orc2 instanceof C1 && c1Orc2.p1 : string >str = ctor1 instanceof C1 && ctor1.p1 : string
>str : string >str : string
>c1Orc2 instanceof C1 && c1Orc2.p1 : string >ctor1 instanceof C1 && ctor1.p1 : string
>c1Orc2 instanceof C1 : boolean >ctor1 instanceof C1 : boolean
>c1Orc2 : C1 | C2 >ctor1 : C1 | C2
>C1 : typeof C1 >C1 : typeof C1
>c1Orc2.p1 : string >ctor1.p1 : string
>c1Orc2 : C1 >ctor1 : C1
>p1 : string >p1 : string
num = c1Orc2 instanceof C2 && c1Orc2.p2; // C2 num = ctor1 instanceof C2 && ctor1.p2; // C2
>num = c1Orc2 instanceof C2 && c1Orc2.p2 : number >num = ctor1 instanceof C2 && ctor1.p2 : number
>num : number >num : number
>c1Orc2 instanceof C2 && c1Orc2.p2 : number >ctor1 instanceof C2 && ctor1.p2 : number
>c1Orc2 instanceof C2 : boolean >ctor1 instanceof C2 : boolean
>c1Orc2 : C1 | C2 >ctor1 : C1 | C2
>C2 : typeof C2 >C2 : typeof C2
>c1Orc2.p2 : number >ctor1.p2 : number
>c1Orc2 : C2 >ctor1 : C2
>p2 : number >p2 : number
str = c1Orc2 instanceof D1 && c1Orc2.p1; // D1 str = ctor1 instanceof D1 && ctor1.p1; // D1
>str = c1Orc2 instanceof D1 && c1Orc2.p1 : string >str = ctor1 instanceof D1 && ctor1.p1 : string
>str : string >str : string
>c1Orc2 instanceof D1 && c1Orc2.p1 : string >ctor1 instanceof D1 && ctor1.p1 : string
>c1Orc2 instanceof D1 : boolean >ctor1 instanceof D1 : boolean
>c1Orc2 : C1 | C2 >ctor1 : C1 | C2
>D1 : typeof D1 >D1 : typeof D1
>c1Orc2.p1 : string >ctor1.p1 : string
>c1Orc2 : D1 >ctor1 : D1
>p1 : string >p1 : string
num = c1Orc2 instanceof D1 && c1Orc2.p3; // D1 num = ctor1 instanceof D1 && ctor1.p3; // D1
>num = c1Orc2 instanceof D1 && c1Orc2.p3 : number >num = ctor1 instanceof D1 && ctor1.p3 : number
>num : number >num : number
>c1Orc2 instanceof D1 && c1Orc2.p3 : number >ctor1 instanceof D1 && ctor1.p3 : number
>c1Orc2 instanceof D1 : boolean >ctor1 instanceof D1 : boolean
>c1Orc2 : C1 | C2 >ctor1 : C1 | C2
>D1 : typeof D1 >D1 : typeof D1
>c1Orc2.p3 : number >ctor1.p3 : number
>c1Orc2 : D1 >ctor1 : D1
>p3 : number >p3 : number
var c2Ord1: C2 | D1; var ctor2: C2 | D1;
>c2Ord1 : C2 | D1 >ctor2 : C2 | D1
>C2 : C2 >C2 : C2
>D1 : D1 >D1 : D1
num = c2Ord1 instanceof C2 && c2Ord1.p2; // C2 num = ctor2 instanceof C2 && ctor2.p2; // C2
>num = c2Ord1 instanceof C2 && c2Ord1.p2 : number >num = ctor2 instanceof C2 && ctor2.p2 : number
>num : number >num : number
>c2Ord1 instanceof C2 && c2Ord1.p2 : number >ctor2 instanceof C2 && ctor2.p2 : number
>c2Ord1 instanceof C2 : boolean >ctor2 instanceof C2 : boolean
>c2Ord1 : C2 | D1 >ctor2 : C2 | D1
>C2 : typeof C2 >C2 : typeof C2
>c2Ord1.p2 : number >ctor2.p2 : number
>c2Ord1 : C2 >ctor2 : C2
>p2 : number >p2 : number
num = c2Ord1 instanceof D1 && c2Ord1.p3; // D1 num = ctor2 instanceof D1 && ctor2.p3; // D1
>num = c2Ord1 instanceof D1 && c2Ord1.p3 : number >num = ctor2 instanceof D1 && ctor2.p3 : number
>num : number >num : number
>c2Ord1 instanceof D1 && c2Ord1.p3 : number >ctor2 instanceof D1 && ctor2.p3 : number
>c2Ord1 instanceof D1 : boolean >ctor2 instanceof D1 : boolean
>c2Ord1 : C2 | D1 >ctor2 : C2 | D1
>D1 : typeof D1 >D1 : typeof D1
>c2Ord1.p3 : number >ctor2.p3 : number
>c2Ord1 : D1 >ctor2 : D1
>p3 : number >p3 : number
str = c2Ord1 instanceof D1 && c2Ord1.p1; // D1 str = ctor2 instanceof D1 && ctor2.p1; // D1
>str = c2Ord1 instanceof D1 && c2Ord1.p1 : string >str = ctor2 instanceof D1 && ctor2.p1 : string
>str : string >str : string
>c2Ord1 instanceof D1 && c2Ord1.p1 : string >ctor2 instanceof D1 && ctor2.p1 : string
>c2Ord1 instanceof D1 : boolean >ctor2 instanceof D1 : boolean
>c2Ord1 : C2 | D1 >ctor2 : C2 | D1
>D1 : typeof D1 >D1 : typeof D1
>c2Ord1.p1 : string >ctor2.p1 : string
>c2Ord1 : D1 >ctor2 : D1
>p1 : string >p1 : string
var r2: D1 | C2 = c2Ord1 instanceof C1 && c2Ord1; // C2 | D1 var r2: D1 | C2 = ctor2 instanceof C1 && ctor2; // C2 | D1
>r2 : D1 | C2 >r2 : D1 | C2
>D1 : D1 >D1 : D1
>C2 : C2 >C2 : C2
>c2Ord1 instanceof C1 && c2Ord1 : D1 >ctor2 instanceof C1 && ctor2 : D1
>c2Ord1 instanceof C1 : boolean >ctor2 instanceof C1 : boolean
>c2Ord1 : C2 | D1 >ctor2 : C2 | D1
>C1 : typeof C1 >C1 : typeof C1
>c2Ord1 : D1 >ctor2 : D1
var ctor3: C1 | C2;
>ctor3 : C1 | C2
>C1 : C1
>C2 : C2
if (ctor3 instanceof C1) {
>ctor3 instanceof C1 : boolean
>ctor3 : C1 | C2
>C1 : typeof C1
ctor3.p1; // C1
>ctor3.p1 : string
>ctor3 : C1
>p1 : string
}
else {
ctor3.p2; // C2
>ctor3.p2 : number
>ctor3 : C2
>p2 : number
}
var ctor4: C1 | C2 | C3;
>ctor4 : C1 | C2 | C3
>C1 : C1
>C2 : C2
>C3 : C3
if (ctor4 instanceof C1) {
>ctor4 instanceof C1 : boolean
>ctor4 : C1 | C2 | C3
>C1 : typeof C1
ctor4.p1; // C1
>ctor4.p1 : string
>ctor4 : C1
>p1 : string
}
else if (ctor4 instanceof C2) {
>ctor4 instanceof C2 : boolean
>ctor4 : C2 | C3
>C2 : typeof C2
ctor4.p2; // C2
>ctor4.p2 : number
>ctor4 : C2
>p2 : number
}
else {
ctor4.p4; // C3
>ctor4.p4 : number
>ctor4 : C3
>p4 : number
}
var ctor5: C1 | D1 | C2;
>ctor5 : C1 | D1 | C2
>C1 : C1
>D1 : D1
>C2 : C2
if (ctor5 instanceof C1) {
>ctor5 instanceof C1 : boolean
>ctor5 : C1 | D1 | C2
>C1 : typeof C1
ctor5.p1; // C1
>ctor5.p1 : string
>ctor5 : C1
>p1 : string
}
else {
ctor5.p2; // C2
>ctor5.p2 : number
>ctor5 : C2
>p2 : number
}
var ctor6: C1 | C2 | C3;
>ctor6 : C1 | C2 | C3
>C1 : C1
>C2 : C2
>C3 : C3
if (ctor6 instanceof C1 || ctor6 instanceof C2) {
>ctor6 instanceof C1 || ctor6 instanceof C2 : boolean
>ctor6 instanceof C1 : boolean
>ctor6 : C1 | C2 | C3
>C1 : typeof C1
>ctor6 instanceof C2 : boolean
>ctor6 : C2 | C3
>C2 : typeof C2
}
else {
ctor6.p4; // C3
>ctor6.p4 : number
>ctor6 : C3
>p4 : number
}

View file

@ -0,0 +1,41 @@
tests/cases/conformance/types/union/unionTypeCallSignatures4.ts(10,1): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/conformance/types/union/unionTypeCallSignatures4.ts(20,1): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/conformance/types/union/unionTypeCallSignatures4.ts(23,1): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/conformance/types/union/unionTypeCallSignatures4.ts(25,1): error TS2346: Supplied parameters do not match any signature of call target.
==== tests/cases/conformance/types/union/unionTypeCallSignatures4.ts (4 errors) ====
type F1 = (a: string, b?: string) => void;
type F2 = (a: string, b?: string, c?: string) => void;
type F3 = (a: string, ...rest: string[]) => void;
type F4 = (a: string, b?: string, ...rest: string[]) => void;
type F5 = (a: string, b: string) => void;
var f12: F1 | F2;
f12("a");
f12("a", "b");
f12("a", "b", "c"); // error
~~~~~~~~~~~~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
var f34: F3 | F4;
f34("a");
f34("a", "b");
f34("a", "b", "c");
var f1234: F1 | F2 | F3 | F4;
f1234("a");
f1234("a", "b");
f1234("a", "b", "c"); // error
~~~~~~~~~~~~~~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
var f12345: F1 | F2 | F3 | F4 | F5;
f12345("a"); // error
~~~~~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
f12345("a", "b");
f12345("a", "b", "c"); // error
~~~~~~~~~~~~~~~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.

View file

@ -0,0 +1,45 @@
//// [unionTypeCallSignatures4.ts]
type F1 = (a: string, b?: string) => void;
type F2 = (a: string, b?: string, c?: string) => void;
type F3 = (a: string, ...rest: string[]) => void;
type F4 = (a: string, b?: string, ...rest: string[]) => void;
type F5 = (a: string, b: string) => void;
var f12: F1 | F2;
f12("a");
f12("a", "b");
f12("a", "b", "c"); // error
var f34: F3 | F4;
f34("a");
f34("a", "b");
f34("a", "b", "c");
var f1234: F1 | F2 | F3 | F4;
f1234("a");
f1234("a", "b");
f1234("a", "b", "c"); // error
var f12345: F1 | F2 | F3 | F4 | F5;
f12345("a"); // error
f12345("a", "b");
f12345("a", "b", "c"); // error
//// [unionTypeCallSignatures4.js]
var f12;
f12("a");
f12("a", "b");
f12("a", "b", "c"); // error
var f34;
f34("a");
f34("a", "b");
f34("a", "b", "c");
var f1234;
f1234("a");
f1234("a", "b");
f1234("a", "b", "c"); // error
var f12345;
f12345("a"); // error
f12345("a", "b");
f12345("a", "b", "c"); // error

View file

@ -0,0 +1,3 @@
function foo() {
return 1;;
}

View file

@ -13,18 +13,55 @@ class C2 {
class D1 extends C1 { class D1 extends C1 {
p3: number; p3: number;
} }
class C3 {
p4: number;
}
var str: string; var str: string;
var num: number; var num: number;
var strOrNum: string | number; var strOrNum: string | number;
var c1Orc2: C1 | C2; var ctor1: C1 | C2;
str = c1Orc2 instanceof C1 && c1Orc2.p1; // C1 str = ctor1 instanceof C1 && ctor1.p1; // C1
num = c1Orc2 instanceof C2 && c1Orc2.p2; // C2 num = ctor1 instanceof C2 && ctor1.p2; // C2
str = c1Orc2 instanceof D1 && c1Orc2.p1; // D1 str = ctor1 instanceof D1 && ctor1.p1; // D1
num = c1Orc2 instanceof D1 && c1Orc2.p3; // D1 num = ctor1 instanceof D1 && ctor1.p3; // D1
var c2Ord1: C2 | D1; var ctor2: C2 | D1;
num = c2Ord1 instanceof C2 && c2Ord1.p2; // C2 num = ctor2 instanceof C2 && ctor2.p2; // C2
num = c2Ord1 instanceof D1 && c2Ord1.p3; // D1 num = ctor2 instanceof D1 && ctor2.p3; // D1
str = c2Ord1 instanceof D1 && c2Ord1.p1; // D1 str = ctor2 instanceof D1 && ctor2.p1; // D1
var r2: D1 | C2 = c2Ord1 instanceof C1 && c2Ord1; // C2 | D1 var r2: D1 | C2 = ctor2 instanceof C1 && ctor2; // C2 | D1
var ctor3: C1 | C2;
if (ctor3 instanceof C1) {
ctor3.p1; // C1
}
else {
ctor3.p2; // C2
}
var ctor4: C1 | C2 | C3;
if (ctor4 instanceof C1) {
ctor4.p1; // C1
}
else if (ctor4 instanceof C2) {
ctor4.p2; // C2
}
else {
ctor4.p4; // C3
}
var ctor5: C1 | D1 | C2;
if (ctor5 instanceof C1) {
ctor5.p1; // C1
}
else {
ctor5.p2; // C2
}
var ctor6: C1 | C2 | C3;
if (ctor6 instanceof C1 || ctor6 instanceof C2) {
}
else {
ctor6.p4; // C3
}

View file

@ -0,0 +1,21 @@
class A {
self() {
return this;
}
}
function f<T extends A>(x: T) {
function g<U extends T>(x: U) {
x = x.self();
}
x = x.self();
}
class B<T extends A> {
foo(x: T) {
x = x.self();
}
bar<U extends T>(x: U) {
x = x.self();
}
}

View file

@ -1,7 +1,6 @@
class C1 { class C1 {
x: this; x: this;
f(x: this): this { return undefined; } f(x: this): this { return undefined; }
constructor(x: this) { }
} }
class C2 { class C2 {

View file

@ -0,0 +1,25 @@
type F1 = (a: string, b?: string) => void;
type F2 = (a: string, b?: string, c?: string) => void;
type F3 = (a: string, ...rest: string[]) => void;
type F4 = (a: string, b?: string, ...rest: string[]) => void;
type F5 = (a: string, b: string) => void;
var f12: F1 | F2;
f12("a");
f12("a", "b");
f12("a", "b", "c"); // error
var f34: F3 | F4;
f34("a");
f34("a", "b");
f34("a", "b", "c");
var f1234: F1 | F2 | F3 | F4;
f1234("a");
f1234("a", "b");
f1234("a", "b", "c"); // error
var f12345: F1 | F2 | F3 | F4 | F5;
f12345("a"); // error
f12345("a", "b");
f12345("a", "b", "c"); // error

View file

@ -39,6 +39,7 @@
"no-inferrable-types": true, "no-inferrable-types": true,
"no-null": true, "no-null": true,
"boolean-trivia": true, "boolean-trivia": true,
"type-operator-spacing": true "type-operator-spacing": true,
"prefer-const": true
} }
} }