Merge branch 'master' into useprintVersion

Conflicts:
	src/compiler/tsc.ts
This commit is contained in:
Yui T
2015-11-19 13:06:29 -08:00
1979 changed files with 88998 additions and 48566 deletions
+567 -75
View File
@@ -1,3 +1,4 @@
/// <reference path="utilities.ts"/>
/// <reference path="parser.ts"/>
/* @internal */
@@ -6,8 +7,23 @@ namespace ts {
export const enum ModuleInstanceState {
NonInstantiated = 0,
Instantiated = 1,
ConstEnumOnly = 2
Instantiated = 1,
ConstEnumOnly = 2
}
const enum Reachability {
Unintialized = 1 << 0,
Reachable = 1 << 1,
Unreachable = 1 << 2,
ReportedUnreachable = 1 << 3
}
function or(state1: Reachability, state2: Reachability): Reachability {
return (state1 | state2) & Reachability.Reachable
? Reachability.Reachable
: (state1 & state2) & Reachability.ReportedUnreachable
? Reachability.ReportedUnreachable
: Reachability.Unreachable;
}
export function getModuleInstanceState(node: Node): ModuleInstanceState {
@@ -77,35 +93,66 @@ namespace ts {
IsContainerWithLocals = IsContainer | HasLocals
}
export function bindSourceFile(file: SourceFile) {
let start = new Date().getTime();
bindSourceFileWorker(file);
const binder = createBinder();
export function bindSourceFile(file: SourceFile, options: CompilerOptions) {
const start = new Date().getTime();
binder(file, options);
bindTime += new Date().getTime() - start;
}
function bindSourceFileWorker(file: SourceFile) {
function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
let file: SourceFile;
let options: CompilerOptions;
let parent: Node;
let container: Node;
let blockScopeContainer: Node;
let lastContainer: Node;
let seenThisKeyword: boolean;
// state used by reachability checks
let hasExplicitReturn: boolean;
let currentReachabilityState: Reachability;
let labelStack: Reachability[];
let labelIndexMap: Map<number>;
let implicitLabels: number[];
// If this file is an external module, then it is automatically in strict-mode according to
// ES6. If it is not an external module, then we'll determine if it is in strict mode or
// not depending on if we see "use strict" in certain places (or if we hit a class/namespace).
let inStrictMode = !!file.externalModuleIndicator;
let inStrictMode: boolean;
let symbolCount = 0;
let Symbol = objectAllocator.getSymbolConstructor();
let classifiableNames: Map<string> = {};
let Symbol: { new (flags: SymbolFlags, name: string): Symbol };
let classifiableNames: Map<string>;
if (!file.locals) {
bind(file);
file.symbolCount = symbolCount;
file.classifiableNames = classifiableNames;
function bindSourceFile(f: SourceFile, opts: CompilerOptions) {
file = f;
options = opts;
inStrictMode = !!file.externalModuleIndicator;
classifiableNames = {};
Symbol = objectAllocator.getSymbolConstructor();
if (!file.locals) {
bind(file);
file.symbolCount = symbolCount;
file.classifiableNames = classifiableNames;
}
file = undefined;
options = undefined;
parent = undefined;
container = undefined;
blockScopeContainer = undefined;
lastContainer = undefined;
seenThisKeyword = false;
hasExplicitReturn = false;
labelStack = undefined;
labelIndexMap = undefined;
implicitLabels = undefined;
}
return;
return bindSourceFile;
function createSymbol(flags: SymbolFlags, name: string): Symbol {
symbolCount++;
@@ -130,9 +177,14 @@ namespace ts {
symbol.members = {};
}
if (symbolFlags & SymbolFlags.Value && !symbol.valueDeclaration) {
symbol.valueDeclaration = node;
}
if (symbolFlags & SymbolFlags.Value) {
const valueDeclaration = symbol.valueDeclaration;
if (!valueDeclaration ||
(valueDeclaration.kind !== node.kind && valueDeclaration.kind === SyntaxKind.ModuleDeclaration)) {
// other kinds of value declarations take precedence over modules
symbol.valueDeclaration = node;
}
}
}
// Should not be called on a declaration with a computed property name,
@@ -143,7 +195,12 @@ namespace ts {
return `"${(<LiteralExpression>node.name).text}"`;
}
if (node.name.kind === SyntaxKind.ComputedPropertyName) {
let nameExpression = (<ComputedPropertyName>node.name).expression;
const nameExpression = (<ComputedPropertyName>node.name).expression;
// treat computed property names where expression is string/numeric literal as just string/numeric literal
if (isStringOrNumericLiteral(nameExpression.kind)) {
return (<LiteralExpression>nameExpression).text;
}
Debug.assert(isWellKnownSymbolSyntactically(nameExpression));
return getPropertyNameForKnownSymbolName((<PropertyAccessExpression>nameExpression).name.text);
}
@@ -164,6 +221,9 @@ namespace ts {
return "__export";
case SyntaxKind.ExportAssignment:
return (<ExportAssignment>node).isExportEquals ? "export=" : "default";
case SyntaxKind.BinaryExpression:
// Binary expression case is for JS module 'module.exports = expr'
return "export=";
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.ClassDeclaration:
return node.flags & NodeFlags.Default ? "default" : undefined;
@@ -185,9 +245,9 @@ namespace ts {
function declareSymbol(symbolTable: SymbolTable, parent: Symbol, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags): Symbol {
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"
let name = isDefaultExport && parent ? "default" : getDeclarationName(node);
const name = isDefaultExport && parent ? "default" : getDeclarationName(node);
let symbol: Symbol;
if (name !== undefined) {
@@ -254,7 +314,7 @@ namespace ts {
}
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 (node.kind === SyntaxKind.ExportSpecifier || (node.kind === SyntaxKind.ImportEqualsDeclaration && hasExportModifier)) {
return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes);
@@ -276,11 +336,11 @@ namespace ts {
// 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.
if (hasExportModifier || container.flags & NodeFlags.ExportContext) {
let exportKind =
const exportKind =
(symbolFlags & SymbolFlags.Value ? SymbolFlags.ExportValue : 0) |
(symbolFlags & SymbolFlags.Type ? SymbolFlags.ExportType : 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);
node.localSymbol = local;
return local;
@@ -298,9 +358,9 @@ namespace ts {
// 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
// these saved values.
let saveParent = parent;
let saveContainer = container;
let savedBlockScopeContainer = blockScopeContainer;
const saveParent = parent;
const saveContainer = container;
const savedBlockScopeContainer = blockScopeContainer;
// This node will now be set as the parent of all of its children as we recurse into them.
parent = node;
@@ -322,7 +382,7 @@ namespace ts {
// 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
// a previous compilation.
let containerFlags = getContainerFlags(node);
const containerFlags = getContainerFlags(node);
if (containerFlags & ContainerFlags.IsContainer) {
container = blockScopeContainer = node;
@@ -338,13 +398,56 @@ namespace ts {
blockScopeContainer.locals = undefined;
}
if (node.kind === SyntaxKind.InterfaceDeclaration) {
let savedReachabilityState: Reachability;
let savedLabelStack: Reachability[];
let savedLabels: Map<number>;
let savedImplicitLabels: number[];
let savedHasExplicitReturn: boolean;
const kind = node.kind;
let flags = node.flags;
// reset all reachability check related flags on node (for incremental scenarios)
flags &= ~NodeFlags.ReachabilityCheckFlags;
if (kind === SyntaxKind.InterfaceDeclaration) {
seenThisKeyword = false;
forEachChild(node, bind);
node.flags = seenThisKeyword ? node.flags | NodeFlags.ContainsThis : node.flags & ~NodeFlags.ContainsThis;
}
else {
forEachChild(node, bind);
const saveState = kind === SyntaxKind.SourceFile || kind === SyntaxKind.ModuleBlock || isFunctionLikeKind(kind);
if (saveState) {
savedReachabilityState = currentReachabilityState;
savedLabelStack = labelStack;
savedLabels = labelIndexMap;
savedImplicitLabels = implicitLabels;
savedHasExplicitReturn = hasExplicitReturn;
currentReachabilityState = Reachability.Reachable;
hasExplicitReturn = false;
labelStack = labelIndexMap = implicitLabels = undefined;
}
bindReachableStatement(node);
if (currentReachabilityState === Reachability.Reachable && isFunctionLikeKind(kind) && nodeIsPresent((<FunctionLikeDeclaration>node).body)) {
flags |= NodeFlags.HasImplicitReturn;
if (hasExplicitReturn) {
flags |= NodeFlags.HasExplicitReturn;
}
}
if (kind === SyntaxKind.InterfaceDeclaration) {
flags = seenThisKeyword ? flags | NodeFlags.ContainsThis : flags & ~NodeFlags.ContainsThis;
}
node.flags = flags;
if (saveState) {
hasExplicitReturn = savedHasExplicitReturn;
currentReachabilityState = savedReachabilityState;
labelStack = savedLabelStack;
labelIndexMap = savedLabels;
implicitLabels = savedImplicitLabels;
}
container = saveContainer;
@@ -352,6 +455,220 @@ namespace ts {
blockScopeContainer = savedBlockScopeContainer;
}
/**
* Returns true if node and its subnodes were successfully traversed.
* Returning false means that node was not examined and caller needs to dive into the node himself.
*/
function bindReachableStatement(node: Node): void {
if (checkUnreachable(node)) {
forEachChild(node, bind);
return;
}
switch (node.kind) {
case SyntaxKind.WhileStatement:
bindWhileStatement(<WhileStatement>node);
break;
case SyntaxKind.DoStatement:
bindDoStatement(<DoStatement>node);
break;
case SyntaxKind.ForStatement:
bindForStatement(<ForStatement>node);
break;
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
bindForInOrForOfStatement(<ForInStatement | ForOfStatement>node);
break;
case SyntaxKind.IfStatement:
bindIfStatement(<IfStatement>node);
break;
case SyntaxKind.ReturnStatement:
case SyntaxKind.ThrowStatement:
bindReturnOrThrow(<ReturnStatement | ThrowStatement>node);
break;
case SyntaxKind.BreakStatement:
case SyntaxKind.ContinueStatement:
bindBreakOrContinueStatement(<BreakOrContinueStatement>node);
break;
case SyntaxKind.TryStatement:
bindTryStatement(<TryStatement>node);
break;
case SyntaxKind.SwitchStatement:
bindSwitchStatement(<SwitchStatement>node);
break;
case SyntaxKind.CaseBlock:
bindCaseBlock(<CaseBlock>node);
break;
case SyntaxKind.LabeledStatement:
bindLabeledStatement(<LabeledStatement>node);
break;
default:
forEachChild(node, bind);
break;
}
}
function bindWhileStatement(n: WhileStatement): void {
const preWhileState =
n.expression.kind === SyntaxKind.FalseKeyword ? Reachability.Unreachable : currentReachabilityState;
const postWhileState =
n.expression.kind === SyntaxKind.TrueKeyword ? Reachability.Unreachable : currentReachabilityState;
// bind expressions (don't affect reachability)
bind(n.expression);
currentReachabilityState = preWhileState;
const postWhileLabel = pushImplicitLabel();
bind(n.statement);
popImplicitLabel(postWhileLabel, postWhileState);
}
function bindDoStatement(n: DoStatement): void {
const preDoState = currentReachabilityState;
const postDoLabel = pushImplicitLabel();
bind(n.statement);
const postDoState = n.expression.kind === SyntaxKind.TrueKeyword ? Reachability.Unreachable : preDoState;
popImplicitLabel(postDoLabel, postDoState);
// bind expressions (don't affect reachability)
bind(n.expression);
}
function bindForStatement(n: ForStatement): void {
const preForState = currentReachabilityState;
const postForLabel = pushImplicitLabel();
// bind expressions (don't affect reachability)
bind(n.initializer);
bind(n.condition);
bind(n.incrementor);
bind(n.statement);
// for statement is considered infinite when it condition is either omitted or is true keyword
// - for(..;;..)
// - for(..;true;..)
const isInfiniteLoop = (!n.condition || n.condition.kind === SyntaxKind.TrueKeyword);
const postForState = isInfiniteLoop ? Reachability.Unreachable : preForState;
popImplicitLabel(postForLabel, postForState);
}
function bindForInOrForOfStatement(n: ForInStatement | ForOfStatement): void {
const preStatementState = currentReachabilityState;
const postStatementLabel = pushImplicitLabel();
// bind expressions (don't affect reachability)
bind(n.initializer);
bind(n.expression);
bind(n.statement);
popImplicitLabel(postStatementLabel, preStatementState);
}
function bindIfStatement(n: IfStatement): void {
// denotes reachability state when entering 'thenStatement' part of the if statement:
// i.e. if condition is false then thenStatement is unreachable
const ifTrueState = n.expression.kind === SyntaxKind.FalseKeyword ? Reachability.Unreachable : currentReachabilityState;
// denotes reachability state when entering 'elseStatement':
// i.e. if condition is true then elseStatement is unreachable
const ifFalseState = n.expression.kind === SyntaxKind.TrueKeyword ? Reachability.Unreachable : currentReachabilityState;
currentReachabilityState = ifTrueState;
// bind expression (don't affect reachability)
bind(n.expression);
bind(n.thenStatement);
if (n.elseStatement) {
const preElseState = currentReachabilityState;
currentReachabilityState = ifFalseState;
bind(n.elseStatement);
currentReachabilityState = or(currentReachabilityState, preElseState);
}
else {
currentReachabilityState = or(currentReachabilityState, ifFalseState);
}
}
function bindReturnOrThrow(n: ReturnStatement | ThrowStatement): void {
// bind expression (don't affect reachability)
bind(n.expression);
if (n.kind === SyntaxKind.ReturnStatement) {
hasExplicitReturn = true;
}
currentReachabilityState = Reachability.Unreachable;
}
function bindBreakOrContinueStatement(n: BreakOrContinueStatement): void {
// call bind on label (don't affect reachability)
bind(n.label);
// for continue case touch label so it will be marked a used
const isValidJump = jumpToLabel(n.label, n.kind === SyntaxKind.BreakStatement ? currentReachabilityState : Reachability.Unreachable);
if (isValidJump) {
currentReachabilityState = Reachability.Unreachable;
}
}
function bindTryStatement(n: TryStatement): void {
// catch\finally blocks has the same reachability as try block
const preTryState = currentReachabilityState;
bind(n.tryBlock);
const postTryState = currentReachabilityState;
currentReachabilityState = preTryState;
bind(n.catchClause);
const postCatchState = currentReachabilityState;
currentReachabilityState = preTryState;
bind(n.finallyBlock);
// post catch/finally state is reachable if
// - post try state is reachable - control flow can fall out of try block
// - post catch state is reachable - control flow can fall out of catch block
currentReachabilityState = or(postTryState, postCatchState);
}
function bindSwitchStatement(n: SwitchStatement): void {
const preSwitchState = currentReachabilityState;
const postSwitchLabel = pushImplicitLabel();
// bind expression (don't affect reachability)
bind(n.expression);
bind(n.caseBlock);
const hasDefault = forEach(n.caseBlock.clauses, c => c.kind === SyntaxKind.DefaultClause);
// post switch state is unreachable if switch is exaustive (has a default case ) and does not have fallthrough from the last case
const postSwitchState = hasDefault && currentReachabilityState !== Reachability.Reachable ? Reachability.Unreachable : preSwitchState;
popImplicitLabel(postSwitchLabel, postSwitchState);
}
function bindCaseBlock(n: CaseBlock): void {
const startState = currentReachabilityState;
for (const clause of n.clauses) {
currentReachabilityState = startState;
bind(clause);
if (clause.statements.length && currentReachabilityState === Reachability.Reachable && options.noFallthroughCasesInSwitch) {
errorOnFirstToken(clause, Diagnostics.Fallthrough_case_in_switch);
}
}
}
function bindLabeledStatement(n: LabeledStatement): void {
// call bind on label (don't affect reachability)
bind(n.label);
const ok = pushNamedLabel(n.label);
bind(n.statement);
if (ok) {
popNamedLabel(n.label, currentReachabilityState);
}
}
function getContainerFlags(node: Node): ContainerFlags {
switch (node.kind) {
case SyntaxKind.ClassExpression:
@@ -488,21 +805,10 @@ namespace ts {
: declareSymbol(file.locals, undefined, node, symbolFlags, symbolExcludes);
}
function isAmbientContext(node: Node): boolean {
while (node) {
if (node.flags & NodeFlags.Ambient) {
return true;
}
node = node.parent;
}
return false;
}
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) {
for (let stat of (<Block>body).statements) {
for (const stat of (<Block>body).statements) {
if (stat.kind === SyntaxKind.ExportDeclaration || stat.kind === SyntaxKind.ExportAssignment) {
return true;
}
@@ -514,7 +820,7 @@ namespace ts {
function setExportContextFlag(node: ModuleDeclaration | SourceFile) {
// A declaration source file or ambient module declaration that contains no export declarations (but possibly regular
// declarations with export modifiers) is an export context in which declarations are implicitly exported.
if (isAmbientContext(node) && !hasExportDeclarations(node)) {
if (isInAmbientContext(node) && !hasExportDeclarations(node)) {
node.flags |= NodeFlags.ExportContext;
}
else {
@@ -528,7 +834,7 @@ namespace ts {
declareSymbolAndAddToSymbolTable(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes);
}
else {
let state = getModuleInstanceState(node);
const state = getModuleInstanceState(node);
if (state === ModuleInstanceState.NonInstantiated) {
declareSymbolAndAddToSymbolTable(node, SymbolFlags.NamespaceModule, SymbolFlags.NamespaceModuleExcludes);
}
@@ -540,7 +846,7 @@ namespace ts {
node.symbol.constEnumOnlyModule = false;
}
else {
let currentModuleIsConstEnumOnly = state === ModuleInstanceState.ConstEnumOnly;
const currentModuleIsConstEnumOnly = state === ModuleInstanceState.ConstEnumOnly;
if (node.symbol.constEnumOnlyModule === undefined) {
// non-merged case - use the current state
node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly;
@@ -561,10 +867,10 @@ namespace ts {
// 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
// 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);
let typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type");
const typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type");
addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral);
typeLiteralSymbol.members = { [symbol.name]: symbol };
}
@@ -576,14 +882,14 @@ namespace ts {
}
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) {
continue;
}
let identifier = <Identifier>prop.name;
const identifier = <Identifier>prop.name;
// 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
@@ -593,18 +899,18 @@ namespace ts {
// c.IsAccessorDescriptor(previous) is true and IsDataDescriptor(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
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.Accessor;
let existingKind = seen[identifier.text];
const existingKind = seen[identifier.text];
if (!existingKind) {
seen[identifier.text] = currentKind;
continue;
}
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,
Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode));
}
@@ -615,7 +921,7 @@ namespace ts {
}
function bindAnonymousDeclaration(node: Declaration, symbolFlags: SymbolFlags, name: string) {
let symbol = createSymbol(symbolFlags, name);
const symbol = createSymbol(symbolFlags, name);
addDeclarationToSymbol(symbol, node, symbolFlags);
}
@@ -694,7 +1000,7 @@ namespace ts {
if (inStrictMode && node.expression.kind === SyntaxKind.Identifier) {
// 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
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));
}
}
@@ -706,11 +1012,11 @@ namespace ts {
function checkStrictModeEvalOrArguments(contextNode: Node, name: Node) {
if (name && name.kind === SyntaxKind.Identifier) {
let identifier = <Identifier>name;
const identifier = <Identifier>name;
if (isEvalOrArgumentsIdentifier(identifier)) {
// We check first if the name is inside class declaration or class expression; if so give explicit 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,
getStrictModeEvalOrArgumentsMessage(contextNode), identifier.text));
}
@@ -766,12 +1072,12 @@ namespace ts {
function checkStrictModeWithStatement(node: WithStatement) {
// Grammar checking for withStatement
if (inStrictMode) {
grammarErrorOnFirstToken(node, Diagnostics.with_statements_are_not_allowed_in_strict_mode);
errorOnFirstToken(node, Diagnostics.with_statements_are_not_allowed_in_strict_mode);
}
}
function grammarErrorOnFirstToken(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any) {
let span = getSpanOfTokenAtPosition(file, node.pos);
function errorOnFirstToken(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any) {
const span = getSpanOfTokenAtPosition(file, node.pos);
file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2));
}
@@ -779,10 +1085,14 @@ namespace ts {
return "__" + indexOf((<SignatureDeclaration>node.parent).parameters, node);
}
function bind(node: Node) {
function bind(node: Node): void {
if (!node) {
return;
}
node.parent = parent;
let savedInStrictMode = inStrictMode;
const savedInStrictMode = inStrictMode;
if (!savedInStrictMode) {
updateStrictMode(node);
}
@@ -828,7 +1138,7 @@ namespace ts {
}
function updateStrictModeStatementList(statements: NodeArray<Statement>) {
for (let statement of statements) {
for (const statement of statements) {
if (!isPrologueDirective(statement)) {
return;
}
@@ -842,7 +1152,7 @@ namespace ts {
/// Should be called only on prologue directives (isPrologueDirective(node) should be true)
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
// string to contain unicode escapes (as per ES5).
@@ -851,9 +1161,18 @@ namespace ts {
function bindWorker(node: Node) {
switch (node.kind) {
/* Strict mode checks */
case SyntaxKind.Identifier:
return checkStrictModeIdentifier(<Identifier>node);
case SyntaxKind.BinaryExpression:
if (isInJavaScriptFile(node)) {
if (isExportsPropertyAssignment(node)) {
bindExportsPropertyAssignment(<BinaryExpression>node);
}
else if (isModuleExportsAssignment(node)) {
bindModuleExportsAssignment(<BinaryExpression>node);
}
}
return checkStrictModeBinaryExpression(<BinaryExpression>node);
case SyntaxKind.CatchClause:
return checkStrictModeCatchClause(<CatchClause>node);
@@ -917,8 +1236,16 @@ namespace ts {
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
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);
case SyntaxKind.CallExpression:
if (isInJavaScriptFile(node)) {
bindCallExpression(<CallExpression>node);
}
break;
// Members of classes, interfaces, and modules
case SyntaxKind.ClassExpression:
case SyntaxKind.ClassDeclaration:
return bindClassLikeDeclaration(<ClassLikeDeclaration>node);
@@ -930,6 +1257,8 @@ namespace ts {
return bindEnumDeclaration(<EnumDeclaration>node);
case SyntaxKind.ModuleDeclaration:
return bindModuleDeclaration(<ModuleDeclaration>node);
// Imports and exports
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.NamespaceImport:
case SyntaxKind.ImportSpecifier:
@@ -949,16 +1278,21 @@ namespace ts {
function bindSourceFileIfExternalModule() {
setExportContextFlag(file);
if (isExternalModule(file)) {
bindAnonymousDeclaration(file, SymbolFlags.ValueModule, `"${removeFileExtension(file.fileName)}"`);
bindSourceFileAsExternalModule();
}
}
function bindExportAssignment(node: ExportAssignment) {
function bindSourceFileAsExternalModule() {
bindAnonymousDeclaration(file, SymbolFlags.ValueModule, `"${removeFileExtension(file.fileName) }"`);
}
function bindExportAssignment(node: ExportAssignment | BinaryExpression) {
const boundExpression = node.kind === SyntaxKind.ExportAssignment ? (<ExportAssignment>node).expression : (<BinaryExpression>node).right;
if (!container.symbol || !container.symbol.exports) {
// Export assignment in some sort of block construct
bindAnonymousDeclaration(node, SymbolFlags.Alias, getDeclarationName(node));
}
else if (node.expression.kind === SyntaxKind.Identifier) {
else if (boundExpression.kind === SyntaxKind.Identifier) {
// An export default clause with an identifier exports all meanings of that identifier
declareSymbol(container.symbol.exports, container.symbol, node, SymbolFlags.Alias, SymbolFlags.PropertyExcludes | SymbolFlags.AliasExcludes);
}
@@ -985,12 +1319,40 @@ namespace ts {
}
}
function setCommonJsModuleIndicator(node: Node) {
if (!file.commonJsModuleIndicator) {
file.commonJsModuleIndicator = node;
bindSourceFileAsExternalModule();
}
}
function bindExportsPropertyAssignment(node: BinaryExpression) {
// When we create a property via 'exports.foo = bar', the 'exports.foo' property access
// expression is the declaration
setCommonJsModuleIndicator(node);
declareSymbol(file.symbol.exports, file.symbol, <PropertyAccessExpression>node.left, SymbolFlags.Property | SymbolFlags.Export, SymbolFlags.None);
}
function bindModuleExportsAssignment(node: BinaryExpression) {
// 'module.exports = expr' assignment
setCommonJsModuleIndicator(node);
bindExportAssignment(node);
}
function bindCallExpression(node: CallExpression) {
// We're only inspecting call expressions to detect CommonJS modules, so we can skip
// this check if we've already seen the module indicator
if (!file.commonJsModuleIndicator && isRequireCall(node)) {
setCommonJsModuleIndicator(node);
}
}
function bindClassLikeDeclaration(node: ClassLikeDeclaration) {
if (node.kind === SyntaxKind.ClassDeclaration) {
bindBlockScopedDeclaration(node, SymbolFlags.Class, SymbolFlags.ClassExcludes);
}
else {
let bindingName = node.name ? node.name.text : "__class";
const bindingName = node.name ? node.name.text : "__class";
bindAnonymousDeclaration(node, SymbolFlags.Class, bindingName);
// Add name of class expression into the map for semantic classifier
if (node.name) {
@@ -998,7 +1360,7 @@ namespace ts {
}
}
let symbol = node.symbol;
const symbol = node.symbol;
// TypeScript 1.0 spec (April 2014): 8.4
// Every class automatically contains a static property member named 'prototype', the
@@ -1009,7 +1371,7 @@ namespace ts {
// 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
// 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 (node.name) {
node.name.parent = node;
@@ -1074,7 +1436,7 @@ namespace ts {
node.parent.kind === SyntaxKind.Constructor &&
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);
}
}
@@ -1084,5 +1446,135 @@ namespace ts {
? bindAnonymousDeclaration(node, symbolFlags, "__computed")
: declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes);
}
// reachability checks
function pushNamedLabel(name: Identifier): boolean {
initializeReachabilityStateIfNecessary();
if (hasProperty(labelIndexMap, name.text)) {
return false;
}
labelIndexMap[name.text] = labelStack.push(Reachability.Unintialized) - 1;
return true;
}
function pushImplicitLabel(): number {
initializeReachabilityStateIfNecessary();
const index = labelStack.push(Reachability.Unintialized) - 1;
implicitLabels.push(index);
return index;
}
function popNamedLabel(label: Identifier, outerState: Reachability): void {
const index = labelIndexMap[label.text];
Debug.assert(index !== undefined);
Debug.assert(labelStack.length == index + 1);
labelIndexMap[label.text] = undefined;
setCurrentStateAtLabel(labelStack.pop(), outerState, label);
}
function popImplicitLabel(implicitLabelIndex: number, outerState: Reachability): void {
if (labelStack.length !== implicitLabelIndex + 1) {
Debug.assert(false, `Label stack: ${labelStack.length}, index:${implicitLabelIndex}`);
}
const i = implicitLabels.pop();
if (implicitLabelIndex !== i) {
Debug.assert(false, `i: ${i}, index: ${implicitLabelIndex}`);
}
setCurrentStateAtLabel(labelStack.pop(), outerState, /*name*/ undefined);
}
function setCurrentStateAtLabel(innerMergedState: Reachability, outerState: Reachability, label: Identifier): void {
if (innerMergedState === Reachability.Unintialized) {
if (label && !options.allowUnusedLabels) {
file.bindDiagnostics.push(createDiagnosticForNode(label, Diagnostics.Unused_label));
}
currentReachabilityState = outerState;
}
else {
currentReachabilityState = or(innerMergedState, outerState);
}
}
function jumpToLabel(label: Identifier, outerState: Reachability): boolean {
initializeReachabilityStateIfNecessary();
const index = label ? labelIndexMap[label.text] : lastOrUndefined(implicitLabels);
if (index === undefined) {
// reference to unknown label or
// break/continue used outside of loops
return false;
}
const stateAtLabel = labelStack[index];
labelStack[index] = stateAtLabel === Reachability.Unintialized ? outerState : or(stateAtLabel, outerState);
return true;
}
function checkUnreachable(node: Node): boolean {
switch (currentReachabilityState) {
case Reachability.Unreachable:
const reportError =
// report error on all statements except empty ones
(isStatement(node) && node.kind !== SyntaxKind.EmptyStatement) ||
// report error on class declarations
node.kind === SyntaxKind.ClassDeclaration ||
// report error on instantiated modules or const-enums only modules if preserveConstEnums is set
(node.kind === SyntaxKind.ModuleDeclaration && shouldReportErrorOnModuleDeclaration(<ModuleDeclaration>node)) ||
// report error on regular enums and const enums if preserveConstEnums is set
(node.kind === SyntaxKind.EnumDeclaration && (!isConstEnumDeclaration(node) || options.preserveConstEnums));
if (reportError) {
currentReachabilityState = Reachability.ReportedUnreachable;
// unreachable code is reported if
// - user has explicitly asked about it AND
// - statement is in not ambient context (statements in ambient context is already an error
// so we should not report extras) AND
// - node is not variable statement OR
// - node is block scoped variable statement OR
// - node is not block scoped variable statement and at least one variable declaration has initializer
// Rationale: we don't want to report errors on non-initialized var's since they are hoisted
// On the other side we do want to report errors on non-initialized 'lets' because of TDZ
const reportUnreachableCode =
!options.allowUnreachableCode &&
!isInAmbientContext(node) &&
(
node.kind !== SyntaxKind.VariableStatement ||
getCombinedNodeFlags((<VariableStatement>node).declarationList) & NodeFlags.BlockScoped ||
forEach((<VariableStatement>node).declarationList.declarations, d => d.initializer)
);
if (reportUnreachableCode) {
errorOnFirstToken(node, Diagnostics.Unreachable_code_detected);
}
}
case Reachability.ReportedUnreachable:
return true;
default:
return false;
}
function shouldReportErrorOnModuleDeclaration(node: ModuleDeclaration): boolean {
const instanceState = getModuleInstanceState(node);
return instanceState === ModuleInstanceState.Instantiated || (instanceState === ModuleInstanceState.ConstEnumOnly && options.preserveConstEnums);
}
}
function initializeReachabilityStateIfNecessary(): void {
if (labelIndexMap) {
return;
}
currentReachabilityState = Reachability.Reachable;
labelIndexMap = {};
labelStack = [];
implicitLabels = [];
}
}
}
+1765 -1489
View File
File diff suppressed because it is too large Load Diff
+88 -28
View File
@@ -1,6 +1,7 @@
/// <reference path="sys.ts"/>
/// <reference path="types.ts"/>
/// <reference path="core.ts"/>
/// <reference path="diagnosticInformationMap.generated.ts"/>
/// <reference path="scanner.ts"/>
namespace ts {
@@ -79,9 +80,9 @@ namespace ts {
"es6": ModuleKind.ES6,
"es2015": ModuleKind.ES2015,
},
description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_system_umd_or_es6,
description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_system_umd_or_es2015,
paramType: Diagnostics.KIND,
error: Diagnostics.Argument_for_module_option_must_be_commonjs_amd_system_umd_or_es6
error: Diagnostics.Argument_for_module_option_must_be_commonjs_amd_system_umd_or_es2015
},
{
name: "newLine",
@@ -150,6 +151,12 @@ namespace ts {
type: "boolean",
description: Diagnostics.Do_not_erase_const_enum_declarations_in_generated_code
},
{
name: "pretty",
paramType: Diagnostics.KIND,
description: Diagnostics.Stylize_errors_and_messages_using_color_and_context_experimental,
type: "boolean"
},
{
name: "project",
shortName: "p",
@@ -212,9 +219,9 @@ namespace ts {
"es6": ScriptTarget.ES6,
"es2015": ScriptTarget.ES2015,
},
description: Diagnostics.Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES6_experimental,
description: Diagnostics.Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES2015_experimental,
paramType: Diagnostics.VERSION,
error: Diagnostics.Argument_for_target_option_must_be_ES3_ES5_or_ES6
error: Diagnostics.Argument_for_target_option_must_be_ES3_ES5_or_ES2015
},
{
name: "version",
@@ -247,6 +254,31 @@ namespace ts {
},
description: Diagnostics.Specifies_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6,
error: Diagnostics.Argument_for_moduleResolution_option_must_be_node_or_classic,
},
{
name: "allowUnusedLabels",
type: "boolean",
description: Diagnostics.Do_not_report_errors_on_unused_labels
},
{
name: "noImplicitReturns",
type: "boolean",
description: Diagnostics.Report_error_when_not_all_code_paths_in_function_return_a_value
},
{
name: "noFallthroughCasesInSwitch",
type: "boolean",
description: Diagnostics.Report_errors_for_fallthrough_cases_in_switch_statement
},
{
name: "allowUnreachableCode",
type: "boolean",
description: Diagnostics.Do_not_report_errors_on_unreachable_code
},
{
name: "forceConsistentCasingInFileNames",
type: "boolean",
description: Diagnostics.Disallow_inconsistently_cased_references_to_the_same_file
}
];
@@ -263,8 +295,8 @@ namespace ts {
return optionNameMapCache;
}
let optionNameMap: Map<CommandLineOption> = {};
let shortOptionNames: Map<string> = {};
const optionNameMap: Map<CommandLineOption> = {};
const shortOptionNames: Map<string> = {};
forEach(optionDeclarations, option => {
optionNameMap[option.name.toLowerCase()] = option;
if (option.shortName) {
@@ -277,10 +309,10 @@ namespace ts {
}
export function parseCommandLine(commandLine: string[], readFile?: (path: string) => string): ParsedCommandLine {
let options: CompilerOptions = {};
let fileNames: string[] = [];
let errors: Diagnostic[] = [];
let { optionNameMap, shortOptionNames } = getOptionNameMap();
const options: CompilerOptions = {};
const fileNames: string[] = [];
const errors: Diagnostic[] = [];
const { optionNameMap, shortOptionNames } = getOptionNameMap();
parseStrings(commandLine);
return {
@@ -305,7 +337,7 @@ namespace ts {
}
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).
if (!args[i] && opt.type !== "boolean") {
@@ -345,19 +377,19 @@ namespace ts {
}
function parseResponseFile(fileName: string) {
let text = readFile ? readFile(fileName) : sys.readFile(fileName);
const text = readFile ? readFile(fileName) : sys.readFile(fileName);
if (!text) {
errors.push(createCompilerDiagnostic(Diagnostics.File_0_not_found, fileName));
return;
}
let args: string[] = [];
const args: string[] = [];
let pos = 0;
while (true) {
while (pos < text.length && text.charCodeAt(pos) <= CharacterCodes.space) pos++;
if (pos >= text.length) break;
let start = pos;
const start = pos;
if (text.charCodeAt(start) === CharacterCodes.doubleQuote) {
pos++;
while (pos < text.length && text.charCodeAt(pos) !== CharacterCodes.doubleQuote) pos++;
@@ -400,13 +432,41 @@ namespace ts {
*/
export function parseConfigFileTextToJson(fileName: string, jsonText: string): { config?: any; error?: Diagnostic } {
try {
return { config: /\S/.test(jsonText) ? JSON.parse(jsonText) : {} };
const jsonTextWithoutComments = removeComments(jsonText);
return { config: /\S/.test(jsonTextWithoutComments) ? JSON.parse(jsonTextWithoutComments) : {} };
}
catch (e) {
return { error: createCompilerDiagnostic(Diagnostics.Failed_to_parse_file_0_Colon_1, fileName, e.message) };
}
}
/**
* Remove the comments from a json like text.
* Comments can be single line comments (starting with # or //) or multiline comments using / * * /
*
* This method replace comment content by whitespace rather than completely remove them to keep positions in json parsing error reporting accurate.
*/
function removeComments(jsonText: string): string {
let output = "";
const scanner = createScanner(ScriptTarget.ES5, /* skipTrivia */ false, LanguageVariant.Standard, jsonText);
let token: SyntaxKind;
while ((token = scanner.scan()) !== SyntaxKind.EndOfFileToken) {
switch (token) {
case SyntaxKind.SingleLineCommentTrivia:
case SyntaxKind.MultiLineCommentTrivia:
// replace comments with whitespace to preserve original character positions
output += scanner.getTokenText().replace(/\S/g, " ");
break;
default:
output += scanner.getTokenText();
break;
}
}
return output;
}
/**
* Parse the contents of a config file (tsconfig.json).
* @param json The contents of the config file to parse
@@ -415,7 +475,7 @@ namespace ts {
* file to. e.g. outDir
*/
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 {
options,
@@ -434,12 +494,12 @@ namespace ts {
}
}
else {
let 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 exclude = json["exclude"] instanceof Array ? map(<string[]>json["exclude"], normalizeSlashes) : undefined;
const sysFiles = host.readDirectory(basePath, ".ts", exclude).concat(host.readDirectory(basePath, ".tsx", exclude));
for (let i = 0; i < sysFiles.length; i++) {
let name = sysFiles[i];
const name = sysFiles[i];
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")) {
fileNames.push(name);
}
@@ -459,24 +519,24 @@ namespace ts {
}
export function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string): { options: CompilerOptions, errors: Diagnostic[] } {
let options: CompilerOptions = {};
let errors: Diagnostic[] = [];
const options: CompilerOptions = {};
const errors: Diagnostic[] = [];
if (!jsonOptions) {
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)) {
let opt = optionNameMap[id];
let optType = opt.type;
const opt = optionNameMap[id];
const optType = opt.type;
let value = jsonOptions[id];
let expectedType = typeof optType === "string" ? optType : "string";
const expectedType = typeof optType === "string" ? optType : "string";
if (typeof value === expectedType) {
if (typeof optType !== "string") {
let key = value.toLowerCase();
const key = value.toLowerCase();
if (hasProperty(optType, key)) {
value = optType[key];
}
+107 -103
View File
@@ -17,45 +17,55 @@ namespace ts {
True = -1
}
export function createFileMap<T>(getCanonicalFileName: (fileName: string) => string): FileMap<T> {
export function createFileMap<T>(keyMapper?: (key: string) => string): FileMap<T> {
let files: Map<T> = {};
return {
get,
set,
contains,
remove,
clear,
forEachValue: forEachValueInMap
forEachValue: forEachValueInMap,
clear
};
function set(fileName: string, value: T) {
files[normalizeKey(fileName)] = value;
function forEachValueInMap(f: (key: Path, value: T) => void) {
for (const key in files) {
f(<Path>key, files[key]);
}
}
function get(fileName: string) {
return files[normalizeKey(fileName)];
// path should already be well-formed so it does not need to be normalized
function get(path: Path): T {
return files[toKey(path)];
}
function contains(fileName: string) {
return hasProperty(files, normalizeKey(fileName));
function set(path: Path, value: T) {
files[toKey(path)] = value;
}
function remove (fileName: string) {
let key = normalizeKey(fileName);
function contains(path: Path) {
return hasProperty(files, toKey(path));
}
function remove(path: Path) {
const key = toKey(path);
delete files[key];
}
function forEachValueInMap(f: (value: T) => void) {
forEachValue(files, f);
}
function normalizeKey(key: string) {
return getCanonicalFileName(normalizeSlashes(key));
}
function clear() {
files = {};
}
function toKey(path: Path): string {
return keyMapper ? keyMapper(path) : path;
}
}
export function toPath(fileName: string, basePath: string, getCanonicalFileName: (path: string) => string): Path {
const nonCanonicalizedPath = isRootedDiskPath(fileName)
? normalizePath(fileName)
: getNormalizedAbsolutePath(fileName, basePath);
return <Path>getCanonicalFileName(nonCanonicalizedPath);
}
export const enum Comparison {
@@ -74,7 +84,7 @@ namespace ts {
export function forEach<T, U>(array: T[], callback: (element: T, index: number) => U): U {
if (array) {
for (let i = 0, len = array.length; i < len; i++) {
let result = callback(array[i], i);
const result = callback(array[i], i);
if (result) {
return result;
}
@@ -85,7 +95,7 @@ namespace ts {
export function contains<T>(array: T[], value: T): boolean {
if (array) {
for (let v of array) {
for (const v of array) {
if (v === value) {
return true;
}
@@ -108,7 +118,7 @@ namespace ts {
export function countWhere<T>(array: T[], predicate: (x: T) => boolean): number {
let count = 0;
if (array) {
for (let v of array) {
for (const v of array) {
if (predicate(v)) {
count++;
}
@@ -121,7 +131,7 @@ namespace ts {
let result: T[];
if (array) {
result = [];
for (let item of array) {
for (const item of array) {
if (f(item)) {
result.push(item);
}
@@ -134,7 +144,7 @@ namespace ts {
let result: U[];
if (array) {
result = [];
for (let v of array) {
for (const v of array) {
result.push(f(v));
}
}
@@ -152,7 +162,7 @@ namespace ts {
let result: T[];
if (array) {
result = [];
for (let item of array) {
for (const item of array) {
if (!contains(result, item)) {
result.push(item);
}
@@ -163,7 +173,7 @@ namespace ts {
export function sum(array: any[], prop: string): number {
let result = 0;
for (let v of array) {
for (const v of array) {
result += v[prop];
}
return result;
@@ -171,7 +181,7 @@ namespace ts {
export function addRange<T>(to: T[], from: T[]): void {
if (to && from) {
for (let v of from) {
for (const v of from) {
to.push(v);
}
}
@@ -210,8 +220,8 @@ namespace ts {
let high = array.length - 1;
while (low <= high) {
let middle = low + ((high - low) >> 1);
let midValue = array[middle];
const middle = low + ((high - low) >> 1);
const midValue = array[middle];
if (midValue === value) {
return middle;
@@ -260,7 +270,7 @@ namespace ts {
return initial;
}
let hasOwnProperty = Object.prototype.hasOwnProperty;
const hasOwnProperty = Object.prototype.hasOwnProperty;
export function hasProperty<T>(map: Map<T>, key: string): boolean {
return hasOwnProperty.call(map, key);
@@ -271,7 +281,7 @@ namespace ts {
}
export function isEmpty<T>(map: Map<T>) {
for (let id in map) {
for (const id in map) {
if (hasProperty(map, id)) {
return false;
}
@@ -280,19 +290,19 @@ namespace ts {
}
export function clone<T>(object: T): T {
let result: any = {};
for (let id in object) {
const result: any = {};
for (const id in object) {
result[id] = (<any>object)[id];
}
return <T>result;
}
export function extend<T1, T2>(first: Map<T1>, second: Map<T2>): Map<T1 & T2> {
let result: Map<T1 & T2> = {};
for (let id in first) {
const result: Map<T1 & T2> = {};
for (const id in first) {
(result as any)[id] = first[id];
}
for (let id in second) {
for (const id in second) {
if (!hasProperty(result, id)) {
(result as any)[id] = second[id];
}
@@ -302,7 +312,7 @@ namespace ts {
export function forEachValue<T, U>(map: Map<T>, callback: (value: T) => U): U {
let result: U;
for (let id in map) {
for (const id in map) {
if (result = callback(map[id])) break;
}
return result;
@@ -310,7 +320,7 @@ namespace ts {
export function forEachKey<T, U>(map: Map<T>, callback: (key: string) => U): U {
let result: U;
for (let id in map) {
for (const id in map) {
if (result = callback(id)) break;
}
return result;
@@ -321,7 +331,7 @@ namespace ts {
}
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];
}
}
@@ -337,7 +347,7 @@ namespace ts {
* 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> {
let result: Map<T> = {};
const result: Map<T> = {};
forEach(array, value => {
result[makeKey(value)] = value;
@@ -365,15 +375,15 @@ namespace ts {
export let localizedDiagnosticMessages: Map<string> = undefined;
export function getLocaleSpecificMessage(message: string) {
return localizedDiagnosticMessages && localizedDiagnosticMessages[message]
? localizedDiagnosticMessages[message]
: message;
export function getLocaleSpecificMessage(message: DiagnosticMessage) {
return localizedDiagnosticMessages && localizedDiagnosticMessages[message.key]
? localizedDiagnosticMessages[message.key]
: message.message;
}
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 {
let end = start + length;
const end = start + length;
Debug.assert(start >= 0, "start must be non-negative, is " + start);
Debug.assert(length >= 0, "length must be non-negative, is " + length);
@@ -383,7 +393,7 @@ namespace ts {
Debug.assert(end <= file.text.length, `end must be the bounds of the file. ${ end } > ${ file.text.length }`);
}
let text = getLocaleSpecificMessage(message.key);
let text = getLocaleSpecificMessage(message);
if (arguments.length > 4) {
text = formatStringFromArgs(text, arguments, 4);
@@ -402,7 +412,7 @@ namespace ts {
export function createCompilerDiagnostic(message: DiagnosticMessage, ...args: any[]): Diagnostic;
export function createCompilerDiagnostic(message: DiagnosticMessage): Diagnostic {
let text = getLocaleSpecificMessage(message.key);
let text = getLocaleSpecificMessage(message);
if (arguments.length > 1) {
text = formatStringFromArgs(text, arguments, 1);
@@ -421,7 +431,7 @@ namespace ts {
export function chainDiagnosticMessages(details: DiagnosticMessageChain, message: DiagnosticMessage, ...args: any[]): DiagnosticMessageChain;
export function chainDiagnosticMessages(details: DiagnosticMessageChain, message: DiagnosticMessage): DiagnosticMessageChain {
let text = getLocaleSpecificMessage(message.key);
let text = getLocaleSpecificMessage(message);
if (arguments.length > 2) {
text = formatStringFromArgs(text, arguments, 2);
@@ -469,10 +479,10 @@ namespace ts {
function compareMessageText(text1: string | DiagnosticMessageChain, text2: string | DiagnosticMessageChain): Comparison {
while (text1 && text2) {
// We still have both chains.
let string1 = typeof text1 === "string" ? text1 : text1.messageText;
let string2 = typeof text2 === "string" ? text2 : text2.messageText;
const string1 = typeof text1 === "string" ? text1 : text1.messageText;
const string2 = typeof text2 === "string" ? text2 : text2.messageText;
let res = compareValues(string1, string2);
const res = compareValues(string1, string2);
if (res) {
return res;
}
@@ -499,11 +509,11 @@ namespace ts {
return diagnostics;
}
let newDiagnostics = [diagnostics[0]];
const newDiagnostics = [diagnostics[0]];
let previousDiagnostic = diagnostics[0];
for (let i = 1; i < diagnostics.length; i++) {
let currentDiagnostic = diagnostics[i];
let isDupe = compareDiagnostics(currentDiagnostic, previousDiagnostic) === Comparison.EqualTo;
const currentDiagnostic = diagnostics[i];
const isDupe = compareDiagnostics(currentDiagnostic, previousDiagnostic) === Comparison.EqualTo;
if (!isDupe) {
newDiagnostics.push(currentDiagnostic);
previousDiagnostic = currentDiagnostic;
@@ -521,9 +531,9 @@ namespace ts {
export function getRootLength(path: string): number {
if (path.charCodeAt(0) === CharacterCodes.slash) {
if (path.charCodeAt(1) !== CharacterCodes.slash) return 1;
let p1 = path.indexOf("/", 2);
const p1 = path.indexOf("/", 2);
if (p1 < 0) return 2;
let p2 = path.indexOf("/", p1 + 1);
const p2 = path.indexOf("/", p1 + 1);
if (p2 < 0) return p1 + 1;
return p2 + 1;
}
@@ -539,7 +549,7 @@ namespace ts {
if (path.lastIndexOf("file:///", 0) === 0) {
return "file:///".length;
}
let idx = path.indexOf("://");
const idx = path.indexOf("://");
if (idx !== -1) {
return idx + "://".length;
}
@@ -548,9 +558,9 @@ namespace ts {
export let directorySeparator = "/";
function getNormalizedParts(normalizedSlashedPath: string, rootLength: number) {
let parts = normalizedSlashedPath.substr(rootLength).split(directorySeparator);
let normalized: string[] = [];
for (let part of parts) {
const parts = normalizedSlashedPath.substr(rootLength).split(directorySeparator);
const normalized: string[] = [];
for (const part of parts) {
if (part !== ".") {
if (part === ".." && normalized.length > 0 && lastOrUndefined(normalized) !== "..") {
normalized.pop();
@@ -570,8 +580,8 @@ namespace ts {
export function normalizePath(path: string): string {
path = normalizeSlashes(path);
let rootLength = getRootLength(path);
let normalized = getNormalizedParts(path, rootLength);
const rootLength = getRootLength(path);
const normalized = getNormalizedParts(path, rootLength);
return path.substr(0, rootLength) + normalized.join(directorySeparator);
}
@@ -588,7 +598,7 @@ namespace ts {
}
function normalizedPathComponents(path: string, rootLength: number) {
let normalizedParts = getNormalizedParts(path, rootLength);
const normalizedParts = getNormalizedParts(path, rootLength);
return [path.substr(0, rootLength)].concat(normalizedParts);
}
@@ -619,7 +629,7 @@ namespace ts {
// In this example the root is: http://www.website.com/
// 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
let rootLength = url.indexOf("://") + "://".length;
while (rootLength < urlLength) {
@@ -640,7 +650,7 @@ namespace ts {
}
// 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) {
// 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
@@ -666,8 +676,8 @@ namespace ts {
}
export function getRelativePathToDirectoryOrUrl(directoryPathOrUrl: string, relativeOrAbsolutePath: string, currentDirectory: string, getCanonicalFileName: (fileName: string) => string, isAbsolutePathAnUrl: boolean) {
let pathComponents = getNormalizedPathOrUrlComponents(relativeOrAbsolutePath, currentDirectory);
let directoryComponents = getNormalizedPathOrUrlComponents(directoryPathOrUrl, currentDirectory);
const pathComponents = getNormalizedPathOrUrlComponents(relativeOrAbsolutePath, currentDirectory);
const directoryComponents = getNormalizedPathOrUrlComponents(directoryPathOrUrl, currentDirectory);
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
// that is ["test", "cases", ""] needs to be actually ["test", "cases"]
@@ -684,7 +694,7 @@ namespace ts {
// Get the relative path
if (joinStartIndex) {
let relativePath = "";
let relativePathComponents = pathComponents.slice(joinStartIndex, pathComponents.length);
const relativePathComponents = pathComponents.slice(joinStartIndex, pathComponents.length);
for (; joinStartIndex < directoryComponents.length; joinStartIndex++) {
if (directoryComponents[joinStartIndex] !== "") {
relativePath = relativePath + ".." + directorySeparator;
@@ -707,7 +717,7 @@ namespace ts {
if (!path) {
return undefined;
}
let i = path.lastIndexOf(directorySeparator);
const i = path.lastIndexOf(directorySeparator);
return i < 0 ? path : path.substring(i + 1);
}
@@ -720,8 +730,8 @@ namespace ts {
}
export function fileExtensionIs(path: string, extension: string): boolean {
let pathLen = path.length;
let extLen = extension.length;
const pathLen = path.length;
const extLen = extension.length;
return pathLen > extLen && path.substr(pathLen - extLen, extLen) === extension;
}
@@ -729,17 +739,12 @@ namespace ts {
* List of supported extensions in order of file resolution precedence.
*/
export const supportedExtensions = [".ts", ".tsx", ".d.ts"];
/**
* List of extensions that will be used to look for external modules.
* This list is kept separate from supportedExtensions to for cases when we'll allow to include .js files in compilation,
* but still would like to load only TypeScript files as modules
*/
export const moduleFileExtensions = supportedExtensions;
export const supportedJsExtensions = supportedExtensions.concat(".js", ".jsx");
export function isSupportedSourceFileName(fileName: string) {
if (!fileName) { return false; }
for (let extension of supportedExtensions) {
for (const extension of supportedExtensions) {
if (fileExtensionIs(fileName, extension)) {
return true;
}
@@ -749,7 +754,7 @@ namespace ts {
const extensionsToRemove = [".d.ts", ".ts", ".js", ".tsx", ".jsx"];
export function removeFileExtension(path: string): string {
for (let ext of extensionsToRemove) {
for (const ext of extensionsToRemove) {
if (fileExtensionIs(path, ext)) {
return path.substr(0, path.length - ext.length);
}
@@ -757,9 +762,9 @@ namespace ts {
return path;
}
let backslashOrDoubleQuote = /[\"\\]/g;
let escapedCharsRegExp = /[\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
let escapedCharsMap: Map<string> = {
const backslashOrDoubleQuote = /[\"\\]/g;
const escapedCharsRegExp = /[\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
const escapedCharsMap: Map<string> = {
"\0": "\\0",
"\t": "\\t",
"\v": "\\v",
@@ -775,7 +780,8 @@ namespace ts {
};
export interface ObjectAllocator {
getNodeConstructor(kind: SyntaxKind): new () => 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;
getTypeConstructor(): new (checker: TypeChecker, flags: TypeFlags) => Type;
getSignatureConstructor(): new (checker: TypeChecker) => Signature;
@@ -794,19 +800,17 @@ namespace ts {
function Signature(checker: TypeChecker) {
}
function Node(kind: SyntaxKind, pos: number, end: number) {
this.kind = kind;
this.pos = pos;
this.end = end;
this.flags = NodeFlags.None;
this.parent = undefined;
}
export let objectAllocator: ObjectAllocator = {
getNodeConstructor: kind => {
function Node() {
}
Node.prototype = {
kind: kind,
pos: -1,
end: -1,
flags: 0,
parent: undefined,
};
return <any>Node;
},
getNodeConstructor: () => <any>Node,
getSourceFileConstructor: () => <any>Node,
getSymbolConstructor: () => <any>Symbol,
getTypeConstructor: () => <any>Type,
getSignatureConstructor: () => <any>Signature
@@ -820,7 +824,7 @@ namespace ts {
}
export namespace Debug {
let currentAssertionLevel = AssertionLevel.None;
const currentAssertionLevel = AssertionLevel.None;
export function shouldAssert(level: AssertionLevel): boolean {
return currentAssertionLevel >= level;
@@ -832,23 +836,23 @@ namespace ts {
if (verboseDebugInfo) {
verboseDebugString = "\r\nVerbose Debug Information: " + verboseDebugInfo();
}
debugger;
throw new Error("Debug Failure. False expression: " + (message || "") + verboseDebugString);
}
}
export function fail(message?: string): void {
Debug.assert(false, message);
Debug.assert(/*expression*/ false, message);
}
}
export function copyListRemovingItem<T>(item: T, list: T[]) {
let copiedList: T[] = [];
for (var i = 0, len = list.length; i < len; i++) {
if (list[i] !== item) {
copiedList.push(list[i]);
const copiedList: T[] = [];
for (const e of list) {
if (e !== item) {
copiedList.push(e);
}
}
return copiedList;
}
}
}
+146 -91
View File
@@ -31,30 +31,34 @@ namespace ts {
}
export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, targetSourceFile: SourceFile): Diagnostic[] {
let diagnostics: Diagnostic[] = [];
let jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, host, ".js");
const diagnostics: Diagnostic[] = [];
const jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, host, ".js");
emitDeclarations(host, resolver, diagnostics, jsFilePath, targetSourceFile);
return diagnostics;
}
function emitDeclarations(host: EmitHost, resolver: EmitResolver, diagnostics: Diagnostic[], jsFilePath: string, root?: SourceFile): DeclarationEmit {
let newLine = host.getNewLine();
let compilerOptions = host.getCompilerOptions();
const newLine = host.getNewLine();
const compilerOptions = host.getCompilerOptions();
let write: (s: string) => void;
let writeLine: () => void;
let increaseIndent: () => void;
let decreaseIndent: () => void;
let writeTextOfNode: (sourceFile: SourceFile, node: Node) => void;
let writeTextOfNode: (text: string, node: Node) => void;
let writer = createAndSetNewTextWriterWithSymbolWriter();
let enclosingDeclaration: Node;
let currentSourceFile: SourceFile;
let currentText: string;
let currentLineMap: number[];
let currentIdentifiers: Map<string>;
let isCurrentFileExternalModule: boolean;
let reportedDeclarationError = false;
let errorNameNode: DeclarationName;
let emitJsDocComments = compilerOptions.removeComments ? function (declaration: Node) { } : writeJsDocComments;
let emit = compilerOptions.stripInternal ? stripInternal : emitNode;
const emitJsDocComments = compilerOptions.removeComments ? function (declaration: Node) { } : writeJsDocComments;
const emit = compilerOptions.stripInternal ? stripInternal : emitNode;
let noDeclare = !root;
let moduleElementDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[] = [];
let asynchronousSubModuleDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[];
@@ -69,7 +73,7 @@ namespace ts {
if (!compilerOptions.noResolve) {
let addedGlobalFileReference = false;
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
if (referencedFile && ((referencedFile.flags & NodeFlags.DeclarationFile) || // This is a declare file reference
@@ -88,7 +92,7 @@ namespace ts {
// create asynchronous output for the importDeclarations
if (moduleElementDeclarationEmitInfo.length) {
let oldWriter = writer;
const oldWriter = writer;
forEach(moduleElementDeclarationEmitInfo, aliasEmitInfo => {
if (aliasEmitInfo.isVisible) {
Debug.assert(aliasEmitInfo.node.kind === SyntaxKind.ImportDeclaration);
@@ -103,16 +107,17 @@ namespace ts {
}
else {
// Emit references corresponding to this file
let emittedReferencedFiles: SourceFile[] = [];
const emittedReferencedFiles: SourceFile[] = [];
let prevModuleElementDeclarationEmitInfo: ModuleElementDeclarationEmitInfo[] = [];
forEach(host.getSourceFiles(), sourceFile => {
if (!isExternalModuleOrDeclarationFile(sourceFile)) {
if (!isDeclarationFile(sourceFile)) {
// Check what references need to be added
if (!compilerOptions.noResolve) {
forEach(sourceFile.referencedFiles, fileReference => {
let referencedFile = tryResolveScriptReference(host, sourceFile, fileReference);
const referencedFile = tryResolveScriptReference(host, sourceFile, fileReference);
// If the reference file is a declaration file or an external module, emit that reference
if (referencedFile && (isExternalModuleOrDeclarationFile(referencedFile) &&
// If the reference file is a declaration file, emit that reference
if (referencedFile && (isDeclarationFile(referencedFile) &&
!contains(emittedReferencedFiles, referencedFile))) { // If the file reference was not already emitted
writeReferencePath(referencedFile);
@@ -120,10 +125,43 @@ namespace ts {
}
});
}
}
if (!isExternalModuleOrDeclarationFile(sourceFile)) {
noDeclare = false;
emitSourceFile(sourceFile);
}
else if (isExternalModule(sourceFile)) {
noDeclare = true;
write(`declare module "${getResolvedExternalModuleName(host, sourceFile)}" {`);
writeLine();
increaseIndent();
emitSourceFile(sourceFile);
decreaseIndent();
write("}");
writeLine();
// create asynchronous output for the importDeclarations
if (moduleElementDeclarationEmitInfo.length) {
const oldWriter = writer;
forEach(moduleElementDeclarationEmitInfo, aliasEmitInfo => {
if (aliasEmitInfo.isVisible && !aliasEmitInfo.asynchronousOutput) {
Debug.assert(aliasEmitInfo.node.kind === SyntaxKind.ImportDeclaration);
createAndSetNewTextWriterWithSymbolWriter();
Debug.assert(aliasEmitInfo.indent === 1);
increaseIndent();
writeImportDeclaration(<ImportDeclaration>aliasEmitInfo.node);
aliasEmitInfo.asynchronousOutput = writer.getText();
decreaseIndent();
}
});
setWriter(oldWriter);
}
prevModuleElementDeclarationEmitInfo = prevModuleElementDeclarationEmitInfo.concat(moduleElementDeclarationEmitInfo);
moduleElementDeclarationEmitInfo = [];
}
});
moduleElementDeclarationEmitInfo = moduleElementDeclarationEmitInfo.concat(prevModuleElementDeclarationEmitInfo);
}
return {
@@ -134,14 +172,13 @@ namespace ts {
};
function hasInternalAnnotation(range: CommentRange) {
let text = currentSourceFile.text;
let comment = text.substring(range.pos, range.end);
const comment = currentText.substring(range.pos, range.end);
return comment.indexOf("@internal") >= 0;
}
function stripInternal(node: Node) {
if (node) {
let leadingCommentRanges = getLeadingCommentRanges(currentSourceFile.text, node.pos);
const leadingCommentRanges = getLeadingCommentRanges(currentText, node.pos);
if (forEach(leadingCommentRanges, hasInternalAnnotation)) {
return;
}
@@ -151,7 +188,7 @@ namespace ts {
}
function createAndSetNewTextWriterWithSymbolWriter(): EmitTextWriterWithSymbolWriter {
let writer = <EmitTextWriterWithSymbolWriter>createTextWriter(newLine);
const writer = <EmitTextWriterWithSymbolWriter>createTextWriter(newLine);
writer.trackSymbol = trackSymbol;
writer.reportInaccessibleThisError = reportInaccessibleThisError;
writer.writeKeyword = writer.write;
@@ -175,7 +212,7 @@ namespace ts {
}
function writeAsynchronousModuleElements(nodes: Node[]) {
let oldWriter = writer;
const oldWriter = writer;
forEach(nodes, declaration => {
let nodeToCheck: Node;
if (declaration.kind === SyntaxKind.VariableDeclaration) {
@@ -238,12 +275,12 @@ namespace ts {
else {
// Report error
reportedDeclarationError = true;
let errorInfo = writer.getSymbolAccessibilityDiagnostic(symbolAccesibilityResult);
const errorInfo = writer.getSymbolAccessibilityDiagnostic(symbolAccesibilityResult);
if (errorInfo) {
if (errorInfo.typeName) {
diagnostics.push(createDiagnosticForNode(symbolAccesibilityResult.errorNode || errorInfo.errorNode,
errorInfo.diagnosticMessage,
getSourceTextOfNodeFromSourceFile(currentSourceFile, errorInfo.typeName),
getTextOfNodeFromSourceText(currentText, errorInfo.typeName),
symbolAccesibilityResult.errorSymbolName,
symbolAccesibilityResult.errorModuleName));
}
@@ -297,14 +334,14 @@ namespace ts {
}
function emitLines(nodes: Node[]) {
for (let node of nodes) {
for (const node of nodes) {
emit(node);
}
}
function emitSeparatedList(nodes: Node[], separator: string, eachNodeEmitFn: (node: Node) => void, canEmitFn?: (node: Node) => boolean) {
let currentWriterPos = writer.getTextPos();
for (let node of nodes) {
for (const node of nodes) {
if (!canEmitFn || canEmitFn(node)) {
if (currentWriterPos !== writer.getTextPos()) {
write(separator);
@@ -321,10 +358,10 @@ namespace ts {
function writeJsDocComments(declaration: Node) {
if (declaration) {
let jsDocComments = getJsDocComments(declaration, currentSourceFile);
emitNewLineBeforeLeadingComments(currentSourceFile, writer, declaration, jsDocComments);
const jsDocComments = getJsDocCommentsFromText(declaration, currentText);
emitNewLineBeforeLeadingComments(currentLineMap, writer, declaration, jsDocComments);
// 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);
}
}
@@ -343,7 +380,7 @@ namespace ts {
case SyntaxKind.VoidKeyword:
case SyntaxKind.ThisKeyword:
case SyntaxKind.StringLiteral:
return writeTextOfNode(currentSourceFile, type);
return writeTextOfNode(currentText, type);
case SyntaxKind.ExpressionWithTypeArguments:
return emitExpressionWithTypeArguments(<ExpressionWithTypeArguments>type);
case SyntaxKind.TypeReference:
@@ -375,19 +412,19 @@ namespace ts {
function writeEntityName(entityName: EntityName | Expression) {
if (entityName.kind === SyntaxKind.Identifier) {
writeTextOfNode(currentSourceFile, entityName);
writeTextOfNode(currentText, entityName);
}
else {
let left = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).left : (<PropertyAccessExpression>entityName).expression;
let right = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).right : (<PropertyAccessExpression>entityName).name;
const left = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).left : (<PropertyAccessExpression>entityName).expression;
const right = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).right : (<PropertyAccessExpression>entityName).name;
writeEntityName(left);
write(".");
writeTextOfNode(currentSourceFile, right);
writeTextOfNode(currentText, right);
}
}
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
entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration ? entityName.parent : enclosingDeclaration);
@@ -417,7 +454,7 @@ namespace ts {
}
function emitTypePredicate(type: TypePredicateNode) {
writeTextOfNode(currentSourceFile, type.parameterName);
writeTextOfNode(currentText, type.parameterName);
write(" is ");
emitType(type.type);
}
@@ -466,8 +503,12 @@ namespace ts {
}
function emitSourceFile(node: SourceFile) {
currentSourceFile = node;
currentText = node.text;
currentLineMap = getLineStarts(node);
currentIdentifiers = node.identifiers;
isCurrentFileExternalModule = isExternalModule(node);
enclosingDeclaration = node;
emitDetachedComments(currentText, currentLineMap, writer, writeCommentRange, node, newLine, true /* remove comments */);
emitLines(node.statements);
}
@@ -476,14 +517,14 @@ namespace ts {
// 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.
function getExportDefaultTempVariableName(): string {
let baseName = "_default";
if (!hasProperty(currentSourceFile.identifiers, baseName)) {
const baseName = "_default";
if (!hasProperty(currentIdentifiers, baseName)) {
return baseName;
}
let count = 0;
while (true) {
let name = baseName + "_" + (++count);
if (!hasProperty(currentSourceFile.identifiers, name)) {
const name = baseName + "_" + (++count);
if (!hasProperty(currentIdentifiers, name)) {
return name;
}
}
@@ -492,11 +533,11 @@ namespace ts {
function emitExportAssignment(node: ExportAssignment) {
if (node.expression.kind === SyntaxKind.Identifier) {
write(node.isExportEquals ? "export = " : "export default ");
writeTextOfNode(currentSourceFile, node.expression);
writeTextOfNode(currentText, node.expression);
}
else {
// Expression
let tempVarName = getExportDefaultTempVariableName();
const tempVarName = getExportDefaultTempVariableName();
write("declare var ");
write(tempVarName);
write(": ");
@@ -512,7 +553,7 @@ namespace ts {
// Make all the declarations visible for the export name
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
writeAsynchronousModuleElements(nodes);
@@ -536,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
else if (node.kind === SyntaxKind.ImportEqualsDeclaration ||
(node.parent.kind === SyntaxKind.SourceFile && isExternalModule(currentSourceFile))) {
(node.parent.kind === SyntaxKind.SourceFile && isCurrentFileExternalModule)) {
let isVisible: boolean;
if (asynchronousSubModuleDeclarationEmitInfo && node.parent.kind !== SyntaxKind.SourceFile) {
// Import declaration of another module that is visited async so lets put it in right spot
@@ -549,7 +590,7 @@ namespace ts {
}
else {
if (node.kind === SyntaxKind.ImportDeclaration) {
let importDeclaration = <ImportDeclaration>node;
const importDeclaration = <ImportDeclaration>node;
if (importDeclaration.importClause) {
isVisible = (importDeclaration.importClause.name && resolver.isDeclarationVisible(importDeclaration.importClause)) ||
isVisibleNamedBinding(importDeclaration.importClause.namedBindings);
@@ -592,7 +633,7 @@ namespace ts {
function emitModuleElementDeclarationFlags(node: Node) {
// 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 (node.flags & NodeFlags.Export) {
write("export ");
@@ -601,7 +642,7 @@ namespace ts {
if (node.flags & NodeFlags.Default) {
write("default ");
}
else if (node.kind !== SyntaxKind.InterfaceDeclaration) {
else if (node.kind !== SyntaxKind.InterfaceDeclaration && !noDeclare) {
write("declare ");
}
}
@@ -631,7 +672,7 @@ namespace ts {
write("export ");
}
write("import ");
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
write(" = ");
if (isInternalModuleImportEqualsDeclaration(node)) {
emitTypeWithNewGetSymbolAccessibilityDiagnostic(<EntityName>node.moduleReference, getImportEntityNameVisibilityError);
@@ -639,7 +680,7 @@ namespace ts {
}
else {
write("require(");
writeTextOfNode(currentSourceFile, getExternalModuleImportEqualsDeclarationExpression(node));
writeTextOfNode(currentText, getExternalModuleImportEqualsDeclarationExpression(node));
write(");");
}
writer.writeLine();
@@ -675,9 +716,9 @@ namespace ts {
}
write("import ");
if (node.importClause) {
let currentWriterPos = writer.getTextPos();
const currentWriterPos = writer.getTextPos();
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 (currentWriterPos !== writer.getTextPos()) {
@@ -686,7 +727,7 @@ namespace ts {
}
if (node.importClause.namedBindings.kind === SyntaxKind.NamespaceImport) {
write("* as ");
writeTextOfNode(currentSourceFile, (<NamespaceImport>node.importClause.namedBindings).name);
writeTextOfNode(currentText, (<NamespaceImport>node.importClause.namedBindings).name);
}
else {
write("{ ");
@@ -696,24 +737,38 @@ namespace ts {
}
write(" from ");
}
writeTextOfNode(currentSourceFile, node.moduleSpecifier);
emitExternalModuleSpecifier(node.moduleSpecifier);
write(";");
writer.writeLine();
}
function emitExternalModuleSpecifier(moduleSpecifier: Expression) {
if (moduleSpecifier.kind === SyntaxKind.StringLiteral && (!root) && (compilerOptions.out || compilerOptions.outFile)) {
const moduleName = getExternalModuleNameFromDeclaration(host, resolver, moduleSpecifier.parent as (ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration));
if (moduleName) {
write("\"");
write(moduleName);
write("\"");
return;
}
}
writeTextOfNode(currentText, moduleSpecifier);
}
function emitImportOrExportSpecifier(node: ImportOrExportSpecifier) {
if (node.propertyName) {
writeTextOfNode(currentSourceFile, node.propertyName);
writeTextOfNode(currentText, node.propertyName);
write(" as ");
}
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
}
function emitExportSpecifier(node: ExportSpecifier) {
emitImportOrExportSpecifier(node);
// 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
writeAsynchronousModuleElements(nodes);
@@ -732,7 +787,7 @@ namespace ts {
}
if (node.moduleSpecifier) {
write(" from ");
writeTextOfNode(currentSourceFile, node.moduleSpecifier);
emitExternalModuleSpecifier(node.moduleSpecifier);
}
write(";");
writer.writeLine();
@@ -747,13 +802,13 @@ namespace ts {
else {
write("module ");
}
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
while (node.body.kind !== SyntaxKind.ModuleBlock) {
node = <ModuleDeclaration>node.body;
write(".");
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
}
let prevEnclosingDeclaration = enclosingDeclaration;
const prevEnclosingDeclaration = enclosingDeclaration;
enclosingDeclaration = node;
write(" {");
writeLine();
@@ -766,12 +821,12 @@ namespace ts {
}
function writeTypeAliasDeclaration(node: TypeAliasDeclaration) {
let prevEnclosingDeclaration = enclosingDeclaration;
const prevEnclosingDeclaration = enclosingDeclaration;
enclosingDeclaration = node;
emitJsDocComments(node);
emitModuleElementDeclarationFlags(node);
write("type ");
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
emitTypeParameters(node.typeParameters);
write(" = ");
emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError);
@@ -795,7 +850,7 @@ namespace ts {
write("const ");
}
write("enum ");
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
write(" {");
writeLine();
increaseIndent();
@@ -807,8 +862,8 @@ namespace ts {
function emitEnumMemberDeclaration(node: EnumMember) {
emitJsDocComments(node);
writeTextOfNode(currentSourceFile, node.name);
let enumMemberValue = resolver.getConstantValue(node);
writeTextOfNode(currentText, node.name);
const enumMemberValue = resolver.getConstantValue(node);
if (enumMemberValue !== undefined) {
write(" = ");
write(enumMemberValue.toString());
@@ -826,7 +881,7 @@ namespace ts {
increaseIndent();
emitJsDocComments(node);
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 (node.constraint && !isPrivateMethodTypeParameter(node)) {
write(" extends ");
@@ -957,11 +1012,11 @@ namespace ts {
}
write("class ");
writeTextOfNode(currentSourceFile, node.name);
let prevEnclosingDeclaration = enclosingDeclaration;
writeTextOfNode(currentText, node.name);
const prevEnclosingDeclaration = enclosingDeclaration;
enclosingDeclaration = node;
emitTypeParameters(node.typeParameters);
let baseTypeNode = getClassExtendsHeritageClauseElement(node);
const baseTypeNode = getClassExtendsHeritageClauseElement(node);
if (baseTypeNode) {
emitHeritageClause([baseTypeNode], /*isImplementsList*/ false);
}
@@ -981,8 +1036,8 @@ namespace ts {
emitJsDocComments(node);
emitModuleElementDeclarationFlags(node);
write("interface ");
writeTextOfNode(currentSourceFile, node.name);
let prevEnclosingDeclaration = enclosingDeclaration;
writeTextOfNode(currentText, node.name);
const prevEnclosingDeclaration = enclosingDeclaration;
enclosingDeclaration = node;
emitTypeParameters(node.typeParameters);
emitHeritageClause(getInterfaceBaseTypeNodes(node), /*isImplementsList*/ false);
@@ -1019,7 +1074,7 @@ namespace ts {
// 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
// what we want, namely the name expression enclosed in brackets.
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
// If optional property emit ?
if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) && hasQuestionToken(node)) {
write("?");
@@ -1068,7 +1123,7 @@ namespace ts {
}
function getVariableDeclarationTypeVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
let diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
const diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
return diagnosticMessage !== undefined ? {
diagnosticMessage,
errorNode: node,
@@ -1082,8 +1137,8 @@ namespace ts {
// For example:
// original: var [, c,,] = [ 2,3,4]
// emitted: declare var c: number; // instead of declare var c:number, ;
let elements: Node[] = [];
for (let element of bindingPattern.elements) {
const elements: Node[] = [];
for (const element of bindingPattern.elements) {
if (element.kind !== SyntaxKind.OmittedExpression) {
elements.push(element);
}
@@ -1093,7 +1148,7 @@ namespace ts {
function emitBindingElement(bindingElement: BindingElement) {
function getBindingElementTypeVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
let diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
const diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
return diagnosticMessage !== undefined ? {
diagnosticMessage,
errorNode: bindingElement,
@@ -1106,7 +1161,7 @@ namespace ts {
emitBindingPattern(<BindingPattern>bindingElement.name);
}
else {
writeTextOfNode(currentSourceFile, bindingElement.name);
writeTextOfNode(currentText, bindingElement.name);
writeTypeOfDeclaration(bindingElement, /*type*/ undefined, getBindingElementTypeVisibilityError);
}
}
@@ -1149,20 +1204,20 @@ namespace ts {
return;
}
let accessors = getAllAccessorDeclarations((<ClassDeclaration>node.parent).members, node);
const accessors = getAllAccessorDeclarations((<ClassDeclaration>node.parent).members, node);
let accessorWithTypeAnnotation: AccessorDeclaration;
if (node === accessors.firstAccessor) {
emitJsDocComments(accessors.getAccessor);
emitJsDocComments(accessors.setAccessor);
emitClassMemberDeclarationFlags(node);
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
if (!(node.flags & NodeFlags.Private)) {
accessorWithTypeAnnotation = node;
let type = getTypeAnnotationFromAccessor(node);
if (!type) {
// 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);
if (type) {
accessorWithTypeAnnotation = anotherAccessor;
@@ -1246,13 +1301,13 @@ namespace ts {
}
if (node.kind === SyntaxKind.FunctionDeclaration) {
write("function ");
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
}
else if (node.kind === SyntaxKind.Constructor) {
write("constructor");
}
else {
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
if (hasQuestionToken(node)) {
write("?");
}
@@ -1279,7 +1334,7 @@ namespace ts {
write("(");
}
let prevEnclosingDeclaration = enclosingDeclaration;
const prevEnclosingDeclaration = enclosingDeclaration;
enclosingDeclaration = node;
// Parameters
@@ -1293,7 +1348,7 @@ namespace ts {
}
// 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) {
// Emit type literal signature return type only if specified
if (node.type) {
@@ -1392,7 +1447,7 @@ namespace ts {
emitBindingPattern(<BindingPattern>node.name);
}
else {
writeTextOfNode(currentSourceFile, node.name);
writeTextOfNode(currentText, node.name);
}
if (resolver.isOptionalParameter(node)) {
write("?");
@@ -1409,7 +1464,7 @@ namespace ts {
}
function getParameterDeclarationTypeVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
let diagnosticMessage: DiagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
const diagnosticMessage: DiagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
return diagnosticMessage !== undefined ? {
diagnosticMessage,
errorNode: node,
@@ -1482,7 +1537,7 @@ namespace ts {
}
else if (bindingPattern.kind === SyntaxKind.ArrayBindingPattern) {
write("[");
let elements = bindingPattern.elements;
const elements = bindingPattern.elements;
emitCommaList(elements, emitBindingElement);
if (elements && elements.hasTrailingComma) {
write(", ");
@@ -1493,7 +1548,7 @@ namespace ts {
function emitBindingElement(bindingElement: BindingElement) {
function getBindingElementTypeVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
let diagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
const diagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccesibilityResult);
return diagnosticMessage !== undefined ? {
diagnosticMessage,
errorNode: bindingElement,
@@ -1518,7 +1573,7 @@ namespace ts {
// Example:
// original: function foo({y: [a,b,c]}) {}
// emit : declare function foo({y: [a, b, c]}: { y: [any, any, any] }) void;
writeTextOfNode(currentSourceFile, bindingElement.propertyName);
writeTextOfNode(currentText, bindingElement.propertyName);
write(": ");
}
if (bindingElement.name) {
@@ -1541,7 +1596,7 @@ namespace ts {
if (bindingElement.dotDotDotToken) {
write("...");
}
writeTextOfNode(currentSourceFile, bindingElement.name);
writeTextOfNode(currentText, bindingElement.name);
}
}
}
@@ -1608,11 +1663,11 @@ namespace ts {
/* @internal */
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,
// or should we just not write this file like we are doing now
if (!emitDeclarationResult.reportedDeclarationError) {
let declarationOutput = emitDeclarationResult.referencePathsOutput
const declarationOutput = emitDeclarationResult.referencePathsOutput
+ getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo);
writeFile(host, diagnostics, removeFileExtension(jsFilePath) + ".d.ts", declarationOutput, host.getCompilerOptions().emitBOM);
}
+75 -34
View File
@@ -627,7 +627,7 @@
"category": "Error",
"code": 1203
},
"Cannot compile modules into 'es6' when targeting 'ES5' or lower.": {
"Cannot compile modules into 'es2015' when targeting 'ES5' or lower.": {
"category": "Error",
"code": 1204
},
@@ -799,7 +799,11 @@
"'=' can only be used in an object literal property inside a destructuring assignment.": {
"category": "Error",
"code": 1312
},
},
"The body of an 'if' statement cannot be the empty statement.": {
"category": "Error",
"code": 1313
},
"Duplicate identifier '{0}'.": {
"category": "Error",
"code": 2300
@@ -1008,7 +1012,7 @@
"category": "Error",
"code": 2354
},
"A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement.": {
"A function whose declared type is neither 'void' nor 'any' must return a value.": {
"category": "Error",
"code": 2355
},
@@ -1092,7 +1096,7 @@
"category": "Error",
"code": 2377
},
"A 'get' accessor must return a value or consist of a single 'throw' statement.": {
"A 'get' accessor must return a value.": {
"category": "Error",
"code": 2378
},
@@ -1712,14 +1716,14 @@
"category": "Error",
"code": 2654
},
"Exported external package typings can only be in '.d.ts' files. Please contact the package author to update the package definition.": {
"category": "Error",
"code": 2655
},
"Exported external package typings file '{0}' is not a module. Please contact the package author to update the package definition.": {
"category": "Error",
"code": 2656
},
"JSX expressions must have one parent element": {
"category": "Error",
"code": 2657
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
"code": 4000
@@ -2000,10 +2004,6 @@
"category": "Error",
"code": 4082
},
"Loop contains block-scoped variable '{0}' referenced by a function in the loop. This is only supported in ECMAScript 6 or higher.": {
"category": "Error",
"code": 4091
},
"The current host does not support the '{0}' option.": {
"category": "Error",
"code": 5001
@@ -2040,7 +2040,7 @@
"category": "Error",
"code": 5042
},
"Option 'isolatedModules' can only be used when either option'--module' is provided or option 'target' is 'ES6' or higher.": {
"Option 'isolatedModules' can only be used when either option '--module' is provided or option 'target' is 'ES2015' or higher.": {
"category": "Error",
"code": 5047
},
@@ -2101,11 +2101,11 @@
"category": "Message",
"code": 6010
},
"Specify ECMAScript target version: 'ES3' (default), 'ES5', or 'ES6' (experimental)": {
"category": "Message",
"code": 6015
},
"Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es6'": {
"Specify ECMAScript target version: 'ES3' (default), 'ES5', or 'ES2015' (experimental)": {
"category": "Message",
"code": 6015
},
"Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'": {
"category": "Message",
"code": 6016
},
@@ -2189,14 +2189,14 @@
"category": "Error",
"code": 6045
},
"Argument for '--module' option must be 'commonjs', 'amd', 'system', 'umd', or 'es6'.": {
"Argument for '--module' option must be 'commonjs', 'amd', 'system', 'umd', or 'es2015'.": {
"category": "Error",
"code": 6046
},
"Argument for '--target' option must be 'ES3', 'ES5', or 'ES6'.": {
"category": "Error",
"code": 6047
},
"Argument for '--target' option must be 'ES3', 'ES5', or 'ES2015'.": {
"category": "Error",
"code": 6047
},
"Locale must be of the form <language> or <language>-<territory>. For example '{0}' or '{1}'.": {
"category": "Error",
"code": 6048
@@ -2258,14 +2258,6 @@
"code": 6063
},
"Specify JSX code generation: 'preserve' or 'react'": {
"category": "Message",
"code": 6080
},
"Argument for '--jsx' must be 'preserve' or 'react'.": {
"category": "Message",
"code": 6081
},
"Enables experimental support for ES7 decorators.": {
"category": "Message",
"code": 6065
@@ -2294,7 +2286,42 @@
"category": "Message",
"code": 6072
},
"Stylize errors and messages using color and context. (experimental)": {
"category": "Message",
"code": 6073
},
"Do not report errors on unused labels.": {
"category": "Message",
"code": 6074
},
"Report error when not all code paths in function return a value.": {
"category": "Message",
"code": 6075
},
"Report errors for fallthrough cases in switch statement.": {
"category": "Message",
"code": 6076
},
"Do not report errors on unreachable code.": {
"category": "Message",
"code": 6077
},
"Disallow inconsistently-cased references to the same file.": {
"category": "Message",
"code": 6078
},
"Specify JSX code generation: 'preserve' or 'react'": {
"category": "Message",
"code": 6080
},
"Argument for '--jsx' must be 'preserve' or 'react'.": {
"category": "Message",
"code": 6081
},
"Only 'amd' and 'system' modules are supported alongside --{0}.": {
"category": "Error",
"code": 6082
},
"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",
"code": 7005
@@ -2363,8 +2390,22 @@
"category": "Error",
"code": 7026
},
"Unreachable code detected.": {
"category": "Error",
"code": 7027
},
"Unused label.": {
"category": "Error",
"code": 7028
},
"Fallthrough case in switch.": {
"category": "Error",
"code": 7029
},
"Not all code paths return a value.": {
"category": "Error",
"code": 7030
},
"You cannot rename this element.": {
"category": "Error",
"code": 8000
+1112 -508
View File
File diff suppressed because it is too large Load Diff
+463 -425
View File
File diff suppressed because it is too large Load Diff
+222 -193
View File
@@ -10,7 +10,7 @@ namespace ts {
/** The version of the TypeScript compiler release */
let emptyArray: any[] = [];
const emptyArray: any[] = [];
export const version = "1.8.0";
@@ -20,7 +20,7 @@ namespace ts {
if (sys.fileExists(fileName)) {
return fileName;
}
let parentPath = getDirectoryPath(searchPath);
const parentPath = getDirectoryPath(searchPath);
if (parentPath === searchPath) {
break;
}
@@ -31,13 +31,13 @@ namespace ts {
}
export function resolveTripleslashReference(moduleName: string, containingFile: string): string {
let basePath = getDirectoryPath(containingFile);
let referencedFileName = isRootedDiskPath(moduleName) ? moduleName : combinePaths(basePath, moduleName);
const basePath = getDirectoryPath(containingFile);
const referencedFileName = isRootedDiskPath(moduleName) ? moduleName : combinePaths(basePath, moduleName);
return normalizePath(referencedFileName);
}
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.module === ModuleKind.CommonJS ? ModuleResolutionKind.NodeJs : ModuleResolutionKind.Classic;
@@ -48,18 +48,18 @@ namespace ts {
}
export function nodeModuleNameResolver(moduleName: string, containingFile: string, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations {
let containingDirectory = getDirectoryPath(containingFile);
const containingDirectory = getDirectoryPath(containingFile);
if (getRootLength(moduleName) !== 0 || nameStartsWithDotSlashOrDotDotSlash(moduleName)) {
let failedLookupLocations: string[] = [];
let candidate = normalizePath(combinePaths(containingDirectory, moduleName));
let resolvedFileName = loadNodeModuleFromFile(candidate, failedLookupLocations, host);
const failedLookupLocations: string[] = [];
const candidate = normalizePath(combinePaths(containingDirectory, moduleName));
let resolvedFileName = loadNodeModuleFromFile(supportedJsExtensions, candidate, failedLookupLocations, host);
if (resolvedFileName) {
return { resolvedModule: { resolvedFileName }, failedLookupLocations };
}
resolvedFileName = loadNodeModuleFromDirectory(candidate, failedLookupLocations, host);
resolvedFileName = loadNodeModuleFromDirectory(supportedJsExtensions, candidate, failedLookupLocations, host);
return resolvedFileName
? { resolvedModule: { resolvedFileName }, failedLookupLocations }
: { resolvedModule: undefined, failedLookupLocations };
@@ -69,11 +69,11 @@ namespace ts {
}
}
function loadNodeModuleFromFile(candidate: string, failedLookupLocation: string[], host: ModuleResolutionHost): string {
return forEach(moduleFileExtensions, tryLoad);
function loadNodeModuleFromFile(extensions: string[], candidate: string, failedLookupLocation: string[], host: ModuleResolutionHost): string {
return forEach(extensions, tryLoad);
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)) {
return fileName;
}
@@ -84,14 +84,14 @@ namespace ts {
}
}
function loadNodeModuleFromDirectory(candidate: string, failedLookupLocation: string[], host: ModuleResolutionHost): string {
let packageJsonPath = combinePaths(candidate, "package.json");
function loadNodeModuleFromDirectory(extensions: string[], candidate: string, failedLookupLocation: string[], host: ModuleResolutionHost): string {
const packageJsonPath = combinePaths(candidate, "package.json");
if (host.fileExists(packageJsonPath)) {
let jsonContent: { typings?: string };
try {
let jsonText = host.readFile(packageJsonPath);
const jsonText = host.readFile(packageJsonPath);
jsonContent = jsonText ? <{ typings?: string }>JSON.parse(jsonText) : { typings: undefined };
}
catch (e) {
@@ -100,7 +100,7 @@ namespace ts {
}
if (jsonContent.typings) {
let result = loadNodeModuleFromFile(normalizePath(combinePaths(candidate, jsonContent.typings)), failedLookupLocation, host);
const result = loadNodeModuleFromFile(extensions, normalizePath(combinePaths(candidate, jsonContent.typings)), failedLookupLocation, host);
if (result) {
return result;
}
@@ -111,29 +111,29 @@ namespace ts {
failedLookupLocation.push(packageJsonPath);
}
return loadNodeModuleFromFile(combinePaths(candidate, "index"), failedLookupLocation, host);
return loadNodeModuleFromFile(extensions, combinePaths(candidate, "index"), failedLookupLocation, host);
}
function loadModuleFromNodeModules(moduleName: string, directory: string, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations {
let failedLookupLocations: string[] = [];
const failedLookupLocations: string[] = [];
directory = normalizeSlashes(directory);
while (true) {
let baseName = getBaseFileName(directory);
const baseName = getBaseFileName(directory);
if (baseName !== "node_modules") {
let nodeModulesFolder = combinePaths(directory, "node_modules");
let candidate = normalizePath(combinePaths(nodeModulesFolder, moduleName));
let result = loadNodeModuleFromFile(candidate, failedLookupLocations, host);
const nodeModulesFolder = combinePaths(directory, "node_modules");
const candidate = normalizePath(combinePaths(nodeModulesFolder, moduleName));
let result = loadNodeModuleFromFile(supportedExtensions, candidate, failedLookupLocations, host);
if (result) {
return { resolvedModule: { resolvedFileName: result, isExternalLibraryImport: true }, failedLookupLocations };
}
result = loadNodeModuleFromDirectory(candidate, failedLookupLocations, host);
result = loadNodeModuleFromDirectory(supportedExtensions, candidate, failedLookupLocations, host);
if (result) {
return { resolvedModule: { resolvedFileName: result, isExternalLibraryImport: true }, failedLookupLocations };
}
}
let parentPath = getDirectoryPath(directory);
const parentPath = getDirectoryPath(directory);
if (parentPath === directory) {
break;
}
@@ -145,7 +145,7 @@ namespace ts {
}
function nameStartsWithDotSlashOrDotDotSlash(name: string) {
let i = name.lastIndexOf("./", 1);
const i = name.lastIndexOf("./", 1);
return i === 0 || (i === 1 && name.charCodeAt(0) === CharacterCodes.dot);
}
@@ -159,19 +159,20 @@ namespace ts {
let searchPath = getDirectoryPath(containingFile);
let searchName: string;
let failedLookupLocations: string[] = [];
const failedLookupLocations: string[] = [];
let referencedSourceFile: string;
const extensions = compilerOptions.allowNonTsExtensions ? supportedJsExtensions : supportedExtensions;
while (true) {
searchName = normalizePath(combinePaths(searchPath, moduleName));
referencedSourceFile = forEach(supportedExtensions, extension => {
referencedSourceFile = forEach(extensions, extension => {
if (extension === ".tsx" && !compilerOptions.jsx) {
// resolve .tsx files only if jsx support is enabled
// 'logical not' handles both undefined and None cases
return undefined;
}
let candidate = searchName + extension;
const candidate = searchName + extension;
if (host.fileExists(candidate)) {
return candidate;
}
@@ -184,7 +185,7 @@ namespace ts {
break;
}
let parentPath = getDirectoryPath(searchPath);
const parentPath = getDirectoryPath(searchPath);
if (parentPath === searchPath) {
break;
}
@@ -199,16 +200,13 @@ namespace ts {
/* @internal */
export const defaultInitCompilerOptions: CompilerOptions = {
module: ModuleKind.CommonJS,
target: ScriptTarget.ES3,
target: ScriptTarget.ES5,
noImplicitAny: false,
outDir: "built",
rootDir: ".",
sourceMap: false,
};
export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost {
let currentDirectory: string;
let existingDirectories: Map<boolean> = {};
const existingDirectories: Map<boolean> = {};
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.
@@ -217,12 +215,12 @@ namespace ts {
}
// returned by CScript sys environment
let unsupportedFileEncodingErrorCode = -2147024809;
const unsupportedFileEncodingErrorCode = -2147024809;
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile {
let text: string;
try {
let start = new Date().getTime();
const start = new Date().getTime();
text = sys.readFile(fileName, options.charset);
ioReadTime += new Date().getTime() - start;
}
@@ -251,7 +249,7 @@ namespace ts {
function ensureDirectoriesExist(directoryPath: string) {
if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) {
let parentDirectory = getDirectoryPath(directoryPath);
const parentDirectory = getDirectoryPath(directoryPath);
ensureDirectoriesExist(parentDirectory);
sys.createDirectory(directoryPath);
}
@@ -259,7 +257,7 @@ namespace ts {
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
try {
let start = new Date().getTime();
const start = new Date().getTime();
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
sys.writeFile(fileName, data, writeByteOrderMark);
ioWriteTime += new Date().getTime() - start;
@@ -277,7 +275,7 @@ namespace ts {
getSourceFile,
getDefaultLibFileName: options => combinePaths(getDirectoryPath(normalizePath(sys.getExecutingFilePath())), getDefaultLibFileName(options)),
writeFile,
getCurrentDirectory: () => currentDirectory || (currentDirectory = sys.getCurrentDirectory()),
getCurrentDirectory: memoize(() => sys.getCurrentDirectory()),
useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames,
getCanonicalFileName,
getNewLine: () => newLine,
@@ -287,7 +285,7 @@ namespace ts {
}
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.getGlobalDiagnostics(cancellationToken),
program.getSemanticDiagnostics(sourceFile, cancellationToken));
@@ -329,7 +327,7 @@ namespace ts {
let program: Program;
let files: SourceFile[] = [];
let fileProcessingDiagnostics = createDiagnosticCollection();
let programDiagnostics = createDiagnosticCollection();
const programDiagnostics = createDiagnosticCollection();
let commonSourceDirectory: string;
let diagnosticsProducingTypeChecker: TypeChecker;
@@ -338,20 +336,24 @@ namespace ts {
let skipDefaultLib = options.noLib;
let start = new Date().getTime();
const start = new Date().getTime();
host = host || createCompilerHost(options);
const currentDirectory = host.getCurrentDirectory();
const resolveModuleNamesWorker = host.resolveModuleNames
? ((moduleNames: string[], containingFile: string) => host.resolveModuleNames(moduleNames, containingFile))
: ((moduleNames: string[], containingFile: string) => map(moduleNames, moduleName => resolveModuleName(moduleName, containingFile, options, host).resolvedModule));
let filesByName = createFileMap<SourceFile>(fileName => host.getCanonicalFileName(fileName));
const filesByName = createFileMap<SourceFile>();
// stores 'filename -> file association' ignoring case
// used to track cases when two file names differ only in casing
const filesByNameIgnoreCase = host.useCaseSensitiveFileNames() ? createFileMap<SourceFile>(fileName => fileName.toLowerCase()) : undefined;
if (oldProgram) {
// check properties that can affect structure of the program or module resolution strategy
// if any of these properties has changed - structure cannot be reused
let oldOptions = oldProgram.getCompilerOptions();
const oldOptions = oldProgram.getCompilerOptions();
if ((oldOptions.module !== options.module) ||
(oldOptions.noResolve !== options.noResolve) ||
(oldOptions.target !== options.target) ||
@@ -362,13 +364,13 @@ namespace ts {
}
if (!tryReuseStructureFromOldProgram()) {
forEach(rootNames, name => processRootFile(name, false));
forEach(rootNames, name => processRootFile(name, /*isDefaultLib*/ false));
// Do not process the default library if:
// - The '--noLib' flag is used.
// - A 'no-default-lib' reference comment is encountered in
// processing the root files.
if (!skipDefaultLib) {
processRootFile(host.getDefaultLibFileName(options), true);
processRootFile(host.getDefaultLibFileName(options), /*isDefaultLib*/ true);
}
}
@@ -381,7 +383,7 @@ namespace ts {
program = {
getRootFileNames: () => rootNames,
getSourceFile: getSourceFile,
getSourceFile,
getSourceFiles: () => files,
getCompilerOptions: () => options,
getSyntacticDiagnostics,
@@ -394,7 +396,7 @@ namespace ts {
getDiagnosticsProducingTypeChecker,
getCommonSourceDirectory: () => commonSourceDirectory,
emit,
getCurrentDirectory: () => host.getCurrentDirectory(),
getCurrentDirectory: () => currentDirectory,
getNodeCount: () => getDiagnosticsProducingTypeChecker().getNodeCount(),
getIdentifierCount: () => getDiagnosticsProducingTypeChecker().getIdentifierCount(),
getSymbolCount: () => getDiagnosticsProducingTypeChecker().getSymbolCount(),
@@ -409,7 +411,7 @@ namespace ts {
getTypeChecker();
classifiableNames = {};
for (let sourceFile of files) {
for (const sourceFile of files) {
copyMap(sourceFile.classifiableNames, classifiableNames);
}
}
@@ -425,20 +427,25 @@ namespace ts {
Debug.assert(!oldProgram.structureIsReused);
// there is an old program, check if we can reuse its structure
let oldRootNames = oldProgram.getRootFileNames();
const oldRootNames = oldProgram.getRootFileNames();
if (!arrayIsEqualTo(oldRootNames, rootNames)) {
return false;
}
// check if program source files has changed in the way that can affect structure of the program
let newSourceFiles: SourceFile[] = [];
let modifiedSourceFiles: SourceFile[] = [];
for (let oldSourceFile of oldProgram.getSourceFiles()) {
const newSourceFiles: SourceFile[] = [];
const filePaths: Path[] = [];
const modifiedSourceFiles: SourceFile[] = [];
for (const oldSourceFile of oldProgram.getSourceFiles()) {
let newSourceFile = host.getSourceFile(oldSourceFile.fileName, options.target);
if (!newSourceFile) {
return false;
}
newSourceFile.path = oldSourceFile.path;
filePaths.push(newSourceFile.path);
if (oldSourceFile !== newSourceFile) {
if (oldSourceFile.hasNoDefaultLib !== newSourceFile.hasNoDefaultLib) {
// value of no-default-lib has changed
@@ -460,13 +467,13 @@ namespace ts {
}
if (resolveModuleNamesWorker) {
let moduleNames = map(newSourceFile.imports, name => name.text);
let resolutions = resolveModuleNamesWorker(moduleNames, newSourceFile.fileName);
const moduleNames = map(newSourceFile.imports, name => name.text);
const resolutions = resolveModuleNamesWorker(moduleNames, getNormalizedAbsolutePath(newSourceFile.fileName, currentDirectory));
// ensure that module resolution results are still correct
for (let i = 0; i < moduleNames.length; ++i) {
let newResolution = resolutions[i];
let oldResolution = getResolvedModule(oldSourceFile, moduleNames[i]);
let resolutionChanged = oldResolution
const newResolution = resolutions[i];
const oldResolution = getResolvedModule(oldSourceFile, moduleNames[i]);
const resolutionChanged = oldResolution
? !newResolution ||
oldResolution.resolvedFileName !== newResolution.resolvedFileName ||
!!oldResolution.isExternalLibraryImport !== !!newResolution.isExternalLibraryImport
@@ -491,14 +498,14 @@ namespace ts {
}
// update fileName -> file mapping
for (let file of newSourceFiles) {
filesByName.set(file.fileName, file);
for (let i = 0, len = newSourceFiles.length; i < len; ++i) {
filesByName.set(filePaths[i], newSourceFiles[i]);
}
files = newSourceFiles;
fileProcessingDiagnostics = oldProgram.getFileProcessingDiagnostics();
for (let modifiedFile of modifiedSourceFiles) {
for (const modifiedFile of modifiedSourceFiles) {
fileProcessingDiagnostics.reattachFileDiagnostics(modifiedFile);
}
oldProgram.structureIsReused = true;
@@ -508,10 +515,10 @@ namespace ts {
function getEmitHost(writeFileCallback?: WriteFileCallback): EmitHost {
return {
getCanonicalFileName: fileName => host.getCanonicalFileName(fileName),
getCanonicalFileName,
getCommonSourceDirectory: program.getCommonSourceDirectory,
getCompilerOptions: program.getCompilerOptions,
getCurrentDirectory: () => host.getCurrentDirectory(),
getCurrentDirectory: () => currentDirectory,
getNewLine: () => host.getNewLine(),
getSourceFile: program.getSourceFile,
getSourceFiles: program.getSourceFiles,
@@ -548,11 +555,11 @@ namespace ts {
// 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
// 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,
getEmitHost(writeFileCallback),
sourceFile);
@@ -561,10 +568,8 @@ namespace ts {
return emitResult;
}
function getSourceFile(fileName: string) {
// first try to use file name as is to find file
// then try to convert relative file name to absolute and use it to retrieve source file
return filesByName.get(fileName) || filesByName.get(getNormalizedAbsolutePath(fileName, host.getCurrentDirectory()));
function getSourceFile(fileName: string): SourceFile {
return filesByName.get(toPath(fileName, currentDirectory, getCanonicalFileName));
}
function getDiagnosticsHelper(
@@ -575,7 +580,7 @@ namespace ts {
return getDiagnostics(sourceFile, cancellationToken);
}
let allDiagnostics: Diagnostic[] = [];
const allDiagnostics: Diagnostic[] = [];
forEach(program.getSourceFiles(), sourceFile => {
if (cancellationToken) {
cancellationToken.throwIfCancellationRequested();
@@ -627,13 +632,13 @@ namespace ts {
function getSemanticDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
return runWithCancellationToken(() => {
let typeChecker = getDiagnosticsProducingTypeChecker();
const typeChecker = getDiagnosticsProducingTypeChecker();
Debug.assert(!!sourceFile.bindDiagnostics);
let bindDiagnostics = sourceFile.bindDiagnostics;
let checkDiagnostics = typeChecker.getDiagnostics(sourceFile, cancellationToken);
let fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName);
let programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName);
const bindDiagnostics = sourceFile.bindDiagnostics;
const checkDiagnostics = typeChecker.getDiagnostics(sourceFile, cancellationToken);
const fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName);
const programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName);
return bindDiagnostics.concat(checkDiagnostics).concat(fileProcessingDiagnosticsInFile).concat(programDiagnosticsInFile);
});
@@ -642,23 +647,23 @@ namespace ts {
function getDeclarationDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
return runWithCancellationToken(() => {
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.
let writeFile: WriteFileCallback = () => { };
const writeFile: WriteFileCallback = () => { };
return ts.getDeclarationDiagnostics(getEmitHost(writeFile), resolver, sourceFile);
}
});
}
function getOptionsDiagnostics(): Diagnostic[] {
let allDiagnostics: Diagnostic[] = [];
const allDiagnostics: Diagnostic[] = [];
addRange(allDiagnostics, fileProcessingDiagnostics.getGlobalDiagnostics());
addRange(allDiagnostics, programDiagnostics.getGlobalDiagnostics());
return sortAndDeduplicateDiagnostics(allDiagnostics);
}
function getGlobalDiagnostics(): Diagnostic[] {
let allDiagnostics: Diagnostic[] = [];
const allDiagnostics: Diagnostic[] = [];
addRange(allDiagnostics, getDiagnosticsProducingTypeChecker().getGlobalDiagnostics());
return sortAndDeduplicateDiagnostics(allDiagnostics);
}
@@ -684,45 +689,60 @@ namespace ts {
return;
}
const isJavaScriptFile = isSourceFileJavaScript(file);
let imports: LiteralExpression[];
for (let node of file.statements) {
collect(node, /* allowRelativeModuleNames */ true);
for (const node of file.statements) {
collect(node, /*allowRelativeModuleNames*/ true, /*collectOnlyRequireCalls*/ false);
}
file.imports = imports || emptyArray;
function collect(node: Node, allowRelativeModuleNames: boolean): void {
switch (node.kind) {
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.ExportDeclaration:
let moduleNameExpr = getExternalModuleName(node);
if (!moduleNameExpr || moduleNameExpr.kind !== SyntaxKind.StringLiteral) {
break;
}
if (!(<LiteralExpression>moduleNameExpr).text) {
break;
}
return;
if (allowRelativeModuleNames || !isExternalModuleNameRelative((<LiteralExpression>moduleNameExpr).text)) {
(imports || (imports = [])).push(<LiteralExpression>moduleNameExpr);
}
break;
case SyntaxKind.ModuleDeclaration:
if ((<ModuleDeclaration>node).name.kind === SyntaxKind.StringLiteral && (node.flags & NodeFlags.Ambient || isDeclarationFile(file))) {
// TypeScript 1.0 spec (April 2014): 12.1.6
// An AmbientExternalModuleDeclaration declares an external module.
// This type of declaration is permitted only in the global module.
// The StringLiteral must specify a top - level external module name.
// Relative external module names are not permitted
forEachChild((<ModuleDeclaration>node).body, node => {
function collect(node: Node, allowRelativeModuleNames: boolean, collectOnlyRequireCalls: boolean): void {
if (!collectOnlyRequireCalls) {
switch (node.kind) {
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.ExportDeclaration:
let moduleNameExpr = getExternalModuleName(node);
if (!moduleNameExpr || moduleNameExpr.kind !== SyntaxKind.StringLiteral) {
break;
}
if (!(<LiteralExpression>moduleNameExpr).text) {
break;
}
if (allowRelativeModuleNames || !isExternalModuleNameRelative((<LiteralExpression>moduleNameExpr).text)) {
(imports || (imports = [])).push(<LiteralExpression>moduleNameExpr);
}
break;
case SyntaxKind.ModuleDeclaration:
if ((<ModuleDeclaration>node).name.kind === SyntaxKind.StringLiteral && (node.flags & NodeFlags.Ambient || isDeclarationFile(file))) {
// TypeScript 1.0 spec (April 2014): 12.1.6
// An ExternalImportDeclaration in anAmbientExternalModuleDeclaration may reference other external modules
// only through top - level external module names. Relative external module names are not permitted.
collect(node, /* allowRelativeModuleNames */ false);
});
}
break;
// An AmbientExternalModuleDeclaration declares an external module.
// This type of declaration is permitted only in the global module.
// The StringLiteral must specify a top - level external module name.
// Relative external module names are not permitted
forEachChild((<ModuleDeclaration>node).body, node => {
// TypeScript 1.0 spec (April 2014): 12.1.6
// An ExternalImportDeclaration in anAmbientExternalModuleDeclaration may reference other external modules
// only through top - level external module names. Relative external module names are not permitted.
collect(node, /*allowRelativeModuleNames*/ false, collectOnlyRequireCalls);
});
}
break;
}
}
if (isJavaScriptFile) {
if (isRequireCall(node)) {
(imports || (imports = [])).push(<StringLiteral>(<CallExpression>node).arguments[0]);
}
else {
forEachChild(node, node => collect(node, allowRelativeModuleNames, /*collectOnlyRequireCalls*/ true));
}
}
}
}
@@ -735,7 +755,7 @@ namespace ts {
diagnostic = Diagnostics.File_0_has_unsupported_extension_The_only_supported_extensions_are_1;
diagnosticArgument = [fileName, "'" + supportedExtensions.join("', '") + "'"];
}
else if (!findSourceFile(fileName, isDefaultLib, refFile, refPos, refEnd)) {
else if (!findSourceFile(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, refFile, refPos, refEnd)) {
diagnostic = Diagnostics.File_0_not_found;
diagnosticArgument = [fileName];
}
@@ -745,13 +765,13 @@ namespace ts {
}
}
else {
let nonTsFile: SourceFile = options.allowNonTsExtensions && findSourceFile(fileName, isDefaultLib, refFile, refPos, refEnd);
const nonTsFile: SourceFile = options.allowNonTsExtensions && findSourceFile(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, refFile, refPos, refEnd);
if (!nonTsFile) {
if (options.allowNonTsExtensions) {
diagnostic = Diagnostics.File_0_not_found;
diagnosticArgument = [fileName];
}
else if (!forEach(supportedExtensions, extension => findSourceFile(fileName + extension, isDefaultLib, refFile, refPos, refEnd))) {
else if (!forEach(supportedExtensions, extension => findSourceFile(fileName + extension, toPath(fileName + extension, currentDirectory, getCanonicalFileName), isDefaultLib, refFile, refPos, refEnd))) {
diagnostic = Diagnostics.File_0_not_found;
fileName += ".ts";
diagnosticArgument = [fileName];
@@ -769,24 +789,31 @@ namespace ts {
}
}
// Get source file from normalized fileName
function findSourceFile(fileName: string, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number): SourceFile {
if (filesByName.contains(fileName)) {
// We've already looked for this file, use cached result
return getSourceFileFromCache(fileName, /*useAbsolutePath*/ false);
function reportFileNamesDifferOnlyInCasingError(fileName: string, existingFileName: string, refFile: SourceFile, refPos: number, refEnd: number): void {
if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) {
fileProcessingDiagnostics.add(createFileDiagnostic(refFile, refPos, refEnd - refPos,
Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, fileName, existingFileName));
}
else {
fileProcessingDiagnostics.add(createCompilerDiagnostic(Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, fileName, existingFileName));
}
}
// Get source file from normalized fileName
function findSourceFile(fileName: string, path: Path, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number): SourceFile {
if (filesByName.contains(path)) {
const file = filesByName.get(path);
// try to check if we've already seen this file but with a different casing in path
// NOTE: this only makes sense for case-insensitive file systems
if (file && options.forceConsistentCasingInFileNames && getNormalizedAbsolutePath(file.fileName, currentDirectory) !== getNormalizedAbsolutePath(fileName, currentDirectory)) {
reportFileNamesDifferOnlyInCasingError(fileName, file.fileName, refFile, refPos, refEnd);
}
let normalizedAbsolutePath = getNormalizedAbsolutePath(fileName, host.getCurrentDirectory());
if (filesByName.contains(normalizedAbsolutePath)) {
const file = getSourceFileFromCache(normalizedAbsolutePath, /*useAbsolutePath*/ true);
// we don't have resolution for this relative file name but the match was found by absolute file name
// store resolution for relative name as well
filesByName.set(fileName, file);
return file;
}
// 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) {
fileProcessingDiagnostics.add(createFileDiagnostic(refFile, refPos, refEnd - refPos,
Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage));
@@ -796,14 +823,24 @@ namespace ts {
}
});
filesByName.set(fileName, file);
filesByName.set(path, file);
if (file) {
file.path = path;
if (host.useCaseSensitiveFileNames()) {
// for case-sensitive file systems check if we've already seen some file with similar filename ignoring case
const existingFile = filesByNameIgnoreCase.get(path);
if (existingFile) {
reportFileNamesDifferOnlyInCasingError(fileName, existingFile.fileName, refFile, refPos, refEnd);
}
else {
filesByNameIgnoreCase.set(path, file);
}
}
skipDefaultLib = skipDefaultLib || file.hasNoDefaultLib;
// Set the source file for normalized absolute path
filesByName.set(normalizedAbsolutePath, file);
let basePath = getDirectoryPath(fileName);
const basePath = getDirectoryPath(fileName);
if (!options.noResolve) {
processReferencedFiles(file, basePath);
}
@@ -812,7 +849,6 @@ namespace ts {
processImportedModules(file, basePath);
if (isDefaultLib) {
file.isDefaultLib = true;
files.unshift(file);
}
else {
@@ -821,54 +857,38 @@ namespace ts {
}
return file;
function getSourceFileFromCache(fileName: string, useAbsolutePath: boolean): SourceFile {
let file = filesByName.get(fileName);
if (file && host.useCaseSensitiveFileNames()) {
let sourceFileName = useAbsolutePath ? getNormalizedAbsolutePath(file.fileName, host.getCurrentDirectory()) : file.fileName;
if (normalizeSlashes(fileName) !== normalizeSlashes(sourceFileName)) {
if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) {
fileProcessingDiagnostics.add(createFileDiagnostic(refFile, refPos, refEnd - refPos,
Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, fileName, sourceFileName));
}
else {
fileProcessingDiagnostics.add(createCompilerDiagnostic(Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, fileName, sourceFileName));
}
}
}
return file;
}
}
function processReferencedFiles(file: SourceFile, basePath: string) {
forEach(file.referencedFiles, ref => {
let referencedFileName = resolveTripleslashReference(ref.fileName, file.fileName);
processSourceFile(referencedFileName, /* isDefaultLib */ false, file, ref.pos, ref.end);
const referencedFileName = resolveTripleslashReference(ref.fileName, file.fileName);
processSourceFile(referencedFileName, /*isDefaultLib*/ false, file, ref.pos, ref.end);
});
}
function getCanonicalFileName(fileName: string): string {
return host.getCanonicalFileName(fileName);
}
function processImportedModules(file: SourceFile, basePath: string) {
collectExternalModuleReferences(file);
if (file.imports.length) {
file.resolvedModules = {};
let moduleNames = map(file.imports, name => name.text);
let resolutions = resolveModuleNamesWorker(moduleNames, file.fileName);
const moduleNames = map(file.imports, name => name.text);
const resolutions = resolveModuleNamesWorker(moduleNames, getNormalizedAbsolutePath(file.fileName, currentDirectory));
for (let i = 0; i < file.imports.length; ++i) {
let resolution = resolutions[i];
const resolution = resolutions[i];
setResolvedModule(file, moduleNames[i], resolution);
if (resolution && !options.noResolve) {
const importedFile = findModuleSourceFile(resolution.resolvedFileName, file.imports[i]);
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 (!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));
}
else if (!fileExtensionIs(importedFile.fileName, ".d.ts")) {
let start = getTokenPosOfNode(file.imports[i], file);
fileProcessingDiagnostics.add(createFileDiagnostic(file, start, file.imports[i].end - start, Diagnostics.Exported_external_package_typings_can_only_be_in_d_ts_files_Please_contact_the_package_author_to_update_the_package_definition));
}
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));
}
}
@@ -880,22 +900,17 @@ namespace ts {
file.resolvedModules = undefined;
}
return;
function findModuleSourceFile(fileName: string, nameLiteral: Expression) {
return findSourceFile(fileName, /* isDefaultLib */ false, file, skipTrivia(file.text, nameLiteral.pos), nameLiteral.end);
}
}
function computeCommonSourceDirectory(sourceFiles: SourceFile[]): string {
let commonPathComponents: string[];
let currentDirectory = host.getCurrentDirectory();
forEach(files, sourceFile => {
const failed = forEach(files, sourceFile => {
// Each file contributes into common source file path
if (isDeclarationFile(sourceFile)) {
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
if (!commonPathComponents) {
@@ -905,10 +920,10 @@ namespace ts {
}
for (let i = 0, n = Math.min(commonPathComponents.length, sourcePathComponents.length); i < n; i++) {
if (commonPathComponents[i] !== sourcePathComponents[i]) {
if (getCanonicalFileName(commonPathComponents[i]) !== getCanonicalFileName(sourcePathComponents[i])) {
if (i === 0) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files));
return;
// Failed to find any common path component
return true;
}
// New common path found that is 0 -> i-1
@@ -923,18 +938,26 @@ namespace ts {
}
});
// A common path can not be found when paths span multiple drives on windows, for example
if (failed) {
return "";
}
if (!commonPathComponents) { // Can happen when all input files are .d.ts files
return currentDirectory;
}
return getNormalizedPathFromPathComponents(commonPathComponents);
}
function checkSourceFilesBelongToPath(sourceFiles: SourceFile[], rootDirectory: string): boolean {
let allFilesBelongToPath = true;
if (sourceFiles) {
let currentDirectory = host.getCurrentDirectory();
let absoluteRootDirectoryPath = host.getCanonicalFileName(getNormalizedAbsolutePath(rootDirectory, currentDirectory));
const absoluteRootDirectoryPath = host.getCanonicalFileName(getNormalizedAbsolutePath(rootDirectory, currentDirectory));
for (var sourceFile of sourceFiles) {
if (!isDeclarationFile(sourceFile)) {
let absoluteSourceFilePath = host.getCanonicalFileName(getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory));
const absoluteSourceFilePath = host.getCanonicalFileName(getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory));
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));
allFilesBelongToPath = false;
@@ -972,16 +995,15 @@ namespace ts {
if (options.mapRoot) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "mapRoot", "inlineSourceMap"));
}
if (options.sourceRoot) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "sourceRoot", "inlineSourceMap"));
}
}
if (options.inlineSources) {
if (!options.sourceMap && !options.inlineSourceMap) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_inlineSources_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided));
}
if (options.sourceRoot) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "sourceRoot", "inlineSources"));
}
}
if (options.out && options.outFile) {
@@ -993,52 +1015,59 @@ namespace ts {
if (options.mapRoot) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "mapRoot", "sourceMap"));
}
if (options.sourceRoot) {
if (options.sourceRoot && !options.inlineSourceMap) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "sourceRoot", "sourceMap"));
}
return;
}
let languageVersion = options.target || ScriptTarget.ES3;
let outFile = options.outFile || options.out;
const languageVersion = options.target || ScriptTarget.ES3;
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.module && languageVersion < ScriptTarget.ES6) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_isolatedModules_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES6_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) {
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));
}
}
else if (firstExternalModuleSourceFile && languageVersion < ScriptTarget.ES6 && !options.module) {
// 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));
}
// Cannot specify module gen target of es6 when below es6
if (options.module === ModuleKind.ES6 && languageVersion < ScriptTarget.ES6) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_compile_modules_into_es6_when_targeting_ES5_or_lower));
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_compile_modules_into_es2015_when_targeting_ES5_or_lower));
}
// Cannot specify module gen that isn't amd or system with --out
if (outFile && options.module && !(options.module === ModuleKind.AMD || options.module === ModuleKind.System)) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Only_amd_and_system_modules_are_supported_alongside_0, options.out ? "out" : "outFile"));
}
// there has to be common source directory if user specified --outdir || --sourceRoot
// if user specified --mapRoot, there needs to be common source directory if there would be multiple files being emitted
if (options.outDir || // there is --outDir specified
options.sourceRoot || // there is --sourceRoot specified
(options.mapRoot && // there is --mapRoot specified and there would be multiple js files generated
(!outFile || firstExternalModuleSourceFile !== undefined))) {
options.mapRoot) { // there is --mapRoot specified
if (options.rootDir && checkSourceFilesBelongToPath(files, options.rootDir)) {
// If a rootDir is specified and is valid use it as the commonSourceDirectory
commonSourceDirectory = getNormalizedAbsolutePath(options.rootDir, host.getCurrentDirectory());
commonSourceDirectory = getNormalizedAbsolutePath(options.rootDir, currentDirectory);
}
else {
// Compute the commonSourceDirectory from the input files
commonSourceDirectory = computeCommonSourceDirectory(files);
// If we failed to find a good common directory, but outDir is specified and at least one of our files is on a windows drive/URL/other resource, add a failure
if (options.outDir && commonSourceDirectory === "" && forEach(files, file => getRootLength(file.fileName) > 1)) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files));
}
}
if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== directorySeparator) {
+60 -58
View File
File diff suppressed because one or more lines are too long
+41 -38
View File
@@ -51,15 +51,15 @@ namespace ts {
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*/;
let binaryStream = new ActiveXObject("ADODB.Stream");
const binaryStream = new ActiveXObject("ADODB.Stream");
binaryStream.Type = 1 /*binary*/;
let args: string[] = [];
const args: string[] = [];
for (let i = 0; i < WScript.Arguments.length; 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
fileStream.Charset = "x-ansi";
fileStream.LoadFromFile(fileName);
let bom = fileStream.ReadText(2) || "";
const bom = fileStream.ReadText(2) || "";
// Position must be at 0 before encoding can be changed
fileStream.Position = 0;
// [0xFF,0xFE] and [0xFE,0xFF] mean utf-16 (little or big endian), otherwise default to utf-8
@@ -124,7 +124,7 @@ namespace ts {
}
function getNames(collection: any): string[] {
let result: string[] = [];
const result: string[] = [];
for (let e = new Enumerator(collection); !e.atEnd(); e.moveNext()) {
result.push(e.item().Name);
}
@@ -132,22 +132,22 @@ namespace ts {
}
function readDirectory(path: string, extension?: string, exclude?: string[]): string[] {
let result: string[] = [];
const result: string[] = [];
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
visitDirectory(path);
return result;
function visitDirectory(path: string) {
let folder = fso.GetFolder(path || ".");
let files = getNames(folder.files);
for (let current of files) {
let name = combinePaths(path, current);
const folder = fso.GetFolder(path || ".");
const files = getNames(folder.files);
for (const current of files) {
const name = combinePaths(path, current);
if ((!extension || fileExtensionIs(name, extension)) && !contains(exclude, getCanonicalPath(name))) {
result.push(name);
}
}
let subfolders = getNames(folder.subfolders);
for (let current of subfolders) {
let name = combinePaths(path, current);
const subfolders = getNames(folder.subfolders);
for (const current of subfolders) {
const name = combinePaths(path, current);
if (!contains(exclude, getCanonicalPath(name))) {
visitDirectory(name);
}
@@ -198,6 +198,7 @@ namespace ts {
const _fs = require("fs");
const _path = require("path");
const _os = require("os");
const _tty = require("tty");
// average async stat takes about 30 microseconds
// set chunk size to do 30 files in < 1 millisecond
@@ -211,7 +212,7 @@ namespace ts {
}
function poll(checkedIndex: number) {
let watchedFile = watchedFiles[checkedIndex];
const watchedFile = watchedFiles[checkedIndex];
if (!watchedFile) {
return;
}
@@ -251,7 +252,7 @@ namespace ts {
}
function addFile(fileName: string, callback: (fileName: string, removed?: boolean) => void): WatchedFile {
let file: WatchedFile = {
const file: WatchedFile = {
fileName,
callback,
mtime: getModifiedTime(fileName)
@@ -290,7 +291,7 @@ namespace ts {
// changes for large reference sets? If so, do we want
// to increase the chunk size or decrease the interval
// time dynamically to match the large reference set?
let watchedFileSet = createWatchedFileSet();
const watchedFileSet = createWatchedFileSet();
function isNode4OrLater(): Boolean {
return parseInt(process.version.charAt(1)) >= 4;
@@ -304,14 +305,14 @@ namespace ts {
if (!_fs.existsSync(fileName)) {
return undefined;
}
let buffer = _fs.readFileSync(fileName);
const buffer = _fs.readFileSync(fileName);
let len = buffer.length;
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,
// flip all byte pairs and treat as little endian.
len &= ~1;
for (let i = 0; i < len; i += 2) {
let temp = buffer[i];
const temp = buffer[i];
buffer[i] = buffer[i + 1];
buffer[i + 1] = temp;
}
@@ -335,7 +336,17 @@ namespace ts {
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 {
@@ -343,17 +354,17 @@ namespace ts {
}
function readDirectory(path: string, extension?: string, exclude?: string[]): string[] {
let result: string[] = [];
const result: string[] = [];
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
visitDirectory(path);
return result;
function visitDirectory(path: string) {
let files = _fs.readdirSync(path || ".").sort();
let directories: string[] = [];
for (let current of files) {
let name = combinePaths(path, current);
const files = _fs.readdirSync(path || ".").sort();
const directories: string[] = [];
for (const current of files) {
const name = combinePaths(path, current);
if (!contains(exclude, getCanonicalPath(name))) {
let stat = _fs.statSync(name);
const stat = _fs.statSync(name);
if (stat.isFile()) {
if (!extension || fileExtensionIs(name, extension)) {
result.push(name);
@@ -364,7 +375,7 @@ namespace ts {
}
}
}
for (let current of directories) {
for (const current of directories) {
visitDirectory(current);
}
}
@@ -375,15 +386,7 @@ namespace ts {
newLine: _os.EOL,
useCaseSensitiveFileNames: useCaseSensitiveFileNames,
write(s: string): void {
const buffer = new Buffer(s, "utf8");
let offset = 0;
let toWrite: number = buffer.length;
let written = 0;
// 1 is a standard descriptor for stdout
while ((written = _fs.writeSync(1, buffer, offset, toWrite)) < toWrite) {
offset += written;
toWrite -= written;
}
process.stdout.write(s);
},
readFile,
writeFile,
@@ -397,7 +400,7 @@ namespace ts {
return _fs.watch(fileName, (eventName: string, relativeFileName: string) => callback(fileName));
}
let watchedFile = watchedFileSet.addFile(fileName, callback);
const watchedFile = watchedFileSet.addFile(fileName, callback);
return {
close: () => watchedFileSet.removeFile(watchedFile)
};
@@ -407,7 +410,7 @@ namespace ts {
// (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643)
return _fs.watch(
path,
{ persisten: true, recursive: !!recursive },
{ persistent: true, recursive: !!recursive },
(eventName: string, relativeFileName: string) => {
// In watchDirectory we only care about adding and removing files (when event name is
// "rename"); changes made within files are handled by corresponding fileWatchers (when
+194 -65
View File
@@ -6,20 +6,28 @@ namespace ts {
fileWatcher?: FileWatcher;
}
let reportDiagnostic = reportDiagnosticSimply;
function reportDiagnostics(diagnostics: Diagnostic[], host: CompilerHost): void {
for (const diagnostic of diagnostics) {
reportDiagnostic(diagnostic, host);
}
}
/**
* Checks to see if the locale is in the appropriate format,
* and if it is, attempts to set the appropriate language.
*/
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) {
errors.push(createCompilerDiagnostic(Diagnostics.Locale_must_be_of_the_form_language_or_language_territory_For_example_0_or_1, "en", "ja-jp"));
return false;
}
let language = matchResult[1];
let territory = matchResult[3];
const language = matchResult[1];
const territory = matchResult[3];
// First try the entire locale, then fall back to just language if that's all we have.
if (!trySetLanguageAndTerritory(language, territory, errors) &&
@@ -33,8 +41,8 @@ namespace ts {
}
function trySetLanguageAndTerritory(language: string, territory: string, errors: Diagnostic[]): boolean {
let compilerFilePath = normalizePath(sys.getExecutingFilePath());
let containingDirectoryPath = getDirectoryPath(compilerFilePath);
const compilerFilePath = normalizePath(sys.getExecutingFilePath());
const containingDirectoryPath = getDirectoryPath(compilerFilePath);
let filePath = combinePaths(containingDirectoryPath, language);
@@ -77,35 +85,122 @@ namespace ts {
}
function getDiagnosticText(message: DiagnosticMessage, ...args: any[]): string {
let diagnostic = createCompilerDiagnostic.apply(undefined, arguments);
const diagnostic = createCompilerDiagnostic.apply(undefined, arguments);
return <string>diagnostic.messageText;
}
function reportDiagnostic(diagnostic: Diagnostic) {
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 {
let output = "";
if (diagnostic.file) {
let loc = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
output += `${ diagnostic.file.fileName }(${ loc.line + 1 },${ loc.character + 1 }): `;
const { line, character } = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
const relativeFileName = getRelativeFileName(diagnostic.file.fileName, host);
output += `${ relativeFileName }(${ 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 }`;
sys.write(output);
}
function reportDiagnostics(diagnostics: Diagnostic[]) {
for (let i = 0; i < diagnostics.length; i++) {
reportDiagnostic(diagnostics[i]);
const redForegroundEscapeSequence = "\u001b[91m";
const yellowForegroundEscapeSequence = "\u001b[93m";
const blueForegroundEscapeSequence = "\u001b[93m";
const gutterStyleSequence = "\u001b[100;30m";
const gutterSeparator = " ";
const resetEscapeSequence = "\u001b[0m";
const elipsis = "...";
const categoryFormatMap: Map<string> = {
[DiagnosticCategory.Warning]: yellowForegroundEscapeSequence,
[DiagnosticCategory.Error]: redForegroundEscapeSequence,
[DiagnosticCategory.Message]: blueForegroundEscapeSequence,
};
function formatAndReset(text: string, formatStyle: string) {
return formatStyle + text + resetEscapeSequence;
}
function reportDiagnosticWithColorAndContext(diagnostic: Diagnostic, host: CompilerHost): void {
let output = "";
if (diagnostic.file) {
const { start, length, file } = diagnostic;
const { line: firstLine, character: firstLineChar } = getLineAndCharacterOfPosition(file, start);
const { line: lastLine, character: lastLineChar } = getLineAndCharacterOfPosition(file, start + length);
const lastLineInFile = getLineAndCharacterOfPosition(file, file.text.length).line;
const relativeFileName = getRelativeFileName(file.fileName, host);
const hasMoreThanFiveLines = (lastLine - firstLine) >= 4;
let gutterWidth = (lastLine + 1 + "").length;
if (hasMoreThanFiveLines) {
gutterWidth = Math.max(elipsis.length, gutterWidth);
}
output += sys.newLine;
for (let i = firstLine; i <= lastLine; i++) {
// If the error spans over 5 lines, we'll only show the first 2 and last 2 lines,
// so we'll skip ahead to the second-to-last line.
if (hasMoreThanFiveLines && firstLine + 1 < i && i < lastLine - 1) {
output += formatAndReset(padLeft(elipsis, gutterWidth), gutterStyleSequence) + gutterSeparator + sys.newLine;
i = lastLine - 1;
}
const lineStart = getPositionOfLineAndCharacter(file, i, 0);
const lineEnd = i < lastLineInFile ? getPositionOfLineAndCharacter(file, i + 1, 0) : file.text.length;
let lineContent = file.text.slice(lineStart, lineEnd);
lineContent = lineContent.replace(/\s+$/g, ""); // trim from end
lineContent = lineContent.replace("\t", " "); // convert tabs to single spaces
// Output the gutter and the actual contents of the line.
output += formatAndReset(padLeft(i + 1 + "", gutterWidth), gutterStyleSequence) + gutterSeparator;
output += lineContent + sys.newLine;
// Output the gutter and the error span for the line using tildes.
output += formatAndReset(padLeft("", gutterWidth), gutterStyleSequence) + gutterSeparator;
output += redForegroundEscapeSequence;
if (i === firstLine) {
// If we're on the last line, then limit it to the last character of the last line.
// Otherwise, we'll just squiggle the rest of the line, giving 'slice' no end position.
const lastCharForLine = i === lastLine ? lastLineChar : undefined;
output += lineContent.slice(0, firstLineChar).replace(/\S/g, " ");
output += lineContent.slice(firstLineChar, lastCharForLine).replace(/./g, "~");
}
else if (i === lastLine) {
output += lineContent.slice(0, lastLineChar).replace(/./g, "~");
}
else {
// Squiggle the entire line.
output += lineContent.replace(/./g, "~");
}
output += resetEscapeSequence;
output += sys.newLine;
}
output += sys.newLine;
output += `${ relativeFileName }(${ firstLine + 1 },${ firstLineChar + 1 }): `;
}
const categoryColor = categoryFormatMap[diagnostic.category];
const category = DiagnosticCategory[diagnostic.category].toLowerCase();
output += `${ formatAndReset(category, categoryColor) } TS${ diagnostic.code }: ${ flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine) }`;
output += sys.newLine + sys.newLine;
sys.write(output);
}
function reportWatchDiagnostic(diagnostic: Diagnostic) {
let output = new Date().toLocaleTimeString() + " - ";
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 }): `;
}
@@ -146,7 +241,7 @@ namespace ts {
}
export function executeCommandLine(args: string[]): void {
let commandLine = parseCommandLine(args);
const commandLine = parseCommandLine(args);
let configFileName: string; // Configuration file name (if any)
let cachedConfigFileText: string; // Cached configuration file text, used for reparsing (if any)
let configFileWatcher: FileWatcher; // Configuration file watcher
@@ -159,9 +254,14 @@ namespace ts {
let timerHandleForRecompilation: number; // Handle for 0.25s wait timer to trigger recompilation
let timerHandleForDirectoryChanges: number; // Handle for 0.25s wait timer to trigger directory change handler
// This map stores and reuses results of fileExists check that happen inside 'createProgram'
// This allows to save time in module resolution heavy scenarios when existence of the same file might be checked multiple times.
let cachedExistingFiles: Map<boolean>;
let hostFileExists: typeof compilerHost.fileExists;
if (commandLine.options.locale) {
if (!isJSONSupported()) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--locale"));
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--locale"), /* compilerHost */ undefined);
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
validateLocaleAndSetLanguage(commandLine.options.locale, commandLine.errors);
@@ -170,7 +270,7 @@ namespace ts {
// If there are any errors due to command line parsing and/or
// setting up localization, report them and quit.
if (commandLine.errors.length > 0) {
reportDiagnostics(commandLine.errors);
reportDiagnostics(commandLine.errors, compilerHost);
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
@@ -192,17 +292,17 @@ namespace ts {
if (commandLine.options.project) {
if (!isJSONSupported()) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--project"));
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--project"), /* compilerHost */ undefined);
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
configFileName = normalizePath(combinePaths(commandLine.options.project, "tsconfig.json"));
if (commandLine.fileNames.length !== 0) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line));
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line), /* compilerHost */ undefined);
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
}
else if (commandLine.fileNames.length === 0 && isJSONSupported()) {
let searchPath = normalizePath(sys.getCurrentDirectory());
const searchPath = normalizePath(sys.getCurrentDirectory());
configFileName = findConfigFile(searchPath);
}
@@ -215,14 +315,14 @@ namespace ts {
// Firefox has Object.prototype.watch
if (commandLine.options.watch && commandLine.options.hasOwnProperty("watch")) {
if (!sys.watchFile) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"));
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"), /* compilerHost */ undefined);
return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
if (configFileName) {
configFileWatcher = sys.watchFile(configFileName, configFileChanged);
}
if (sys.watchDirectory && configFileName) {
let directory = ts.getDirectoryPath(configFileName);
const directory = ts.getDirectoryPath(configFileName);
directoryWatcher = sys.watchDirectory(
// 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
@@ -240,18 +340,29 @@ namespace ts {
cachedConfigFileText = sys.readFile(configFileName);
}
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);
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
return;
}
}
if (!cachedConfigFileText) {
const error = createCompilerDiagnostic(Diagnostics.File_0_not_found, configFileName);
reportDiagnostics([error], /* compilerHost */ undefined);
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
return;
}
let result = parseConfigFileTextToJson(configFileName, cachedConfigFileText);
let configObject = result.config;
let configParseResult = parseJsonConfigFileContent(configObject, sys, getDirectoryPath(configFileName));
const result = parseConfigFileTextToJson(configFileName, cachedConfigFileText);
const configObject = result.config;
if (!configObject) {
reportDiagnostics([result.error], /* compilerHost */ undefined);
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
return;
}
const configParseResult = parseJsonConfigFileContent(configObject, sys, getDirectoryPath(configFileName));
if (configParseResult.errors.length > 0) {
reportDiagnostics(configParseResult.errors);
reportDiagnostics(configParseResult.errors, /* compilerHost */ undefined);
sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped);
return;
}
@@ -263,7 +374,7 @@ namespace ts {
if (!cachedProgram) {
if (configFileName) {
let configParseResult = parseConfigFile();
const configParseResult = parseConfigFile();
rootFileNames = configParseResult.fileNames;
compilerOptions = extend(commandLine.options, configParseResult.options);
}
@@ -274,9 +385,19 @@ namespace ts {
compilerHost = createCompilerHost(compilerOptions);
hostGetSourceFile = compilerHost.getSourceFile;
compilerHost.getSourceFile = getSourceFile;
hostFileExists = compilerHost.fileExists;
compilerHost.fileExists = cachedFileExists;
}
let compileResult = compile(rootFileNames, compilerOptions, compilerHost);
if (compilerOptions.pretty) {
reportDiagnostic = reportDiagnosticWithColorAndContext;
}
// reset the cache of existing files
cachedExistingFiles = {};
const compileResult = compile(rootFileNames, compilerOptions, compilerHost);
if (!compilerOptions.watch) {
return sys.exit(compileResult.exitStatus);
@@ -286,17 +407,24 @@ namespace ts {
reportWatchDiagnostic(createCompilerDiagnostic(Diagnostics.Compilation_complete_Watching_for_file_changes));
}
function cachedFileExists(fileName: string): boolean {
if (hasProperty(cachedExistingFiles, fileName)) {
return cachedExistingFiles[fileName];
}
return cachedExistingFiles[fileName] = hostFileExists(fileName);
}
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void) {
// Return existing SourceFile object if one is available
if (cachedProgram) {
let sourceFile = cachedProgram.getSourceFile(fileName);
const sourceFile = cachedProgram.getSourceFile(fileName);
// A modified source file has no watcher and should not be reused
if (sourceFile && sourceFile.fileWatcher) {
return sourceFile;
}
}
// Use default host function
let sourceFile = hostGetSourceFile(fileName, languageVersion, onError);
const sourceFile = hostGetSourceFile(fileName, languageVersion, onError);
if (sourceFile && compilerOptions.watch) {
// Attach a file watcher
sourceFile.fileWatcher = sys.watchFile(sourceFile.fileName, (fileName: string, removed?: boolean) => sourceFileChanged(sourceFile, removed));
@@ -307,7 +435,7 @@ namespace ts {
// Change cached program to the given program
function setCachedProgram(program: Program) {
if (cachedProgram) {
let newSourceFiles = program ? program.getSourceFiles() : undefined;
const newSourceFiles = program ? program.getSourceFiles() : undefined;
forEach(cachedProgram.getSourceFiles(), sourceFile => {
if (!(newSourceFiles && contains(newSourceFiles, sourceFile))) {
if (sourceFile.fileWatcher) {
@@ -325,7 +453,7 @@ namespace ts {
sourceFile.fileWatcher.close();
sourceFile.fileWatcher = undefined;
if (removed) {
let index = rootFileNames.indexOf(sourceFile.fileName);
const index = rootFileNames.indexOf(sourceFile.fileName);
if (index >= 0) {
rootFileNames.splice(index, 1);
}
@@ -356,11 +484,12 @@ namespace ts {
}
function directoryChangeHandler() {
let parsedCommandLine = parseConfigFile();
let newFileNames = ts.map(parsedCommandLine.fileNames, compilerHost.getCanonicalFileName);
let canonicalRootFileNames = ts.map(rootFileNames, compilerHost.getCanonicalFileName);
const parsedCommandLine = parseConfigFile();
const newFileNames = ts.map(parsedCommandLine.fileNames, compilerHost.getCanonicalFileName);
const canonicalRootFileNames = ts.map(rootFileNames, compilerHost.getCanonicalFileName);
if (!arrayStructurallyIsEqualTo(newFileNames, canonicalRootFileNames)) {
// 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())) {
setCachedProgram(undefined);
startTimerForRecompilation();
}
@@ -391,8 +520,8 @@ namespace ts {
checkTime = 0;
emitTime = 0;
let program = createProgram(fileNames, compilerOptions, compilerHost);
let exitStatus = compileProgram();
const program = createProgram(fileNames, compilerOptions, compilerHost);
const exitStatus = compileProgram();
if (compilerOptions.listFiles) {
forEach(program.getSourceFiles(), file => {
@@ -401,7 +530,7 @@ namespace ts {
}
if (compilerOptions.diagnostics) {
let memoryUsed = sys.getMemoryUsage ? sys.getMemoryUsage() : -1;
const memoryUsed = sys.getMemoryUsage ? sys.getMemoryUsage() : -1;
reportCountStatistic("Files", program.getSourceFiles().length);
reportCountStatistic("Lines", countLines(program));
reportCountStatistic("Nodes", program.getNodeCount());
@@ -444,7 +573,7 @@ namespace ts {
}
}
reportDiagnostics(diagnostics);
reportDiagnostics(diagnostics, compilerHost);
// If the user doesn't want us to emit, then we're done at this point.
if (compilerOptions.noEmit) {
@@ -454,8 +583,8 @@ namespace ts {
}
// Otherwise, emit and report any errors we ran into.
let emitOutput = program.emit();
reportDiagnostics(emitOutput.diagnostics);
const emitOutput = program.emit();
reportDiagnostics(emitOutput.diagnostics, compilerHost);
// If the emitter didn't emit anything, then pass that value along.
if (emitOutput.emitSkipped) {
@@ -480,8 +609,8 @@ namespace ts {
let output = "";
// We want to align our "syntax" and "examples" commands to a certain margin.
let syntaxLength = getDiagnosticText(Diagnostics.Syntax_Colon_0, "").length;
let examplesLength = getDiagnosticText(Diagnostics.Examples_Colon_0, "").length;
const syntaxLength = getDiagnosticText(Diagnostics.Syntax_Colon_0, "").length;
const examplesLength = getDiagnosticText(Diagnostics.Examples_Colon_0, "").length;
let marginLength = Math.max(syntaxLength, examplesLength);
// Build up the syntactic skeleton.
@@ -492,7 +621,7 @@ namespace ts {
output += sys.newLine + sys.newLine;
// 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 += padding + "tsc --out file.js file.ts" + sys.newLine;
output += padding + "tsc @args.txt" + sys.newLine;
@@ -501,17 +630,17 @@ namespace ts {
output += getDiagnosticText(Diagnostics.Options_Colon) + sys.newLine;
// 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()));
// We want our descriptions to align at the same column in our output,
// so we keep track of the longest option usage string.
marginLength = 0;
let usageColumn: string[] = []; // Things like "-d, --declaration" go in here.
let descriptionColumn: string[] = [];
const usageColumn: string[] = []; // Things like "-d, --declaration" go in here.
const descriptionColumn: string[] = [];
for (let i = 0; i < optsList.length; i++) {
let option = optsList[i];
const option = optsList[i];
// If an option lacks a description,
// it is not officially supported.
@@ -537,15 +666,15 @@ namespace ts {
}
// Special case that can't fit in the loop.
let usageText = " @<" + getDiagnosticText(Diagnostics.file) + ">";
const usageText = " @<" + getDiagnosticText(Diagnostics.file) + ">";
usageColumn.push(usageText);
descriptionColumn.push(getDiagnosticText(Diagnostics.Insert_command_line_options_and_files_from_a_file));
marginLength = Math.max(usageText.length, marginLength);
// Print out each row, aligning all the descriptions on the same column.
for (let i = 0; i < usageColumn.length; i++) {
let usage = usageColumn[i];
let description = descriptionColumn[i];
const usage = usageColumn[i];
const description = descriptionColumn[i];
output += usage + makePadding(marginLength - usage.length + 2) + description + sys.newLine;
}
@@ -565,14 +694,14 @@ namespace ts {
}
function writeConfigFile(options: CompilerOptions, fileNames: string[]) {
let currentDirectory = sys.getCurrentDirectory();
let file = combinePaths(currentDirectory, "tsconfig.json");
const currentDirectory = sys.getCurrentDirectory();
const file = normalizePath(combinePaths(currentDirectory, "tsconfig.json"));
if (sys.fileExists(file)) {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file));
reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file), /* compilerHost */ undefined);
}
else {
let compilerOptions = extend(options, defaultInitCompilerOptions);
let configurations: any = {
const compilerOptions = extend(options, defaultInitCompilerOptions);
const configurations: any = {
compilerOptions: serializeCompilerOptions(compilerOptions),
exclude: ["node_modules"]
};
@@ -583,18 +712,18 @@ namespace ts {
}
sys.writeFile(file, JSON.stringify(configurations, undefined, 4));
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Successfully_created_a_tsconfig_json_file));
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Successfully_created_a_tsconfig_json_file), /* compilerHost */ undefined);
}
return;
function serializeCompilerOptions(options: CompilerOptions): Map<string | number | boolean> {
let result: Map<string | number | boolean> = {};
let optionsNameMap = getOptionNameMap().optionNameMap;
const result: Map<string | number | boolean> = {};
const optionsNameMap = getOptionNameMap().optionNameMap;
for (let name in options) {
for (const name in options) {
if (hasProperty(options, name)) {
let value = options[name];
const value = options[name];
switch (name) {
case "init":
case "watch":
@@ -611,8 +740,8 @@ namespace ts {
}
else {
// Enum
let typeMap = <Map<number>>optionDefinition.type;
for (let key in typeMap) {
const typeMap = <Map<number>>optionDefinition.type;
for (const key in typeMap) {
if (hasProperty(typeMap, key)) {
if (typeMap[key] === value)
result[name] = key;
+2 -2
View File
@@ -11,6 +11,7 @@
"core.ts",
"sys.ts",
"types.ts",
"diagnosticInformationMap.generated.ts",
"scanner.ts",
"parser.ts",
"utilities.ts",
@@ -19,7 +20,6 @@
"emitter.ts",
"program.ts",
"commandLineParser.ts",
"tsc.ts",
"diagnosticInformationMap.generated.ts"
"tsc.ts"
]
}
+361 -83
View File
File diff suppressed because it is too large Load Diff
+373 -190
View File
File diff suppressed because it is too large Load Diff