Merge branch 'master' into fixDeFaultOfFindAllRefsToMaster

Conflicts:
	src/compiler/checker.ts
	src/compiler/types.ts
This commit is contained in:
Daniel Rosenwasser
2015-06-22 17:14:12 -07:00
1033 changed files with 29850 additions and 20845 deletions
+291 -13
View File
@@ -1,7 +1,7 @@
/// <reference path="parser.ts"/>
/* @internal */
module ts {
namespace ts {
export let bindTime = 0;
export const enum ModuleInstanceState {
@@ -88,12 +88,20 @@ module ts {
let container: Node;
let blockScopeContainer: Node;
let lastContainer: Node;
// 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 symbolCount = 0;
let Symbol = objectAllocator.getSymbolConstructor();
let classifiableNames: Map<string> = {};
if (!file.locals) {
bind(file);
file.symbolCount = symbolCount;
file.classifiableNames = classifiableNames;
}
return;
@@ -194,6 +202,11 @@ module ts {
symbol = hasProperty(symbolTable, name)
? symbolTable[name]
: (symbolTable[name] = createSymbol(SymbolFlags.None, name));
if (name && (includes & SymbolFlags.Classifiable)) {
classifiableNames[name] = name;
}
if (symbol.flags & excludes) {
if (node.name) {
node.name.parent = node;
@@ -338,6 +351,7 @@ module ts {
case SyntaxKind.ArrowFunction:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.SourceFile:
case SyntaxKind.TypeAliasDeclaration:
return ContainerFlags.IsContainerWithLocals;
case SyntaxKind.CatchClause:
@@ -385,10 +399,10 @@ module ts {
function declareSymbolAndAddToSymbolTableWorker(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags): Symbol {
switch (container.kind) {
// Modules, source files, and classes need specialized handling for how their
// Modules, source files, and classes need specialized handling for how their
// members are declared (for example, a member of a class will go into a specific
// symbol table depending on if it is static or not). As such, we defer to
// specialized handlers to take care of declaring these child members.
// symbol table depending on if it is static or not). We defer to specialized
// handlers to take care of declaring these child members.
case SyntaxKind.ModuleDeclaration:
return declareModuleMember(node, symbolFlags, symbolExcludes);
@@ -406,9 +420,10 @@ module ts {
case SyntaxKind.ObjectLiteralExpression:
case SyntaxKind.InterfaceDeclaration:
// Interface/Object-types always have their children added to the 'members' of
// their container. They are only accessible through an instance of their
// container, and are never in scope otherwise (even inside the body of the
// object / type / interface declaring them).
// their container. They are only accessible through an instance of their
// container, and are never in scope otherwise (even inside the body of the
// object / type / interface declaring them). An exception is type parameters,
// which are in scope without qualification (similar to 'locals').
return declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes);
case SyntaxKind.FunctionType:
@@ -424,11 +439,12 @@ module ts {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.TypeAliasDeclaration:
// All the children of these container types are never visible through another
// symbol (i.e. through another symbol's 'exports' or 'members'). Instead,
// they're only accessed 'lexically' (i.e. from code that exists underneath
// symbol (i.e. through another symbol's 'exports' or 'members'). Instead,
// they're only accessed 'lexically' (i.e. from code that exists underneath
// their container in the tree. To accomplish this, we simply add their declared
// symbol to the 'locals' of the container. These symbols can then be found as
// symbol to the 'locals' of the container. These symbols can then be found as
// the type checker walks up the containers, checking them for matching names.
return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes);
}
@@ -521,6 +537,51 @@ module ts {
typeLiteralSymbol.members = { [symbol.name]: symbol };
}
function bindObjectLiteralExpression(node: ObjectLiteralExpression) {
const enum ElementKind {
Property = 1,
Accessor = 2
}
if (inStrictMode) {
let seen: Map<ElementKind> = {};
for (let prop of node.properties) {
if (prop.name.kind !== SyntaxKind.Identifier) {
continue;
}
let 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
// a.This production is contained in strict code and IsDataDescriptor(previous) is true and
// IsDataDescriptor(propId.descriptor) is true.
// b.IsDataDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true.
// c.IsAccessorDescriptor(previous) is true and IsDataDescriptor(propId.descriptor) is true.
// d.IsAccessorDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true
// 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
? ElementKind.Property
: ElementKind.Accessor;
let existingKind = seen[identifier.text];
if (!existingKind) {
seen[identifier.text] = currentKind;
continue;
}
if (currentKind === ElementKind.Property && existingKind === ElementKind.Property) {
let 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));
}
}
}
return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__object");
}
function bindAnonymousDeclaration(node: Declaration, symbolFlags: SymbolFlags, name: string) {
let symbol = createSymbol(symbolFlags, name);
addDeclarationToSymbol(symbol, node, symbolFlags);
@@ -550,6 +611,138 @@ module ts {
bindBlockScopedDeclaration(node, SymbolFlags.BlockScopedVariable, SymbolFlags.BlockScopedVariableExcludes);
}
// The binder visits every node in the syntax tree so it is a convenient place to perform a single localized
// check for reserved words used as identifiers in strict mode code.
function checkStrictModeIdentifier(node: Identifier) {
if (inStrictMode &&
node.originalKeywordKind >= SyntaxKind.FirstFutureReservedWord &&
node.originalKeywordKind <= SyntaxKind.LastFutureReservedWord &&
!isIdentifierName(node)) {
// Report error only if there are no parse errors in file
if (!file.parseDiagnostics.length) {
file.bindDiagnostics.push(createDiagnosticForNode(node,
getStrictModeIdentifierMessage(node), declarationNameToString(node)));
}
}
}
function getStrictModeIdentifierMessage(node: Node) {
// Provide specialized messages to help the user understand why we think they're in
// strict mode.
if (getAncestor(node, SyntaxKind.ClassDeclaration) || getAncestor(node, SyntaxKind.ClassExpression)) {
return Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode;
}
if (file.externalModuleIndicator) {
return Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Modules_are_automatically_in_strict_mode;
}
return Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode;
}
function checkStrictModeBinaryExpression(node: BinaryExpression) {
if (inStrictMode && isLeftHandSideExpression(node.left) && isAssignmentOperator(node.operatorToken.kind)) {
// ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an
// Assignment operator(11.13) or of a PostfixExpression(11.3)
checkStrictModeEvalOrArguments(node, <Identifier>node.left);
}
}
function checkStrictModeCatchClause(node: CatchClause) {
// It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the
// Catch production is eval or arguments
if (inStrictMode && node.variableDeclaration) {
checkStrictModeEvalOrArguments(node, node.variableDeclaration.name);
}
}
function checkStrictModeDeleteExpression(node: DeleteExpression) {
// Grammar checking
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);
file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode));
}
}
function isEvalOrArgumentsIdentifier(node: Node): boolean {
return node.kind === SyntaxKind.Identifier &&
((<Identifier>node).text === "eval" || (<Identifier>node).text === "arguments");
}
function checkStrictModeEvalOrArguments(contextNode: Node, name: Node) {
if (name && name.kind === SyntaxKind.Identifier) {
let 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);
file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length,
getStrictModeEvalOrArgumentsMessage(contextNode), identifier.text));
}
}
}
function getStrictModeEvalOrArgumentsMessage(node: Node) {
// Provide specialized messages to help the user understand why we think they're in
// strict mode.
if (getAncestor(node, SyntaxKind.ClassDeclaration) || getAncestor(node, SyntaxKind.ClassExpression)) {
return Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode;
}
if (file.externalModuleIndicator) {
return Diagnostics.Invalid_use_of_0_Modules_are_automatically_in_strict_mode;
}
return Diagnostics.Invalid_use_of_0_in_strict_mode;
}
function checkStrictModeFunctionName(node: FunctionLikeDeclaration) {
if (inStrictMode) {
// It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a strict mode FunctionDeclaration or FunctionExpression (13.1))
checkStrictModeEvalOrArguments(node, node.name);
}
}
function checkStrictModeNumericLiteral(node: LiteralExpression) {
if (inStrictMode && node.flags & NodeFlags.OctalLiteral) {
file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Octal_literals_are_not_allowed_in_strict_mode));
}
}
function checkStrictModePostfixUnaryExpression(node: PostfixUnaryExpression) {
// Grammar checking
// The identifier eval or arguments may not appear as the LeftHandSideExpression of an
// Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression
// operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator.
if (inStrictMode) {
checkStrictModeEvalOrArguments(node, <Identifier>node.operand);
}
}
function checkStrictModePrefixUnaryExpression(node: PrefixUnaryExpression) {
// Grammar checking
if (inStrictMode) {
if (node.operator === SyntaxKind.PlusPlusToken || node.operator === SyntaxKind.MinusMinusToken) {
checkStrictModeEvalOrArguments(node, <Identifier>node.operand);
}
}
}
function checkStrictModeWithStatement(node: WithStatement) {
// Grammar checking for withStatement
if (inStrictMode) {
grammarErrorOnFirstToken(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);
file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2));
}
function getDestructuringParameterName(node: Declaration) {
return "__" + indexOf((<SignatureDeclaration>node.parent).parameters, node);
}
@@ -557,6 +750,11 @@ module ts {
function bind(node: Node) {
node.parent = parent;
var savedInStrictMode = inStrictMode;
if (!savedInStrictMode) {
updateStrictMode(node);
}
// First we bind declaration nodes to a symbol if possible. We'll both create a symbol
// and then potentially add the symbol to an appropriate symbol table. Possible
// destination symbol tables are:
@@ -574,10 +772,70 @@ module ts {
// the current 'container' node when it changes. This helps us know which symbol table
// a local should go into for example.
bindChildren(node);
inStrictMode = savedInStrictMode;
}
function updateStrictMode(node: Node) {
switch (node.kind) {
case SyntaxKind.SourceFile:
case SyntaxKind.ModuleBlock:
updateStrictModeStatementList((<SourceFile | ModuleBlock>node).statements);
return;
case SyntaxKind.Block:
if (isFunctionLike(node.parent)) {
updateStrictModeStatementList((<Block>node).statements);
}
return;
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
// All classes are automatically in strict mode in ES6.
inStrictMode = true;
return;
}
}
function updateStrictModeStatementList(statements: NodeArray<Statement>) {
for (let statement of statements) {
if (!isPrologueDirective(statement)) {
return;
}
if (isUseStrictPrologueDirective(<ExpressionStatement>statement)) {
inStrictMode = true;
return;
}
}
}
/// Should be called only on prologue directives (isPrologueDirective(node) should be true)
function isUseStrictPrologueDirective(node: ExpressionStatement): boolean {
let 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).
return nodeText === '"use strict"' || nodeText === "'use strict'";
}
function bindWorker(node: Node) {
switch (node.kind) {
case SyntaxKind.Identifier:
return checkStrictModeIdentifier(<Identifier>node);
case SyntaxKind.BinaryExpression:
return checkStrictModeBinaryExpression(<BinaryExpression>node);
case SyntaxKind.CatchClause:
return checkStrictModeCatchClause(<CatchClause>node);
case SyntaxKind.DeleteExpression:
return checkStrictModeDeleteExpression(<DeleteExpression>node);
case SyntaxKind.NumericLiteral:
return checkStrictModeNumericLiteral(<LiteralExpression>node);
case SyntaxKind.PostfixUnaryExpression:
return checkStrictModePostfixUnaryExpression(<PostfixUnaryExpression>node);
case SyntaxKind.PrefixUnaryExpression:
return checkStrictModePrefixUnaryExpression(<PrefixUnaryExpression>node);
case SyntaxKind.WithStatement:
return checkStrictModeWithStatement(<WithStatement>node);
case SyntaxKind.TypeParameter:
return declareSymbolAndAddToSymbolTable(<Declaration>node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes);
case SyntaxKind.Parameter:
@@ -606,6 +864,7 @@ module ts {
return bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.Method | ((<MethodDeclaration>node).questionToken ? SymbolFlags.Optional : SymbolFlags.None),
isObjectLiteralMethod(node) ? SymbolFlags.PropertyExcludes : SymbolFlags.MethodExcludes);
case SyntaxKind.FunctionDeclaration:
checkStrictModeFunctionName(<FunctionDeclaration>node);
return declareSymbolAndAddToSymbolTable(<Declaration>node, SymbolFlags.Function, SymbolFlags.FunctionExcludes);
case SyntaxKind.Constructor:
return declareSymbolAndAddToSymbolTable(<Declaration>node, SymbolFlags.Constructor, /*symbolExcludes:*/ SymbolFlags.None);
@@ -619,9 +878,10 @@ module ts {
case SyntaxKind.TypeLiteral:
return bindAnonymousDeclaration(<TypeLiteralNode>node, SymbolFlags.TypeLiteral, "__type");
case SyntaxKind.ObjectLiteralExpression:
return bindAnonymousDeclaration(<ObjectLiteralExpression>node, SymbolFlags.ObjectLiteral, "__object");
return bindObjectLiteralExpression(<ObjectLiteralExpression>node);
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
checkStrictModeFunctionName(<FunctionExpression>node);
return bindAnonymousDeclaration(<FunctionExpression>node, SymbolFlags.Function, "__function");
case SyntaxKind.ClassExpression:
case SyntaxKind.ClassDeclaration:
@@ -658,7 +918,11 @@ module ts {
}
function bindExportAssignment(node: ExportAssignment) {
if (node.expression.kind === SyntaxKind.Identifier) {
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) {
// 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);
}
@@ -669,7 +933,11 @@ module ts {
}
function bindExportDeclaration(node: ExportDeclaration) {
if (!node.exportClause) {
if (!container.symbol || !container.symbol.exports) {
// Export * in some sort of block construct
bindAnonymousDeclaration(node, SymbolFlags.ExportStar, getDeclarationName(node));
}
else if (!node.exportClause) {
// All export * declarations are collected in an __export symbol
declareSymbol(container.symbol.exports, container.symbol, node, SymbolFlags.ExportStar, SymbolFlags.None);
}
@@ -719,6 +987,10 @@ module ts {
}
function bindVariableDeclarationOrBindingElement(node: VariableDeclaration | BindingElement) {
if (inStrictMode) {
checkStrictModeEvalOrArguments(node, node.name)
}
if (!isBindingPattern(node.name)) {
if (isBlockOrCatchScoped(node)) {
bindBlockScopedVariableDeclaration(node);
@@ -742,6 +1014,12 @@ module ts {
}
function bindParameter(node: ParameterDeclaration) {
if (inStrictMode) {
// It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a
// strict mode FunctionLikeDeclaration or FunctionExpression(13.1)
checkStrictModeEvalOrArguments(node, node.name);
}
if (isBindingPattern(node.name)) {
bindAnonymousDeclaration(node, SymbolFlags.FunctionScopedVariable, getDestructuringParameterName(node));
}
+954 -847
View File
File diff suppressed because it is too large Load Diff
+14 -8
View File
@@ -3,7 +3,7 @@
/// <reference path="core.ts"/>
/// <reference path="scanner.ts"/>
module ts {
namespace ts {
/* @internal */
export var optionDeclarations: CommandLineOption[] = [
{
@@ -103,9 +103,14 @@ module ts {
name: "noResolve",
type: "boolean",
},
{
name: "skipDefaultLibCheck",
type: "boolean",
},
{
name: "out",
type: "string",
isFilePath: true,
description: Diagnostics.Concatenate_and_emit_output_to_single_file,
paramType: Diagnostics.FILE,
},
@@ -349,7 +354,7 @@ module ts {
return {
options: getCompilerOptions(),
fileNames: getFiles(),
fileNames: getFileNames(),
errors
};
@@ -395,23 +400,24 @@ module ts {
return options;
}
function getFiles(): string[] {
var files: string[] = [];
function getFileNames(): string[] {
var fileNames: string[] = [];
if (hasProperty(json, "files")) {
if (json["files"] instanceof Array) {
var files = map(<string[]>json["files"], s => combinePaths(basePath, s));
fileNames = map(<string[]>json["files"], s => combinePaths(basePath, s));
}
}
else {
var sysFiles = host.readDirectory(basePath, ".ts");
var exclude = json["exclude"] instanceof Array ? map(<string[]>json["exclude"], normalizeSlashes) : undefined;
var sysFiles = host.readDirectory(basePath, ".ts", exclude);
for (var i = 0; i < sysFiles.length; i++) {
var name = sysFiles[i];
if (!fileExtensionIs(name, ".d.ts") || !contains(sysFiles, name.substr(0, name.length - 5) + ".ts")) {
files.push(name);
fileNames.push(name);
}
}
}
return files;
return fileNames;
}
}
}
+38 -2
View File
@@ -1,7 +1,7 @@
/// <reference path="types.ts"/>
/* @internal */
module ts {
namespace ts {
// Ternary values are defined such that
// x & y is False if either x or y is False.
// x & y is Maybe if either x or y is Maybe, but neither x or y is False.
@@ -15,6 +15,42 @@ module ts {
True = -1
}
export function createFileMap<T>(getCanonicalFileName: (fileName: string) => string): FileMap<T> {
let files: Map<T> = {};
return {
get,
set,
contains,
remove,
forEachValue: forEachValueInMap
}
function set(fileName: string, value: T) {
files[normalizeKey(fileName)] = value;
}
function get(fileName: string) {
return files[normalizeKey(fileName)];
}
function contains(fileName: string) {
return hasProperty(files, normalizeKey(fileName));
}
function remove (fileName: string) {
let key = normalizeKey(fileName);
delete files[key];
}
function forEachValueInMap(f: (value: T) => void) {
forEachValue(files, f);
}
function normalizeKey(key: string) {
return getCanonicalFileName(normalizeSlashes(key));
}
}
export const enum Comparison {
LessThan = -1,
EqualTo = 0,
@@ -536,7 +572,7 @@ module ts {
export function getNormalizedPathComponents(path: string, currentDirectory: string) {
path = normalizeSlashes(path);
let rootLength = getRootLength(path);
if (rootLength == 0) {
if (rootLength === 0) {
// If the path is not rooted it is relative to current directory
path = combinePaths(normalizeSlashes(currentDirectory), path);
rootLength = getRootLength(path);
+7 -2
View File
@@ -1,7 +1,7 @@
/// <reference path="checker.ts"/>
/* @internal */
module ts {
namespace ts {
interface ModuleElementDeclarationEmitInfo {
node: Node;
outputPos: number;
@@ -709,7 +709,12 @@ module ts {
function writeModuleDeclaration(node: ModuleDeclaration) {
emitJsDocComments(node);
emitModuleElementDeclarationFlags(node);
write("module ");
if (node.flags & NodeFlags.Namespace) {
write("namespace ");
}
else {
write("module ");
}
writeTextOfNode(currentSourceFile, node.name);
while (node.body.kind !== SyntaxKind.ModuleBlock) {
node = <ModuleDeclaration>node.body;
@@ -1,7 +1,7 @@
// <auto-generated />
/// <reference path="types.ts" />
/* @internal */
module ts {
namespace ts {
export var Diagnostics = {
Unterminated_string_literal: { code: 1002, category: DiagnosticCategory.Error, key: "Unterminated string literal." },
Identifier_expected: { code: 1003, category: DiagnosticCategory.Error, key: "Identifier expected." },
@@ -171,14 +171,26 @@ module ts {
A_class_declaration_without_the_default_modifier_must_have_a_name: { code: 1211, category: DiagnosticCategory.Error, key: "A class declaration without the 'default' modifier must have a name" },
Identifier_expected_0_is_a_reserved_word_in_strict_mode: { code: 1212, category: DiagnosticCategory.Error, key: "Identifier expected. '{0}' is a reserved word in strict mode" },
Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode: { code: 1213, category: DiagnosticCategory.Error, key: "Identifier expected. '{0}' is a reserved word in strict mode. Class definitions are automatically in strict mode." },
Type_expected_0_is_a_reserved_word_in_strict_mode: { code: 1215, category: DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode" },
Type_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode: { code: 1216, category: DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode. Class definitions are automatically in strict mode." },
Identifier_expected_0_is_a_reserved_word_in_strict_mode_Modules_are_automatically_in_strict_mode: { code: 1214, category: DiagnosticCategory.Error, key: "Identifier expected. '{0}' is a reserved word in strict mode. Modules are automatically in strict mode." },
Invalid_use_of_0_Modules_are_automatically_in_strict_mode: { code: 1215, category: DiagnosticCategory.Error, key: "Invalid use of '{0}'. Modules are automatically in strict mode." },
Export_assignment_is_not_supported_when_module_flag_is_system: { code: 1218, category: DiagnosticCategory.Error, key: "Export assignment is not supported when '--module' flag is 'system'." },
Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Specify_experimentalDecorators_to_remove_this_warning: { code: 1219, category: DiagnosticCategory.Error, key: "Experimental support for decorators is a feature that is subject to change in a future release. Specify '--experimentalDecorators' to remove this warning." },
Generators_are_only_available_when_targeting_ECMAScript_6_or_higher: { code: 1220, category: DiagnosticCategory.Error, key: "Generators are only available when targeting ECMAScript 6 or higher." },
Generators_are_not_allowed_in_an_ambient_context: { code: 1221, category: DiagnosticCategory.Error, key: "Generators are not allowed in an ambient context." },
An_overload_signature_cannot_be_declared_as_a_generator: { code: 1222, category: DiagnosticCategory.Error, key: "An overload signature cannot be declared as a generator." },
_0_tag_already_specified: { code: 1223, category: DiagnosticCategory.Error, key: "'{0}' tag already specified." },
Signature_0_must_have_a_type_predicate: { code: 1224, category: DiagnosticCategory.Error, key: "Signature '{0}' must have a type predicate." },
Cannot_find_parameter_0: { code: 1225, category: DiagnosticCategory.Error, key: "Cannot find parameter '{0}'." },
Type_predicate_0_is_not_assignable_to_1: { code: 1226, category: DiagnosticCategory.Error, key: "Type predicate '{0}' is not assignable to '{1}'." },
Parameter_0_is_not_in_the_same_position_as_parameter_1: { code: 1227, category: DiagnosticCategory.Error, key: "Parameter '{0}' is not in the same position as parameter '{1}'." },
A_type_predicate_is_only_allowed_in_return_type_position_for_functions_and_methods: { code: 1228, category: DiagnosticCategory.Error, key: "A type predicate is only allowed in return type position for functions and methods." },
A_type_predicate_cannot_reference_a_rest_parameter: { code: 1229, category: DiagnosticCategory.Error, key: "A type predicate cannot reference a rest parameter." },
A_type_predicate_cannot_reference_element_0_in_a_binding_pattern: { code: 1230, category: DiagnosticCategory.Error, key: "A type predicate cannot reference element '{0}' in a binding pattern." },
An_export_assignment_can_only_be_used_in_a_module: { code: 1231, category: DiagnosticCategory.Error, key: "An export assignment can only be used in a module." },
An_import_declaration_can_only_be_used_in_a_namespace_or_module: { code: 1232, category: DiagnosticCategory.Error, key: "An import declaration can only be used in a namespace or module." },
An_export_declaration_can_only_be_used_in_a_module: { code: 1233, category: DiagnosticCategory.Error, key: "An export declaration can only be used in a module." },
An_ambient_module_declaration_is_only_allowed_at_the_top_level_in_a_file: { code: 1234, category: DiagnosticCategory.Error, key: "An ambient module declaration is only allowed at the top level in a file." },
A_namespace_declaration_is_only_allowed_in_a_namespace_or_module: { code: 1235, category: DiagnosticCategory.Error, key: "A namespace declaration is only allowed in a namespace or module." },
Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." },
Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." },
@@ -372,6 +384,11 @@ module ts {
Cannot_find_namespace_0: { code: 2503, category: DiagnosticCategory.Error, key: "Cannot find namespace '{0}'." },
No_best_common_type_exists_among_yield_expressions: { code: 2504, category: DiagnosticCategory.Error, key: "No best common type exists among yield expressions." },
A_generator_cannot_have_a_void_type_annotation: { code: 2505, category: DiagnosticCategory.Error, key: "A generator cannot have a 'void' type annotation." },
_0_is_referenced_directly_or_indirectly_in_its_own_base_expression: { code: 2506, category: DiagnosticCategory.Error, key: "'{0}' is referenced directly or indirectly in its own base expression." },
Type_0_is_not_a_constructor_function_type: { code: 2507, category: DiagnosticCategory.Error, key: "Type '{0}' is not a constructor function type." },
No_base_constructor_has_the_specified_number_of_type_arguments: { code: 2508, category: DiagnosticCategory.Error, key: "No base constructor has the specified number of type arguments." },
Base_constructor_return_type_0_is_not_a_class_or_interface_type: { code: 2509, category: DiagnosticCategory.Error, key: "Base constructor return type '{0}' is not a class or interface type." },
Base_constructors_must_all_have_the_same_return_type: { code: 2510, category: DiagnosticCategory.Error, key: "Base constructors must all have the same return type." },
Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." },
Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." },
Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using private name '{1}'." },
+74 -5
View File
@@ -671,14 +671,14 @@
"category": "Error",
"code": 1213
},
"Type expected. '{0}' is a reserved word in strict mode": {
"Identifier expected. '{0}' is a reserved word in strict mode. Modules are automatically in strict mode.": {
"category": "Error",
"code": 1214
},
"Invalid use of '{0}'. Modules are automatically in strict mode.": {
"category": "Error",
"code": 1215
},
"Type expected. '{0}' is a reserved word in strict mode. Class definitions are automatically in strict mode.": {
"category": "Error",
"code": 1216
},
"Export assignment is not supported when '--module' flag is 'system'.": {
"category": "Error",
"code": 1218
@@ -703,6 +703,55 @@
"category": "Error",
"code": 1223
},
"Signature '{0}' must have a type predicate.": {
"category": "Error",
"code": 1224
},
"Cannot find parameter '{0}'.": {
"category": "Error",
"code": 1225
},
"Type predicate '{0}' is not assignable to '{1}'.": {
"category": "Error",
"code": 1226
},
"Parameter '{0}' is not in the same position as parameter '{1}'.": {
"category": "Error",
"code": 1227
},
"A type predicate is only allowed in return type position for functions and methods.": {
"category": "Error",
"code": 1228
},
"A type predicate cannot reference a rest parameter.": {
"category": "Error",
"code": 1229
},
"A type predicate cannot reference element '{0}' in a binding pattern.": {
"category": "Error",
"code": 1230
},
"An export assignment can only be used in a module.": {
"category": "Error",
"code": 1231
},
"An import declaration can only be used in a namespace or module.": {
"category": "Error",
"code": 1232
},
"An export declaration can only be used in a module.": {
"category": "Error",
"code": 1233
},
"An ambient module declaration is only allowed at the top level in a file.": {
"category": "Error",
"code": 1234
},
"A namespace declaration is only allowed in a namespace or module.": {
"category": "Error",
"code": 1235
},
"Duplicate identifier '{0}'.": {
"category": "Error",
@@ -1476,6 +1525,26 @@
"category": "Error",
"code": 2505
},
"'{0}' is referenced directly or indirectly in its own base expression.": {
"category": "Error",
"code": 2506
},
"Type '{0}' is not a constructor function type.": {
"category": "Error",
"code": 2507
},
"No base constructor has the specified number of type arguments.": {
"category": "Error",
"code": 2508
},
"Base constructor return type '{0}' is not a class or interface type.": {
"category": "Error",
"code": 2509
},
"Base constructors must all have the same return type.": {
"category": "Error",
"code": 2510
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
+215 -244
View File
@@ -2,7 +2,7 @@
/// <reference path="declarationEmitter.ts"/>
/* @internal */
module ts {
namespace ts {
export function isExternalModuleOrDeclarationFile(sourceFile: SourceFile) {
return isExternalModule(sourceFile) || isDeclarationFile(sourceFile);
}
@@ -21,8 +21,7 @@ module ts {
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};`;
// emit output for the __decorate helper function
@@ -125,7 +124,6 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
let generatedNameSet: Map<string> = {};
let nodeToGeneratedName: string[] = [];
let blockScopedVariableToGeneratedName: string[];
let computedPropertyNamesToGeneratedNames: string[];
let extendsEmitted = false;
@@ -249,81 +247,44 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
}
function assignGeneratedName(node: Node, name: string) {
nodeToGeneratedName[getNodeId(node)] = unescapeIdentifier(name);
}
function generateNameForFunctionOrClassDeclaration(node: Declaration) {
if (!node.name) {
assignGeneratedName(node, makeUniqueName("default"));
}
}
function generateNameForModuleOrEnum(node: ModuleDeclaration | EnumDeclaration) {
if (node.name.kind === SyntaxKind.Identifier) {
let name = node.name.text;
// Use module/enum name itself if it is unique, otherwise make a unique variation
assignGeneratedName(node, isUniqueLocalName(name, node) ? name : makeUniqueName(name));
}
let name = node.name.text;
// Use module/enum name itself if it is unique, otherwise make a unique variation
return isUniqueLocalName(name, node) ? name : makeUniqueName(name);
}
function generateNameForImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration) {
let expr = getExternalModuleName(node);
let baseName = expr.kind === SyntaxKind.StringLiteral ?
escapeIdentifier(makeIdentifierFromModuleName((<LiteralExpression>expr).text)) : "module";
assignGeneratedName(node, makeUniqueName(baseName));
return makeUniqueName(baseName);
}
function generateNameForImportDeclaration(node: ImportDeclaration) {
if (node.importClause) {
generateNameForImportOrExportDeclaration(node);
}
}
function generateNameForExportDeclaration(node: ExportDeclaration) {
if (node.moduleSpecifier) {
generateNameForImportOrExportDeclaration(node);
}
}
function generateNameForExportAssignment(node: ExportAssignment) {
if (node.expression && node.expression.kind !== SyntaxKind.Identifier) {
assignGeneratedName(node, makeUniqueName("default"));
}
function generateNameForExportDefault() {
return makeUniqueName("default");
}
function generateNameForNode(node: Node) {
switch (node.kind) {
case SyntaxKind.Identifier:
return makeUniqueName((<Identifier>node).text);
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.EnumDeclaration:
return generateNameForModuleOrEnum(<ModuleDeclaration | EnumDeclaration>node);
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ExportDeclaration:
return generateNameForImportOrExportDeclaration(<ImportDeclaration | ExportDeclaration>node);
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
generateNameForFunctionOrClassDeclaration(<Declaration>node);
break;
case SyntaxKind.ModuleDeclaration:
generateNameForModuleOrEnum(<ModuleDeclaration>node);
generateNameForNode((<ModuleDeclaration>node).body);
break;
case SyntaxKind.EnumDeclaration:
generateNameForModuleOrEnum(<EnumDeclaration>node);
break;
case SyntaxKind.ImportDeclaration:
generateNameForImportDeclaration(<ImportDeclaration>node);
break;
case SyntaxKind.ExportDeclaration:
generateNameForExportDeclaration(<ExportDeclaration>node);
break;
case SyntaxKind.ExportAssignment:
generateNameForExportAssignment(<ExportAssignment>node);
break;
return generateNameForExportDefault();
}
}
function getGeneratedNameForNode(node: Node) {
let nodeId = getNodeId(node);
if (!nodeToGeneratedName[nodeId]) {
generateNameForNode(node);
}
return nodeToGeneratedName[nodeId];
let id = getNodeId(node);
return nodeToGeneratedName[id] || (nodeToGeneratedName[id] = unescapeIdentifier(generateNameForNode(node)));
}
function initializeEmitterWithSourceMaps() {
@@ -358,7 +319,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
let prevEncodedEmittedColumn = lastEncodedSourceMapSpan.emittedColumn;
// Line/Comma delimiters
if (lastEncodedSourceMapSpan.emittedLine == lastRecordedSourceMapSpan.emittedLine) {
if (lastEncodedSourceMapSpan.emittedLine === lastRecordedSourceMapSpan.emittedLine) {
// Emit comma to separate the entry
if (sourceMapData.sourceMapMappings) {
sourceMapData.sourceMapMappings += ",";
@@ -441,8 +402,8 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
// If this location wasn't recorded or the location in source is going backwards, record the span
if (!lastRecordedSourceMapSpan ||
lastRecordedSourceMapSpan.emittedLine != emittedLine ||
lastRecordedSourceMapSpan.emittedColumn != emittedColumn ||
lastRecordedSourceMapSpan.emittedLine !== emittedLine ||
lastRecordedSourceMapSpan.emittedColumn !== emittedColumn ||
(lastRecordedSourceMapSpan.sourceIndex === sourceMapSourceIndex &&
(lastRecordedSourceMapSpan.sourceLine > sourceLinePos.line ||
(lastRecordedSourceMapSpan.sourceLine === sourceLinePos.line && lastRecordedSourceMapSpan.sourceColumn > sourceLinePos.character)))) {
@@ -687,19 +648,19 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
sourceMapDir = getDirectoryPath(normalizePath(jsFilePath));
}
function emitNodeWithSourceMap(node: Node, allowGeneratedIdentifiers?: boolean) {
function emitNodeWithSourceMap(node: Node) {
if (node) {
if (nodeIsSynthesized(node)) {
return emitNodeWithoutSourceMap(node, /*allowGeneratedIdentifiers*/ false);
return emitNodeWithoutSourceMap(node);
}
if (node.kind != SyntaxKind.SourceFile) {
if (node.kind !== SyntaxKind.SourceFile) {
recordEmitNodeStartSpan(node);
emitNodeWithoutSourceMap(node, allowGeneratedIdentifiers);
emitNodeWithoutSourceMap(node);
recordEmitNodeEndSpan(node);
}
else {
recordNewSourceFileStart(<SourceFile>node);
emitNodeWithoutSourceMap(node, /*allowGeneratedIdentifiers*/ false);
emitNodeWithoutSourceMap(node);
}
}
}
@@ -1201,80 +1162,129 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
}
function isNotExpressionIdentifier(node: Identifier) {
function isExpressionIdentifier(node: Node): boolean {
let parent = node.parent;
switch (parent.kind) {
case SyntaxKind.Parameter:
case SyntaxKind.VariableDeclaration:
case SyntaxKind.BindingElement:
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.ShorthandPropertyAssignment:
case SyntaxKind.EnumMember:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.ImportClause:
case SyntaxKind.NamespaceImport:
return (<Declaration>parent).name === node;
case SyntaxKind.ImportSpecifier:
case SyntaxKind.ExportSpecifier:
return (<ImportOrExportSpecifier>parent).name === node || (<ImportOrExportSpecifier>parent).propertyName === node;
case SyntaxKind.BreakStatement:
case SyntaxKind.ContinueStatement:
case SyntaxKind.ArrayLiteralExpression:
case SyntaxKind.BinaryExpression:
case SyntaxKind.CallExpression:
case SyntaxKind.CaseClause:
case SyntaxKind.ComputedPropertyName:
case SyntaxKind.ConditionalExpression:
case SyntaxKind.Decorator:
case SyntaxKind.DeleteExpression:
case SyntaxKind.DoStatement:
case SyntaxKind.ElementAccessExpression:
case SyntaxKind.ExportAssignment:
return false;
case SyntaxKind.LabeledStatement:
return (<LabeledStatement>node.parent).label === node;
case SyntaxKind.ExpressionStatement:
case SyntaxKind.ExpressionWithTypeArguments:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.NewExpression:
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.PostfixUnaryExpression:
case SyntaxKind.PrefixUnaryExpression:
case SyntaxKind.ReturnStatement:
case SyntaxKind.ShorthandPropertyAssignment:
case SyntaxKind.SpreadElementExpression:
case SyntaxKind.SwitchStatement:
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.TemplateSpan:
case SyntaxKind.ThrowStatement:
case SyntaxKind.TypeAssertionExpression:
case SyntaxKind.TypeOfExpression:
case SyntaxKind.VoidExpression:
case SyntaxKind.WhileStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.YieldExpression:
return true;
case SyntaxKind.BindingElement:
case SyntaxKind.EnumMember:
case SyntaxKind.Parameter:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.VariableDeclaration:
return (<BindingElement | EnumMember | ParameterDeclaration | PropertyAssignment | PropertyDeclaration | VariableDeclaration>parent).initializer === node;
case SyntaxKind.PropertyAccessExpression:
return (<ExpressionStatement>parent).expression === node;
case SyntaxKind.ArrowFunction:
case SyntaxKind.FunctionExpression:
return (<FunctionLikeDeclaration>parent).body === node;
case SyntaxKind.ImportEqualsDeclaration:
return (<ImportEqualsDeclaration>parent).moduleReference === node;
case SyntaxKind.QualifiedName:
return (<QualifiedName>parent).left === node;
}
return false;
}
function emitExpressionIdentifier(node: Identifier) {
let substitution = resolver.getExpressionNameSubstitution(node, getGeneratedNameForNode);
if (substitution) {
write(substitution);
let container = resolver.getReferencedExportContainer(node);
if (container) {
if (container.kind === SyntaxKind.SourceFile) {
// Identifier references module export
if (languageVersion < ScriptTarget.ES6 && compilerOptions.module !== ModuleKind.System) {
write("exports.");
}
}
else {
// Identifier references namespace export
write(getGeneratedNameForNode(container));
write(".");
}
}
else {
writeTextOfNode(currentSourceFile, node);
}
}
function getGeneratedNameForIdentifier(node: Identifier): string {
if (nodeIsSynthesized(node) || !blockScopedVariableToGeneratedName) {
return undefined;
}
var variableId = resolver.getBlockScopedVariableId(node)
if (variableId === undefined) {
return undefined;
}
return blockScopedVariableToGeneratedName[variableId];
}
function emitIdentifier(node: Identifier, allowGeneratedIdentifiers: boolean) {
if (allowGeneratedIdentifiers) {
let generatedName = getGeneratedNameForIdentifier(node);
if (generatedName) {
write(generatedName);
else if (languageVersion < ScriptTarget.ES6) {
let declaration = resolver.getReferencedImportDeclaration(node);
if (declaration) {
if (declaration.kind === SyntaxKind.ImportClause) {
// Identifier references default import
write(getGeneratedNameForNode(<ImportDeclaration>declaration.parent));
write(languageVersion === ScriptTarget.ES3 ? '["default"]' : ".default");
return;
}
else if (declaration.kind === SyntaxKind.ImportSpecifier) {
// Identifier references named import
write(getGeneratedNameForNode(<ImportDeclaration>declaration.parent.parent.parent));
write(".");
writeTextOfNode(currentSourceFile, (<ImportSpecifier>declaration).propertyName || (<ImportSpecifier>declaration).name);
return;
}
}
declaration = resolver.getReferencedNestedRedeclaration(node);
if (declaration) {
write(getGeneratedNameForNode(declaration.name));
return;
}
}
writeTextOfNode(currentSourceFile, node);
}
function isNameOfNestedRedeclaration(node: Identifier) {
if (languageVersion < ScriptTarget.ES6) {
let parent = node.parent;
switch (parent.kind) {
case SyntaxKind.BindingElement:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.VariableDeclaration:
return (<Declaration>parent).name === node && resolver.isNestedRedeclaration(<Declaration>parent);
}
}
return false;
}
function emitIdentifier(node: Identifier) {
if (!node.parent) {
write(node.text);
}
else if (!isNotExpressionIdentifier(node)) {
else if (isExpressionIdentifier(node)) {
emitExpressionIdentifier(node);
}
else if (isNameOfNestedRedeclaration(node)) {
write(getGeneratedNameForNode(node));
}
else {
writeTextOfNode(currentSourceFile, node);
}
@@ -1320,7 +1330,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
function emitBindingElement(node: BindingElement) {
if (node.propertyName) {
emit(node.propertyName, /*allowGeneratedIdentifiers*/ false);
emit(node.propertyName);
write(": ");
}
if (node.dotDotDotToken) {
@@ -1646,6 +1656,12 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
function parenthesizeForAccess(expr: Expression): LeftHandSideExpression {
// When diagnosing whether the expression needs parentheses, the decision should be based
// on the innermost expression in a chain of nested type assertions.
while (expr.kind === SyntaxKind.TypeAssertionExpression) {
expr = (<TypeAssertion>expr).expression;
}
// isLeftHandSideExpression is almost the correct criterion for when it is not necessary
// to parenthesize the expression before a dot. The known exceptions are:
//
@@ -1654,7 +1670,10 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
// NumberLiteral
// 1.x -> not the same as (1).x
//
if (isLeftHandSideExpression(expr) && expr.kind !== SyntaxKind.NewExpression && expr.kind !== SyntaxKind.NumericLiteral) {
if (isLeftHandSideExpression(expr) &&
expr.kind !== SyntaxKind.NewExpression &&
expr.kind !== SyntaxKind.NumericLiteral) {
return <LeftHandSideExpression>expr;
}
let node = <ParenthesizedExpression>createSynthesizedNode(SyntaxKind.ParenthesizedExpression);
@@ -1673,7 +1692,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
write("*");
}
emit(node.name, /*allowGeneratedIdentifiers*/ false);
emit(node.name);
if (languageVersion < ScriptTarget.ES6) {
write(": function ");
}
@@ -1681,40 +1700,34 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
function emitPropertyAssignment(node: PropertyDeclaration) {
emit(node.name, /*allowGeneratedIdentifiers*/ false);
emit(node.name);
write(": ");
emit(node.initializer);
}
// Return true if identifier resolves to an exported member of a namespace
function isNamespaceExportReference(node: Identifier) {
let container = resolver.getReferencedExportContainer(node);
return container && container.kind !== SyntaxKind.SourceFile;
}
function emitShorthandPropertyAssignment(node: ShorthandPropertyAssignment) {
emit(node.name, /*allowGeneratedIdentifiers*/ false);
// If short-hand property has a prefix, then regardless of the target version, we will emit it as normal property assignment. For example:
// module m {
// export let y;
// }
// module m {
// export let obj = { y };
// }
// The short-hand property in obj need to emit as such ... = { y : m.y } regardless of the TargetScript version
if (languageVersion < ScriptTarget.ES6) {
// The name property of a short-hand property assignment is considered an expression position, so here
// we manually emit the identifier to avoid rewriting.
writeTextOfNode(currentSourceFile, node.name);
// If emitting pre-ES6 code, or if the name requires rewriting when resolved as an expression identifier,
// we emit a normal property assignment. For example:
// module m {
// export let y;
// }
// module m {
// let obj = { y };
// }
// Here we need to emit obj = { y : m.y } regardless of the output target.
if (languageVersion < ScriptTarget.ES6 || isNamespaceExportReference(node.name)) {
// Emit identifier as an identifier
write(": ");
var generatedName = getGeneratedNameForIdentifier(node.name);
if (generatedName) {
write(generatedName);
}
else {
// Even though this is stored as identifier treat it as an expression
// Short-hand, { x }, is equivalent of normal form { x: x }
emitExpressionIdentifier(node.name);
}
}
else if (resolver.getExpressionNameSubstitution(node.name, getGeneratedNameForNode)) {
// Emit identifier as an identifier
write(": ");
// Even though this is stored as identifier treat it as an expression
// Short-hand, { x }, is equivalent of normal form { x: x }
emitExpressionIdentifier(node.name);
emit(node.name);
}
}
@@ -1767,7 +1780,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
let indentedBeforeDot = indentIfOnDifferentLines(node, node.expression, node.dotToken);
write(".");
let indentedAfterDot = indentIfOnDifferentLines(node, node.dotToken, node.name);
emit(node.name, /*allowGeneratedIdentifiers*/ false);
emit(node.name);
decreaseIndentIf(indentedBeforeDot, indentedAfterDot);
}
@@ -1889,23 +1902,21 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
function emitNewExpression(node: NewExpression) {
write("new ");
// Spread operator logic can be supported in new expressions in ES5 using a combination
// Spread operator logic is supported in new expressions in ES5 using a combination
// of Function.prototype.bind() and Function.prototype.apply().
//
// Example:
//
// var arguments = [1, 2, 3, 4, 5];
// new Array(...arguments);
// var args = [1, 2, 3, 4, 5];
// new Array(...args);
//
// Could be transpiled into ES5:
// is compiled into the following ES5:
//
// var arguments = [1, 2, 3, 4, 5];
// new (Array.bind.apply(Array, [void 0].concat(arguments)));
// var args = [1, 2, 3, 4, 5];
// new (Array.bind.apply(Array, [void 0].concat(args)));
//
// `[void 0]` is the first argument which represents `thisArg` to the bind method above.
// And `thisArg` will be set to the return value of the constructor when instantiated
// with the new operator — regardless of any value we set `thisArg` to. Thus, we set it
// to an undefined, `void 0`.
// The 'thisArg' to 'bind' is ignored when invoking the result of 'bind' with 'new',
// Thus, we set it to undefined ('void 0').
if (languageVersion === ScriptTarget.ES5 &&
node.arguments &&
hasSpreadElement(node.arguments)) {
@@ -1941,13 +1952,16 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
function emitParenExpression(node: ParenthesizedExpression) {
if (!node.parent || node.parent.kind !== SyntaxKind.ArrowFunction) {
// If the node is synthesized, it means the emitter put the parentheses there,
// not the user. If we didn't want them, the emitter would not have put them
// there.
if (!nodeIsSynthesized(node) && node.parent.kind !== SyntaxKind.ArrowFunction) {
if (node.expression.kind === SyntaxKind.TypeAssertionExpression) {
let operand = (<TypeAssertion>node.expression).expression;
// Make sure we consider all nested cast expressions, e.g.:
// (<any><number><any>-A).x;
while (operand.kind == SyntaxKind.TypeAssertionExpression) {
while (operand.kind === SyntaxKind.TypeAssertionExpression) {
operand = (<TypeAssertion>operand).expression;
}
@@ -2769,8 +2783,6 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
write(", ");
}
renameNonTopLevelLetAndConst(name);
const isVariableDeclarationOrBindingElement =
name.parent && (name.parent.kind === SyntaxKind.VariableDeclaration || name.parent.kind === SyntaxKind.BindingElement);
@@ -2838,11 +2850,14 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
function createPropertyAccessForDestructuringProperty(object: Expression, propName: Identifier | LiteralExpression): Expression {
if (propName.kind !== SyntaxKind.Identifier) {
return createElementAccessExpression(object, propName);
// We create a synthetic copy of the identifier in order to avoid the rewriting that might
// otherwise occur when the identifier is emitted.
let syntheticName = <Identifier | LiteralExpression>createSynthesizedNode(propName.kind);
syntheticName.text = propName.text;
if (syntheticName.kind !== SyntaxKind.Identifier) {
return createElementAccessExpression(object, syntheticName);
}
return createPropertyAccessExpression(object, propName);
return createPropertyAccessExpression(object, syntheticName);
}
function createSliceCall(value: Expression, sliceIndex: number): CallExpression {
@@ -2864,8 +2879,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
for (let p of properties) {
if (p.kind === SyntaxKind.PropertyAssignment || p.kind === SyntaxKind.ShorthandPropertyAssignment) {
// TODO(andersh): Computed property support
let propName = <Identifier | LiteralExpression>((<PropertyAssignment>p).name);
let propName = <Identifier | LiteralExpression>(<PropertyAssignment>p).name;
emitDestructuringAssignment((<PropertyAssignment>p).initializer || propName, createPropertyAccessForDestructuringProperty(value, propName));
}
}
@@ -2979,8 +2993,6 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
}
else {
renameNonTopLevelLetAndConst(<Identifier>node.name);
let initializer = node.initializer;
if (!initializer && languageVersion < ScriptTarget.ES6) {
@@ -3040,54 +3052,6 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
return getCombinedNodeFlags(node.parent);
}
function renameNonTopLevelLetAndConst(node: Node): void {
// do not rename if
// - language version is ES6+
// - node is synthesized
// - node is not identifier (can happen when tree is malformed)
// - node is definitely not name of variable declaration.
// it still can be part of parameter declaration, this check will be done next
if (languageVersion >= ScriptTarget.ES6 ||
nodeIsSynthesized(node) ||
node.kind !== SyntaxKind.Identifier ||
(node.parent.kind !== SyntaxKind.VariableDeclaration && node.parent.kind !== SyntaxKind.BindingElement)) {
return;
}
let combinedFlags = getCombinedFlagsForIdentifier(<Identifier>node);
if (((combinedFlags & NodeFlags.BlockScoped) === 0) || combinedFlags & NodeFlags.Export) {
// do not rename exported or non-block scoped variables
return;
}
// here it is known that node is a block scoped variable
let list = getAncestor(node, SyntaxKind.VariableDeclarationList);
if (list.parent.kind === SyntaxKind.VariableStatement) {
let isSourceFileLevelBinding = list.parent.parent.kind === SyntaxKind.SourceFile;
let isModuleLevelBinding = list.parent.parent.kind === SyntaxKind.ModuleBlock;
let isFunctionLevelBinding =
list.parent.parent.kind === SyntaxKind.Block && isFunctionLike(list.parent.parent.parent);
if (isSourceFileLevelBinding || isModuleLevelBinding || isFunctionLevelBinding) {
return;
}
}
let blockScopeContainer = getEnclosingBlockScopeContainer(node);
let parent = blockScopeContainer.kind === SyntaxKind.SourceFile
? blockScopeContainer
: blockScopeContainer.parent;
if (resolver.resolvesToSomeValue(parent, (<Identifier>node).text)) {
let variableId = resolver.getBlockScopedVariableId(<Identifier>node);
if (!blockScopedVariableToGeneratedName) {
blockScopedVariableToGeneratedName = [];
}
let generatedName = makeUniqueName((<Identifier>node).text);
blockScopedVariableToGeneratedName[variableId] = generatedName;
}
}
function isES6ExportedDeclaration(node: Node) {
return !!(node.flags & NodeFlags.Export) &&
languageVersion >= ScriptTarget.ES6 &&
@@ -3251,7 +3215,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
function emitAccessor(node: AccessorDeclaration) {
write(node.kind === SyntaxKind.GetAccessor ? "get " : "set ");
emit(node.name, /*allowGeneratedIdentifiers*/ false);
emit(node.name);
emitSignatureAndBody(node);
}
@@ -4354,7 +4318,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
let argumentsWritten = 0;
if (compilerOptions.emitDecoratorMetadata) {
if (shouldEmitTypeMetadata(node)) {
var serializedType = resolver.serializeTypeOfNode(node, getGeneratedNameForNode);
var serializedType = resolver.serializeTypeOfNode(node);
if (serializedType) {
if (writeComma) {
write(", ");
@@ -4367,7 +4331,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
}
if (shouldEmitParamTypesMetadata(node)) {
var serializedTypes = resolver.serializeParameterTypesOfNode(node, getGeneratedNameForNode);
var serializedTypes = resolver.serializeParameterTypesOfNode(node);
if (serializedTypes) {
if (writeComma || argumentsWritten) {
write(", ");
@@ -4385,7 +4349,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
}
if (shouldEmitReturnTypeMetadata(node)) {
var serializedType = resolver.serializeReturnTypeOfNode(node, getGeneratedNameForNode);
var serializedType = resolver.serializeReturnTypeOfNode(node);
if (serializedType) {
if (writeComma || argumentsWritten) {
write(", ");
@@ -4491,7 +4455,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
emitDeclarationName(node);
write(`", `);
emitDeclarationName(node);
write(")");
write(");");
}
emitExportMemberAssignments(node.name);
}
@@ -4612,7 +4576,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
emitDeclarationName(node);
write(`", `);
emitDeclarationName(node);
write(")");
write(");");
}
emitExportMemberAssignments(<Identifier>node.name);
}
@@ -4983,13 +4947,16 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
}
}
function getLocalNameForExternalImport(importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration): string {
let namespaceDeclaration = getNamespaceDeclarationNode(importNode);
if (namespaceDeclaration && !isDefaultImport(importNode)) {
function getLocalNameForExternalImport(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration): string {
let namespaceDeclaration = getNamespaceDeclarationNode(node);
if (namespaceDeclaration && !isDefaultImport(node)) {
return getSourceTextOfNodeFromSourceFile(currentSourceFile, namespaceDeclaration.name);
}
else {
return getGeneratedNameForNode(<ImportDeclaration | ExportDeclaration>importNode);
if (node.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node).importClause) {
return getGeneratedNameForNode(node);
}
if (node.kind === SyntaxKind.ExportDeclaration && (<ExportDeclaration>node).moduleSpecifier) {
return getGeneratedNameForNode(node);
}
}
@@ -5377,10 +5344,10 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
emitSetters(exportStarFunction);
writeLine();
emitExecute(node, startIndex);
emitTempDeclarations(/*newLine*/ true)
decreaseIndent();
writeLine();
write("}"); // return
emitTempDeclarations(/*newLine*/ true);
}
function emitSetters(exportStarFunction: string) {
@@ -5527,7 +5494,11 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
Debug.assert(!exportFunctionForFile);
// make sure that name of 'exports' function does not conflict with existing identifiers
exportFunctionForFile = makeUniqueName("exports");
write("System.register([");
write("System.register(");
if (node.moduleName) {
write(`"${node.moduleName}", `);
}
write("[")
for (let i = 0; i < externalImports.length; ++i) {
let text = getExternalModuleNameText(externalImports[i]);
if (i !== 0) {
@@ -5613,8 +5584,8 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
writeLine();
write("define(");
if (node.amdModuleName) {
write("\"" + node.amdModuleName + "\", ");
if (node.moduleName) {
write("\"" + node.moduleName + "\", ");
}
emitAMDDependencies(node, /*includeNonAmdDependencies*/ true);
write(") {");
@@ -5774,7 +5745,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
emitLeadingComments(node.endOfFileToken);
}
function emitNodeWithoutSourceMap(node: Node, allowGeneratedIdentifiers?: boolean): void {
function emitNodeWithoutSourceMap(node: Node): void {
if (!node) {
return;
}
@@ -5788,7 +5759,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
emitLeadingComments(node);
}
emitJavaScriptWorker(node, allowGeneratedIdentifiers);
emitJavaScriptWorker(node);
if (emitComments) {
emitTrailingComments(node);
@@ -5838,11 +5809,11 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
return true;
}
function emitJavaScriptWorker(node: Node, allowGeneratedIdentifiers: boolean = true) {
function emitJavaScriptWorker(node: Node) {
// Check if the node can be emitted regardless of the ScriptTarget
switch (node.kind) {
case SyntaxKind.Identifier:
return emitIdentifier(<Identifier>node, allowGeneratedIdentifiers);
return emitIdentifier(<Identifier>node);
case SyntaxKind.Parameter:
return emitParameter(<ParameterDeclaration>node);
case SyntaxKind.MethodDeclaration:
+140 -175
View File
@@ -1,7 +1,7 @@
/// <reference path="scanner.ts"/>
/// <reference path="utilities.ts"/>
module ts {
namespace ts {
let nodeConstructors = new Array<new () => Node>(SyntaxKind.Count);
/* @internal */ export let parseTime = 0;
@@ -103,6 +103,9 @@ module ts {
case SyntaxKind.TypeReference:
return visitNode(cbNode, (<TypeReferenceNode>node).typeName) ||
visitNodes(cbNodes, (<TypeReferenceNode>node).typeArguments);
case SyntaxKind.TypePredicate:
return visitNode(cbNode, (<TypePredicateNode>node).parameterName) ||
visitNode(cbNode, (<TypePredicateNode>node).type);
case SyntaxKind.TypeQuery:
return visitNode(cbNode, (<TypeQueryNode>node).exprName);
case SyntaxKind.TypeLiteral:
@@ -255,6 +258,7 @@ module ts {
return visitNodes(cbNodes, node.decorators) ||
visitNodes(cbNodes, node.modifiers) ||
visitNode(cbNode, (<TypeAliasDeclaration>node).name) ||
visitNodes(cbNodes, (<TypeAliasDeclaration>node).typeParameters) ||
visitNode(cbNode, (<TypeAliasDeclaration>node).type);
case SyntaxKind.EnumDeclaration:
return visitNodes(cbNodes, node.decorators) ||
@@ -491,13 +495,6 @@ module ts {
// attached to the EOF token.
let parseErrorBeforeNextFinishedNode: boolean = false;
export const enum StatementFlags {
None = 0,
Statement = 1,
ModuleElement = 2,
StatementOrModuleElement = Statement | ModuleElement
}
export function parseSourceFile(fileName: string, _sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, setParentNodes?: boolean): SourceFile {
initializeState(fileName, _sourceText, languageVersion, _syntaxCursor);
@@ -547,7 +544,7 @@ module ts {
token = nextToken();
processReferenceComments(sourceFile);
sourceFile.statements = parseList(ParsingContext.SourceElements, /*checkForStrictMode*/ true, parseSourceElement);
sourceFile.statements = parseList(ParsingContext.SourceElements, parseStatement);
Debug.assert(token === SyntaxKind.EndOfFileToken);
sourceFile.endOfFileToken = parseTokenNode();
@@ -650,10 +647,6 @@ module ts {
}
}
function setStrictModeContext(val: boolean) {
setContextFlag(val, ParserContextFlags.StrictMode);
}
function setDisallowInContext(val: boolean) {
setContextFlag(val, ParserContextFlags.DisallowIn);
}
@@ -747,10 +740,6 @@ module ts {
return (contextFlags & ParserContextFlags.Yield) !== 0;
}
function inStrictModeContext() {
return (contextFlags & ParserContextFlags.StrictMode) !== 0;
}
function inGeneratorParameterContext() {
return (contextFlags & ParserContextFlags.GeneratorParameter) !== 0;
}
@@ -1125,17 +1114,14 @@ module ts {
switch (parsingContext) {
case ParsingContext.SourceElements:
case ParsingContext.ModuleElements:
case ParsingContext.BlockStatements:
case ParsingContext.SwitchClauseStatements:
// If we're in error recovery, then we don't want to treat ';' as an empty statement.
// The problem is that ';' can show up in far too many contexts, and if we see one
// and assume it's a statement, then we may bail out inappropriately from whatever
// we're parsing. For example, if we have a semicolon in the middle of a class, then
// we really don't want to assume the class is over and we're on a statement in the
// outer module. We just want to consume and move on.
return !(token === SyntaxKind.SemicolonToken && inErrorRecovery) && isStartOfModuleElement();
case ParsingContext.BlockStatements:
case ParsingContext.SwitchClauseStatements:
// During error recovery we don't treat empty statements as statements
return !(token === SyntaxKind.SemicolonToken && inErrorRecovery) && isStartOfStatement();
case ParsingContext.SwitchClauses:
return token === SyntaxKind.CaseKeyword || token === SyntaxKind.DefaultKeyword;
@@ -1246,7 +1232,6 @@ module ts {
}
switch (kind) {
case ParsingContext.ModuleElements:
case ParsingContext.BlockStatements:
case ParsingContext.SwitchClauses:
case ParsingContext.TypeMembers:
@@ -1330,31 +1315,17 @@ module ts {
}
// Parses a list of elements
function parseList<T extends Node>(kind: ParsingContext, checkForStrictMode: boolean, parseElement: () => T): NodeArray<T> {
function parseList<T extends Node>(kind: ParsingContext, parseElement: () => T): NodeArray<T> {
let saveParsingContext = parsingContext;
parsingContext |= 1 << kind;
let result = <NodeArray<T>>[];
result.pos = getNodePos();
let savedStrictModeContext = inStrictModeContext();
while (!isListTerminator(kind)) {
if (isListElement(kind, /* inErrorRecovery */ false)) {
let element = parseListElement(kind, parseElement);
result.push(element);
// test elements only if we are not already in strict mode
if (checkForStrictMode && !inStrictModeContext()) {
if (isPrologueDirective(element)) {
if (isUseStrictPrologueDirective(element)) {
setStrictModeContext(true);
checkForStrictMode = false;
}
}
else {
checkForStrictMode = false;
}
}
continue;
}
@@ -1363,22 +1334,11 @@ module ts {
}
}
setStrictModeContext(savedStrictModeContext);
result.end = getNodeEnd();
parsingContext = saveParsingContext;
return result;
}
/// Should be called only on prologue directives (isPrologueDirective(node) should be true)
function isUseStrictPrologueDirective(node: Node): boolean {
Debug.assert(isPrologueDirective(node));
let nodeText = getTextOfNodeFromSourceText(sourceText, (<ExpressionStatement>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).
return nodeText === '"use strict"' || nodeText === "'use strict'";
}
function parseListElement<T extends Node>(parsingContext: ParsingContext, parseElement: () => T): T {
let node = currentNode(parsingContext);
if (node) {
@@ -1457,15 +1417,13 @@ module ts {
function canReuseNode(node: Node, parsingContext: ParsingContext): boolean {
switch (parsingContext) {
case ParsingContext.ModuleElements:
return isReusableModuleElement(node);
case ParsingContext.ClassMembers:
return isReusableClassMember(node);
case ParsingContext.SwitchClauses:
return isReusableSwitchClause(node);
case ParsingContext.SourceElements:
case ParsingContext.BlockStatements:
case ParsingContext.SwitchClauseStatements:
return isReusableStatement(node);
@@ -1528,37 +1486,25 @@ module ts {
return false;
}
function isReusableModuleElement(node: Node) {
if (node) {
switch (node.kind) {
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.ExportDeclaration:
case SyntaxKind.ExportAssignment:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.EnumDeclaration:
return true;
}
return isReusableStatement(node);
}
return false;
}
function isReusableClassMember(node: Node) {
if (node) {
switch (node.kind) {
case SyntaxKind.Constructor:
case SyntaxKind.IndexSignature:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.SemicolonClassElement:
return true;
case SyntaxKind.MethodDeclaration:
// Method declarations are not necessarily reusable. An object-literal
// may have a method calls "constructor(...)" and we must reparse that
// into an actual .ConstructorDeclaration.
let methodDeclaration = <MethodDeclaration>node;
let nameIsConstructor = methodDeclaration.name.kind === SyntaxKind.Identifier &&
(<Identifier>methodDeclaration.name).originalKeywordKind === SyntaxKind.ConstructorKeyword;
return !nameIsConstructor;
}
}
@@ -1600,6 +1546,15 @@ module ts {
case SyntaxKind.LabeledStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.DebuggerStatement:
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.ExportDeclaration:
case SyntaxKind.ExportAssignment:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.TypeAliasDeclaration:
return true;
}
}
@@ -1673,8 +1628,7 @@ module ts {
function parsingContextErrors(context: ParsingContext): DiagnosticMessage {
switch (context) {
case ParsingContext.SourceElements: return Diagnostics.Declaration_or_statement_expected;
case ParsingContext.ModuleElements: return Diagnostics.Declaration_or_statement_expected;
case ParsingContext.BlockStatements: return Diagnostics.Statement_expected;
case ParsingContext.BlockStatements: return Diagnostics.Declaration_or_statement_expected;
case ParsingContext.SwitchClauses: return Diagnostics.case_or_default_expected;
case ParsingContext.SwitchClauseStatements: return Diagnostics.Statement_expected;
case ParsingContext.TypeMembers: return Diagnostics.Property_or_signature_expected;
@@ -1791,32 +1745,32 @@ module ts {
}
function parseRightSideOfDot(allowIdentifierNames: boolean): Identifier {
// Technically a keyword is valid here as all keywords are identifier names.
// However, often we'll encounter this in error situations when the keyword
// Technically a keyword is valid here as all identifiers and keywords are identifier names.
// However, often we'll encounter this in error situations when the identifier or keyword
// is actually starting another valid construct.
//
// So, we check for the following specific case:
//
// name.
// keyword identifierNameOrKeyword
// identifierOrKeyword identifierNameOrKeyword
//
// Note: the newlines are important here. For example, if that above code
// were rewritten into:
//
// name.keyword
// name.identifierOrKeyword
// identifierNameOrKeyword
//
// Then we would consider it valid. That's because ASI would take effect and
// the code would be implicitly: "name.keyword; identifierNameOrKeyword".
// the code would be implicitly: "name.identifierOrKeyword; identifierNameOrKeyword".
// In the first case though, ASI will not take effect because there is not a
// line terminator after the keyword.
if (scanner.hasPrecedingLineBreak() && scanner.isReservedWord()) {
// line terminator after the identifier or keyword.
if (scanner.hasPrecedingLineBreak() && isIdentifierOrKeyword()) {
let matchesPattern = lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine);
if (matchesPattern) {
// Report that we need an identifier. However, report it right after the dot,
// and not on the next token. This is because the next token might actually
// be an identifier and the error woudl be quite confusing.
// be an identifier and the error would be quite confusing.
return <Identifier>createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentToken*/ true, Diagnostics.Identifier_expected);
}
}
@@ -1897,9 +1851,17 @@ module ts {
// TYPES
function parseTypeReference(): TypeReferenceNode {
let node = <TypeReferenceNode>createNode(SyntaxKind.TypeReference);
node.typeName = parseEntityName(/*allowReservedWords*/ false, Diagnostics.Type_expected);
function parseTypeReferenceOrTypePredicate(): TypeReferenceNode | TypePredicateNode {
let typeName = parseEntityName(/*allowReservedWords*/ false, Diagnostics.Type_expected);
if (typeName.kind === SyntaxKind.Identifier && token === SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) {
nextToken();
let node = <TypePredicateNode>createNode(SyntaxKind.TypePredicate, typeName.pos);
node.parameterName = <Identifier>typeName;
node.type = parseType();
return finishNode(node);
}
let node = <TypeReferenceNode>createNode(SyntaxKind.TypeReference, typeName.pos);
node.typeName = typeName;
if (!scanner.hasPrecedingLineBreak() && token === SyntaxKind.LessThanToken) {
node.typeArguments = parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
}
@@ -2289,7 +2251,7 @@ module ts {
function parseObjectTypeMembers(): NodeArray<Declaration> {
let members: NodeArray<Declaration>;
if (parseExpected(SyntaxKind.OpenBraceToken)) {
members = parseList(ParsingContext.TypeMembers, /*checkForStrictMode*/ false, parseTypeMember);
members = parseList(ParsingContext.TypeMembers, parseTypeMember);
parseExpected(SyntaxKind.CloseBraceToken);
}
else {
@@ -2336,7 +2298,7 @@ module ts {
case SyntaxKind.SymbolKeyword:
// If these are followed by a dot, then parse these out as a dotted type reference instead.
let node = tryParse(parseKeywordAndNoDot);
return node || parseTypeReference();
return node || parseTypeReferenceOrTypePredicate();
case SyntaxKind.VoidKeyword:
return parseTokenNode<TypeNode>();
case SyntaxKind.TypeOfKeyword:
@@ -2348,7 +2310,7 @@ module ts {
case SyntaxKind.OpenParenToken:
return parseParenthesizedType();
default:
return parseTypeReference();
return parseTypeReferenceOrTypePredicate();
}
}
@@ -2658,12 +2620,6 @@ module ts {
return true;
}
if (inStrictModeContext()) {
// If we're in strict mode, then 'yield' is a keyword, could only ever start
// a yield expression.
return true;
}
// We're in a context where 'yield expr' is not allowed. However, if we can
// definitely tell that the user was trying to parse a 'yield expr' and not
// just a normal expr that start with a 'yield' identifier, then parse out
@@ -2678,7 +2634,7 @@ module ts {
// for now we just check if the next token is an identifier. More heuristics
// can be added here later as necessary. We just need to make sure that we
// don't accidently consume something legal.
return lookAhead(nextTokenIsIdentifierOnSameLine);
return lookAhead(nextTokenIsIdentifierOrKeywordOrNumberOnSameLine);
}
return false;
@@ -2686,7 +2642,7 @@ module ts {
function nextTokenIsIdentifierOnSameLine() {
nextToken();
return !scanner.hasPrecedingLineBreak() && isIdentifier()
return !scanner.hasPrecedingLineBreak() && isIdentifier();
}
function parseYieldExpression(): YieldExpression {
@@ -3521,10 +3477,10 @@ module ts {
}
// STATEMENTS
function parseBlock(ignoreMissingOpenBrace: boolean, checkForStrictMode: boolean, diagnosticMessage?: DiagnosticMessage): Block {
function parseBlock(ignoreMissingOpenBrace: boolean, diagnosticMessage?: DiagnosticMessage): Block {
let node = <Block>createNode(SyntaxKind.Block);
if (parseExpected(SyntaxKind.OpenBraceToken, diagnosticMessage) || ignoreMissingOpenBrace) {
node.statements = parseList(ParsingContext.BlockStatements, checkForStrictMode, parseStatement);
node.statements = parseList(ParsingContext.BlockStatements, parseStatement);
parseExpected(SyntaxKind.CloseBraceToken);
}
else {
@@ -3544,7 +3500,7 @@ module ts {
setDecoratorContext(false);
}
let block = parseBlock(ignoreMissingOpenBrace, /*checkForStrictMode*/ true, diagnosticMessage);
let block = parseBlock(ignoreMissingOpenBrace, diagnosticMessage);
if (saveDecoratorContext) {
setDecoratorContext(true);
@@ -3686,7 +3642,7 @@ module ts {
parseExpected(SyntaxKind.CaseKeyword);
node.expression = allowInAnd(parseExpression);
parseExpected(SyntaxKind.ColonToken);
node.statements = parseList(ParsingContext.SwitchClauseStatements, /*checkForStrictMode*/ false, parseStatement);
node.statements = parseList(ParsingContext.SwitchClauseStatements, parseStatement);
return finishNode(node);
}
@@ -3694,7 +3650,7 @@ module ts {
let node = <DefaultClause>createNode(SyntaxKind.DefaultClause);
parseExpected(SyntaxKind.DefaultKeyword);
parseExpected(SyntaxKind.ColonToken);
node.statements = parseList(ParsingContext.SwitchClauseStatements, /*checkForStrictMode*/ false, parseStatement);
node.statements = parseList(ParsingContext.SwitchClauseStatements, parseStatement);
return finishNode(node);
}
@@ -3710,7 +3666,7 @@ module ts {
parseExpected(SyntaxKind.CloseParenToken);
let caseBlock = <CaseBlock>createNode(SyntaxKind.CaseBlock, scanner.getStartPos());
parseExpected(SyntaxKind.OpenBraceToken);
caseBlock.clauses = parseList(ParsingContext.SwitchClauses, /*checkForStrictMode*/ false, parseCaseOrDefaultClause);
caseBlock.clauses = parseList(ParsingContext.SwitchClauses, parseCaseOrDefaultClause);
parseExpected(SyntaxKind.CloseBraceToken);
node.caseBlock = finishNode(caseBlock);
return finishNode(node);
@@ -3737,14 +3693,14 @@ module ts {
let node = <TryStatement>createNode(SyntaxKind.TryStatement);
parseExpected(SyntaxKind.TryKeyword);
node.tryBlock = parseBlock(/*ignoreMissingOpenBrace*/ false, /*checkForStrictMode*/ false);
node.tryBlock = parseBlock(/*ignoreMissingOpenBrace*/ false);
node.catchClause = token === SyntaxKind.CatchKeyword ? parseCatchClause() : undefined;
// If we don't have a catch clause, then we must have a finally clause. Try to parse
// one out no matter what.
if (!node.catchClause || token === SyntaxKind.FinallyKeyword) {
parseExpected(SyntaxKind.FinallyKeyword);
node.finallyBlock = parseBlock(/*ignoreMissingOpenBrace*/ false, /*checkForStrictMode*/ false);
node.finallyBlock = parseBlock(/*ignoreMissingOpenBrace*/ false);
}
return finishNode(node);
@@ -3758,7 +3714,7 @@ module ts {
}
parseExpected(SyntaxKind.CloseParenToken);
result.block = parseBlock(/*ignoreMissingOpenBrace*/ false, /*checkForStrictMode*/ false);
result.block = parseBlock(/*ignoreMissingOpenBrace*/ false);
return finishNode(result);
}
@@ -3799,7 +3755,12 @@ module ts {
return isIdentifierOrKeyword() && !scanner.hasPrecedingLineBreak();
}
function parseDeclarationFlags(): StatementFlags {
function nextTokenIsIdentifierOrKeywordOrNumberOnSameLine() {
nextToken();
return (isIdentifierOrKeyword() || token === SyntaxKind.NumericLiteral) && !scanner.hasPrecedingLineBreak();
}
function isDeclaration(): boolean {
while (true) {
switch (token) {
case SyntaxKind.VarKeyword:
@@ -3808,28 +3769,54 @@ module ts {
case SyntaxKind.FunctionKeyword:
case SyntaxKind.ClassKeyword:
case SyntaxKind.EnumKeyword:
return StatementFlags.Statement;
return true;
// 'declare', 'module', 'namespace', 'interface'* and 'type' are all legal JavaScript identifiers;
// however, an identifier cannot be followed by another identifier on the same line. This is what we
// count on to parse out the respective declarations. For instance, we exploit this to say that
//
// namespace n
//
// can be none other than the beginning of a namespace declaration, but need to respect that JavaScript sees
//
// namespace
// n
//
// as the identifier 'namespace' on one line followed by the identifier 'n' on another.
// We need to look one token ahead to see if it permissible to try parsing a declaration.
//
// *Note*: 'interface' is actually a strict mode reserved word. So while
//
// "use strict"
// interface
// I {}
//
// could be legal, it would add complexity for very little gain.
case SyntaxKind.InterfaceKeyword:
case SyntaxKind.TypeKeyword:
nextToken();
return isIdentifierOrKeyword() ? StatementFlags.Statement : StatementFlags.None;
return nextTokenIsIdentifierOnSameLine();
case SyntaxKind.ModuleKeyword:
case SyntaxKind.NamespaceKeyword:
return nextTokenIsIdentifierOrStringLiteralOnSameLine();
case SyntaxKind.DeclareKeyword:
nextToken();
return isIdentifierOrKeyword() || token === SyntaxKind.StringLiteral ? StatementFlags.ModuleElement : StatementFlags.None;
// ASI takes effect for this modifier.
if (scanner.hasPrecedingLineBreak()) {
return false;
}
continue;
case SyntaxKind.ImportKeyword:
nextToken();
return token === SyntaxKind.StringLiteral || token === SyntaxKind.AsteriskToken ||
token === SyntaxKind.OpenBraceToken || isIdentifierOrKeyword() ?
StatementFlags.ModuleElement : StatementFlags.None;
token === SyntaxKind.OpenBraceToken || isIdentifierOrKeyword();
case SyntaxKind.ExportKeyword:
nextToken();
if (token === SyntaxKind.EqualsToken || token === SyntaxKind.AsteriskToken ||
token === SyntaxKind.OpenBraceToken || token === SyntaxKind.DefaultKeyword) {
return StatementFlags.ModuleElement;
return true;
}
continue;
case SyntaxKind.DeclareKeyword:
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
@@ -3837,16 +3824,16 @@ module ts {
nextToken();
continue;
default:
return StatementFlags.None;
return false;
}
}
}
function getDeclarationFlags(): StatementFlags {
return lookAhead(parseDeclarationFlags);
function isStartOfDeclaration(): boolean {
return lookAhead(isDeclaration);
}
function getStatementFlags(): StatementFlags {
function isStartOfStatement(): boolean {
switch (token) {
case SyntaxKind.AtToken:
case SyntaxKind.SemicolonToken:
@@ -3872,12 +3859,12 @@ module ts {
// however, we say they are here so that we may gracefully parse them and error later.
case SyntaxKind.CatchKeyword:
case SyntaxKind.FinallyKeyword:
return StatementFlags.Statement;
return true;
case SyntaxKind.ConstKeyword:
case SyntaxKind.ExportKeyword:
case SyntaxKind.ImportKeyword:
return getDeclarationFlags();
return isStartOfDeclaration();
case SyntaxKind.DeclareKeyword:
case SyntaxKind.InterfaceKeyword:
@@ -3885,7 +3872,7 @@ module ts {
case SyntaxKind.NamespaceKeyword:
case SyntaxKind.TypeKeyword:
// When these don't start a declaration, they're an identifier in an expression statement
return getDeclarationFlags() || StatementFlags.Statement;
return true;
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
@@ -3893,52 +3880,30 @@ module ts {
case SyntaxKind.StaticKeyword:
// When these don't start a declaration, they may be the start of a class member if an identifier
// immediately follows. Otherwise they're an identifier in an expression statement.
return getDeclarationFlags() ||
(lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine) ? StatementFlags.None : StatementFlags.Statement);
return isStartOfDeclaration() || !lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine);
default:
return isStartOfExpression() ? StatementFlags.Statement : StatementFlags.None;
return isStartOfExpression();
}
}
function isStartOfStatement(): boolean {
return (getStatementFlags() & StatementFlags.Statement) !== 0;
}
function isStartOfModuleElement(): boolean {
return (getStatementFlags() & StatementFlags.StatementOrModuleElement) !== 0;
}
function nextTokenIsIdentifierOrStartOfDestructuringOnTheSameLine() {
function nextTokenIsIdentifierOrStartOfDestructuring() {
nextToken();
return !scanner.hasPrecedingLineBreak() &&
(isIdentifier() || token === SyntaxKind.OpenBraceToken || token === SyntaxKind.OpenBracketToken);
return isIdentifier() || token === SyntaxKind.OpenBraceToken || token === SyntaxKind.OpenBracketToken;
}
function isLetDeclaration() {
// It is let declaration if in strict mode or next token is identifier\open bracket\open curly on same line.
// otherwise it needs to be treated like identifier
return inStrictModeContext() || lookAhead(nextTokenIsIdentifierOrStartOfDestructuringOnTheSameLine);
// In ES6 'let' always starts a lexical declaration if followed by an identifier or {
// or [.
return lookAhead(nextTokenIsIdentifierOrStartOfDestructuring);
}
function parseStatement(): Statement {
return <Statement>parseModuleElementOfKind(StatementFlags.Statement);
}
function parseModuleElement(): ModuleElement {
return parseModuleElementOfKind(StatementFlags.StatementOrModuleElement);
}
function parseSourceElement(): ModuleElement {
return parseModuleElementOfKind(StatementFlags.StatementOrModuleElement);
}
function parseModuleElementOfKind(flags: StatementFlags): ModuleElement {
switch (token) {
case SyntaxKind.SemicolonToken:
return parseEmptyStatement();
case SyntaxKind.OpenBraceToken:
return parseBlock(/*ignoreMissingOpenBrace*/ false, /*checkForStrictMode*/ false);
return parseBlock(/*ignoreMissingOpenBrace*/ false);
case SyntaxKind.VarKeyword:
return parseVariableStatement(scanner.getStartPos(), /*decorators*/ undefined, /*modifiers*/ undefined);
case SyntaxKind.LetKeyword:
@@ -3971,7 +3936,7 @@ module ts {
case SyntaxKind.ThrowKeyword:
return parseThrowStatement();
case SyntaxKind.TryKeyword:
// Include the next two for error recovery.
// Include 'catch' and 'finally' for error recovery.
case SyntaxKind.CatchKeyword:
case SyntaxKind.FinallyKeyword:
return parseTryStatement();
@@ -3979,20 +3944,21 @@ module ts {
return parseDebuggerStatement();
case SyntaxKind.AtToken:
return parseDeclaration();
case SyntaxKind.ConstKeyword:
case SyntaxKind.InterfaceKeyword:
case SyntaxKind.TypeKeyword:
case SyntaxKind.ModuleKeyword:
case SyntaxKind.NamespaceKeyword:
case SyntaxKind.DeclareKeyword:
case SyntaxKind.ConstKeyword:
case SyntaxKind.EnumKeyword:
case SyntaxKind.ExportKeyword:
case SyntaxKind.ImportKeyword:
case SyntaxKind.InterfaceKeyword:
case SyntaxKind.ModuleKeyword:
case SyntaxKind.NamespaceKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.PublicKeyword:
case SyntaxKind.StaticKeyword:
case SyntaxKind.TypeKeyword:
if (getDeclarationFlags() & flags) {
if (isStartOfDeclaration()) {
return parseDeclaration();
}
break;
@@ -4000,7 +3966,7 @@ module ts {
return parseExpressionOrLabeledStatement();
}
function parseDeclaration(): ModuleElement {
function parseDeclaration(): Statement {
let fullStart = getNodePos();
let decorators = parseDecorators();
let modifiers = parseModifiers();
@@ -4030,10 +3996,10 @@ module ts {
parseExportAssignment(fullStart, decorators, modifiers) :
parseExportDeclaration(fullStart, decorators, modifiers);
default:
if (decorators) {
if (decorators || modifiers) {
// We reached this point because we encountered decorators and/or modifiers and assumed a declaration
// would follow. For recovery and error reporting purposes, return an incomplete declaration.
let node = <ModuleElement>createMissingNode(SyntaxKind.MissingDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected);
let node = <Statement>createMissingNode(SyntaxKind.MissingDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected);
node.pos = fullStart;
node.decorators = decorators;
setModifiers(node, modifiers);
@@ -4042,6 +4008,11 @@ module ts {
}
}
function nextTokenIsIdentifierOrStringLiteralOnSameLine() {
nextToken();
return !scanner.hasPrecedingLineBreak() && (isIdentifier() || token === SyntaxKind.StringLiteral);
}
function parseFunctionBlockOrSemicolon(isGenerator: boolean, diagnosticMessage?: DiagnosticMessage): Block {
if (token !== SyntaxKind.OpenBraceToken && canParseSemicolon()) {
parseSemicolon();
@@ -4427,7 +4398,7 @@ module ts {
return parsePropertyOrMethodDeclaration(fullStart, decorators, modifiers);
}
if (decorators) {
if (decorators || modifiers) {
// treat this as a property declaration with a missing name.
let name = <Identifier>createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected);
return parsePropertyDeclaration(fullStart, decorators, modifiers, name, /*questionToken*/ undefined);
@@ -4450,10 +4421,6 @@ module ts {
}
function parseClassDeclarationOrExpression(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, kind: SyntaxKind): ClassLikeDeclaration {
// In ES6 specification, All parts of a ClassDeclaration or a ClassExpression are strict mode code
let savedStrictModeContext = inStrictModeContext();
setStrictModeContext(true);
var node = <ClassLikeDeclaration>createNode(kind, fullStart);
node.decorators = decorators;
setModifiers(node, modifiers);
@@ -4476,9 +4443,7 @@ module ts {
node.members = createMissingList<ClassElement>();
}
var finishedNode = finishNode(node);
setStrictModeContext(savedStrictModeContext);
return finishedNode;
return finishNode(node);
}
function parseHeritageClauses(isClassHeritageClause: boolean): NodeArray<HeritageClause> {
@@ -4496,7 +4461,7 @@ module ts {
}
function parseHeritageClausesWorker() {
return parseList(ParsingContext.HeritageClauses, /*checkForStrictMode*/ false, parseHeritageClause);
return parseList(ParsingContext.HeritageClauses, parseHeritageClause);
}
function parseHeritageClause() {
@@ -4526,7 +4491,7 @@ module ts {
}
function parseClassMembers() {
return parseList(ParsingContext.ClassMembers, /*checkForStrictMode*/ false, parseClassElement);
return parseList(ParsingContext.ClassMembers, parseClassElement);
}
function parseInterfaceDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): InterfaceDeclaration {
@@ -4547,6 +4512,7 @@ module ts {
setModifiers(node, modifiers);
parseExpected(SyntaxKind.TypeKeyword);
node.name = parseIdentifier();
node.typeParameters = parseTypeParameters();
parseExpected(SyntaxKind.EqualsToken);
node.type = parseType();
parseSemicolon();
@@ -4583,7 +4549,7 @@ module ts {
function parseModuleBlock(): ModuleBlock {
let node = <ModuleBlock>createNode(SyntaxKind.ModuleBlock, scanner.getStartPos());
if (parseExpected(SyntaxKind.OpenBraceToken)) {
node.statements = parseList(ParsingContext.ModuleElements, /*checkForStrictMode*/false, parseModuleElement);
node.statements = parseList(ParsingContext.BlockStatements, parseStatement);
parseExpected(SyntaxKind.CloseBraceToken);
}
else {
@@ -4895,7 +4861,7 @@ module ts {
sourceFile.referencedFiles = referencedFiles;
sourceFile.amdDependencies = amdDependencies;
sourceFile.amdModuleName = amdModuleName;
sourceFile.moduleName = amdModuleName;
}
function setExternalModuleIndicator(sourceFile: SourceFile) {
@@ -4911,7 +4877,6 @@ module ts {
const enum ParsingContext {
SourceElements, // Elements in source file
ModuleElements, // Elements in module declaration
BlockStatements, // Statements in block
SwitchClauses, // Clauses in switch statement
SwitchClauseStatements, // Statements in switch clause
+65 -35
View File
@@ -1,7 +1,7 @@
/// <reference path="sys.ts" />
/// <reference path="emitter.ts" />
module ts {
namespace ts {
/* @internal */ export let programTime = 0;
/* @internal */ export let emitTime = 0;
/* @internal */ export let ioReadTime = 0;
@@ -10,9 +10,6 @@ module ts {
/** The version of the TypeScript compiler release */
export const version = "1.5.3";
const carriageReturnLineFeed = "\r\n";
const lineFeed = "\n";
export function findConfigFile(searchPath: string): string {
var fileName = "tsconfig.json";
while (true) {
@@ -94,10 +91,7 @@ module ts {
}
}
let newLine =
options.newLine === NewLineKind.CarriageReturnLineFeed ? carriageReturnLineFeed :
options.newLine === NewLineKind.LineFeed ? lineFeed :
sys.newLine;
const newLine = getNewLineCharacter(options);
return {
getSourceFile,
@@ -111,7 +105,10 @@ module ts {
}
export function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile): Diagnostic[] {
let diagnostics = program.getSyntacticDiagnostics(sourceFile).concat(program.getGlobalDiagnostics()).concat(program.getSemanticDiagnostics(sourceFile));
let diagnostics = program.getOptionsDiagnostics().concat(
program.getSyntacticDiagnostics(sourceFile),
program.getGlobalDiagnostics(),
program.getSemanticDiagnostics(sourceFile));
if (program.getCompilerOptions().declaration) {
diagnostics.concat(program.getDeclarationDiagnostics(sourceFile));
@@ -149,20 +146,31 @@ module ts {
export function createProgram(rootNames: string[], options: CompilerOptions, host?: CompilerHost): Program {
let program: Program;
let files: SourceFile[] = [];
let filesByName: Map<SourceFile> = {};
let diagnostics = createDiagnosticCollection();
let seenNoDefaultLib = options.noLib;
let commonSourceDirectory: string;
let diagnosticsProducingTypeChecker: TypeChecker;
let noDiagnosticsTypeChecker: TypeChecker;
let classifiableNames: Map<string>;
let skipDefaultLib = options.noLib;
let start = new Date().getTime();
host = host || createCompilerHost(options);
forEach(rootNames, name => processRootFile(name, false));
if (!seenNoDefaultLib) {
processRootFile(host.getDefaultLibFileName(options), true);
let filesByName = createFileMap<SourceFile>(fileName => host.getCanonicalFileName(fileName));
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), /*isDefaultLib:*/ true);
}
verifyCompilerOptions();
programTime += new Date().getTime() - start;
@@ -172,10 +180,12 @@ module ts {
getSourceFiles: () => files,
getCompilerOptions: () => options,
getSyntacticDiagnostics,
getOptionsDiagnostics,
getGlobalDiagnostics,
getSemanticDiagnostics,
getDeclarationDiagnostics,
getTypeChecker,
getClassifiableNames,
getDiagnosticsProducingTypeChecker,
getCommonSourceDirectory: () => commonSourceDirectory,
emit,
@@ -187,6 +197,20 @@ module ts {
};
return program;
function getClassifiableNames() {
if (!classifiableNames) {
// Initialize a checker so that all our files are bound.
getTypeChecker();
classifiableNames = {};
for (let sourceFile of files) {
copyMap(sourceFile.classifiableNames, classifiableNames);
}
}
return classifiableNames;
}
function getEmitHost(writeFileCallback?: WriteFileCallback): EmitHost {
return {
getCanonicalFileName: fileName => host.getCanonicalFileName(fileName),
@@ -238,8 +262,7 @@ module ts {
}
function getSourceFile(fileName: string) {
fileName = host.getCanonicalFileName(normalizeSlashes(fileName));
return hasProperty(filesByName, fileName) ? filesByName[fileName] : undefined;
return filesByName.get(fileName);
}
function getDiagnosticsHelper(sourceFile: SourceFile, getDiagnostics: (sourceFile: SourceFile) => Diagnostic[]): Diagnostic[] {
@@ -291,13 +314,15 @@ module ts {
}
}
function getGlobalDiagnostics(): Diagnostic[] {
let typeChecker = getDiagnosticsProducingTypeChecker();
function getOptionsDiagnostics(): Diagnostic[] {
let allDiagnostics: Diagnostic[] = [];
addRange(allDiagnostics, typeChecker.getGlobalDiagnostics());
addRange(allDiagnostics, diagnostics.getGlobalDiagnostics());
return sortAndDeduplicateDiagnostics(allDiagnostics);
}
function getGlobalDiagnostics(): Diagnostic[] {
let allDiagnostics: Diagnostic[] = [];
addRange(allDiagnostics, getDiagnosticsProducingTypeChecker().getGlobalDiagnostics());
return sortAndDeduplicateDiagnostics(allDiagnostics);
}
@@ -334,14 +359,17 @@ module ts {
}
}
else {
if (options.allowNonTsExtensions && !findSourceFile(fileName, isDefaultLib, refFile, refPos, refEnd)) {
diagnostic = Diagnostics.File_0_not_found;
diagnosticArgument = [fileName];
}
else if (!forEach(supportedExtensions, extension => findSourceFile(fileName + extension, isDefaultLib, refFile, refPos, refEnd))) {
diagnostic = Diagnostics.File_0_not_found;
fileName += ".ts";
diagnosticArgument = [fileName];
var nonTsFile: SourceFile = options.allowNonTsExtensions && findSourceFile(fileName, 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))) {
diagnostic = Diagnostics.File_0_not_found;
fileName += ".ts";
diagnosticArgument = [fileName];
}
}
}
@@ -358,19 +386,19 @@ module ts {
// Get source file from normalized fileName
function findSourceFile(fileName: string, isDefaultLib: boolean, refFile?: SourceFile, refStart?: number, refLength?: number): SourceFile {
let canonicalName = host.getCanonicalFileName(normalizeSlashes(fileName));
if (hasProperty(filesByName, canonicalName)) {
if (filesByName.contains(canonicalName)) {
// We've already looked for this file, use cached result
return getSourceFileFromCache(fileName, canonicalName, /*useAbsolutePath*/ false);
}
else {
let normalizedAbsolutePath = getNormalizedAbsolutePath(fileName, host.getCurrentDirectory());
let canonicalAbsolutePath = host.getCanonicalFileName(normalizedAbsolutePath);
if (hasProperty(filesByName, canonicalAbsolutePath)) {
if (filesByName.contains(canonicalAbsolutePath)) {
return getSourceFileFromCache(normalizedAbsolutePath, canonicalAbsolutePath, /*useAbsolutePath*/ true);
}
// We haven't looked for this file, do so now and cache result
let file = filesByName[canonicalName] = host.getSourceFile(fileName, options.target, hostErrorMessage => {
let file = host.getSourceFile(fileName, options.target, hostErrorMessage => {
if (refFile) {
diagnostics.add(createFileDiagnostic(refFile, refStart, refLength,
Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage));
@@ -379,11 +407,12 @@ module ts {
diagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage));
}
});
filesByName.set(canonicalName, file);
if (file) {
seenNoDefaultLib = seenNoDefaultLib || file.hasNoDefaultLib;
skipDefaultLib = skipDefaultLib || file.hasNoDefaultLib;
// Set the source file for normalized absolute path
filesByName[canonicalAbsolutePath] = file;
filesByName.set(canonicalAbsolutePath, file);
if (!options.noResolve) {
let basePath = getDirectoryPath(fileName);
@@ -391,6 +420,7 @@ module ts {
processImportedModules(file, basePath);
}
if (isDefaultLib) {
file.isDefaultLib = true;
files.unshift(file);
}
else {
@@ -402,7 +432,7 @@ module ts {
}
function getSourceFileFromCache(fileName: string, canonicalName: string, useAbsolutePath: boolean): SourceFile {
let file = filesByName[canonicalName];
let file = filesByName.get(canonicalName);
if (file && host.useCaseSensitiveFileNames()) {
let sourceFileName = useAbsolutePath ? getNormalizedAbsolutePath(file.fileName, host.getCurrentDirectory()) : file.fileName;
if (canonicalName !== sourceFileName) {
@@ -647,4 +677,4 @@ module ts {
}
}
}
}
}
+26 -2
View File
@@ -1,7 +1,7 @@
/// <reference path="core.ts"/>
/// <reference path="diagnosticInformationMap.generated.ts"/>
module ts {
namespace ts {
export interface ErrorCallback {
(message: DiagnosticMessage, length: number): void;
}
@@ -72,6 +72,7 @@ module ts {
"in": SyntaxKind.InKeyword,
"instanceof": SyntaxKind.InstanceOfKeyword,
"interface": SyntaxKind.InterfaceKeyword,
"is": SyntaxKind.IsKeyword,
"let": SyntaxKind.LetKeyword,
"module": SyntaxKind.ModuleKeyword,
"namespace": SyntaxKind.NamespaceKeyword,
@@ -375,8 +376,31 @@ module ts {
return ch >= CharacterCodes._0 && ch <= CharacterCodes._7;
}
export function couldStartTrivia(text: string, pos: number): boolean {
// Keep in sync with skipTrivia
let ch = text.charCodeAt(pos);
switch (ch) {
case CharacterCodes.carriageReturn:
case CharacterCodes.lineFeed:
case CharacterCodes.tab:
case CharacterCodes.verticalTab:
case CharacterCodes.formFeed:
case CharacterCodes.space:
case CharacterCodes.slash:
// starts of normal trivia
case CharacterCodes.lessThan:
case CharacterCodes.equals:
case CharacterCodes.greaterThan:
// Starts of conflict marker trivia
return true;
default:
return ch > CharacterCodes.maxAsciiCharacter;
}
}
/* @internal */
export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boolean): number {
// Keep in sync with couldStartTrivia
while (true) {
let ch = text.charCodeAt(pos);
switch (ch) {
@@ -933,7 +957,7 @@ module ts {
error(Diagnostics.Unexpected_end_of_text);
isInvalidExtendedEscape = true;
}
else if (text.charCodeAt(pos) == CharacterCodes.closeBrace) {
else if (text.charCodeAt(pos) === CharacterCodes.closeBrace) {
// Only swallow the following character up if it's a '}'.
pos++;
}
+32 -16
View File
@@ -1,6 +1,6 @@
/// <reference path="core.ts"/>
module ts {
namespace ts {
export interface System {
args: string[];
newLine: string;
@@ -15,7 +15,7 @@ module ts {
createDirectory(path: string): void;
getExecutingFilePath(): string;
getCurrentDirectory(): string;
readDirectory(path: string, extension?: string): string[];
readDirectory(path: string, extension?: string, exclude?: string[]): string[];
getMemoryUsage?(): number;
exit(exitCode?: number): void;
}
@@ -109,7 +109,11 @@ module ts {
}
}
function getNames(collection: any): string[] {
function getCanonicalPath(path: string): string {
return path.toLowerCase();
}
function getNames(collection: any): string[]{
var result: string[] = [];
for (var e = new Enumerator(collection); !e.atEnd(); e.moveNext()) {
result.push(e.item().Name);
@@ -117,21 +121,26 @@ module ts {
return result.sort();
}
function readDirectory(path: string, extension?: string): string[] {
function readDirectory(path: string, extension?: string, exclude?: string[]): string[] {
var result: string[] = [];
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
visitDirectory(path);
return result;
function visitDirectory(path: string) {
var folder = fso.GetFolder(path || ".");
var files = getNames(folder.files);
for (let name of files) {
if (!extension || fileExtensionIs(name, extension)) {
result.push(combinePaths(path, name));
for (let current of files) {
let name = combinePaths(path, current);
if ((!extension || fileExtensionIs(name, extension)) && !contains(exclude, getCanonicalPath(name))) {
result.push(name);
}
}
var subfolders = getNames(folder.subfolders);
for (let current of subfolders) {
visitDirectory(combinePaths(path, current));
let name = combinePaths(path, current);
if (!contains(exclude, getCanonicalPath(name))) {
visitDirectory(name);
}
}
}
}
@@ -222,8 +231,13 @@ module ts {
_fs.writeFileSync(fileName, data, "utf8");
}
function readDirectory(path: string, extension?: string): string[] {
function getCanonicalPath(path: string): string {
return useCaseSensitiveFileNames ? path.toLowerCase() : path;
}
function readDirectory(path: string, extension?: string, exclude?: string[]): string[] {
var result: string[] = [];
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
visitDirectory(path);
return result;
function visitDirectory(path: string) {
@@ -231,14 +245,16 @@ module ts {
var directories: string[] = [];
for (let current of files) {
var name = combinePaths(path, current);
var stat = _fs.statSync(name);
if (stat.isFile()) {
if (!extension || fileExtensionIs(name, extension)) {
result.push(name);
if (!contains(exclude, getCanonicalPath(name))) {
var stat = _fs.statSync(name);
if (stat.isFile()) {
if (!extension || fileExtensionIs(name, extension)) {
result.push(name);
}
}
else if (stat.isDirectory()) {
directories.push(name);
}
}
else if (stat.isDirectory()) {
directories.push(name);
}
}
for (let current of directories) {
+1 -1
View File
@@ -1,7 +1,7 @@
/// <reference path="program.ts"/>
/// <reference path="commandLineParser.ts"/>
module ts {
namespace ts {
export interface SourceFile {
fileWatcher: FileWatcher;
}
+83 -40
View File
@@ -1,8 +1,16 @@
module ts {
namespace ts {
export interface Map<T> {
[index: string]: T;
}
export interface FileMap<T> {
get(fileName: string): T;
set(fileName: string, value: T): void;
contains(fileName: string): boolean;
remove(fileName: string): void;
forEachValue(f: (v: T) => void): void;
}
export interface TextRange {
pos: number;
end: number;
@@ -137,6 +145,7 @@ module ts {
ConstructorKeyword,
DeclareKeyword,
GetKeyword,
IsKeyword,
ModuleKeyword,
NamespaceKeyword,
RequireKeyword,
@@ -169,6 +178,7 @@ module ts {
ConstructSignature,
IndexSignature,
// Type
TypePredicate,
TypeReference,
FunctionType,
ConstructorType,
@@ -352,10 +362,6 @@ module ts {
export const enum ParserContextFlags {
None = 0,
// Set if this node was parsed in strict mode. Used for grammar error checks, as well as
// checking if the node can be reused in incremental settings.
StrictMode = 1 << 0,
// If this node was parsed in a context where 'in-expressions' are not allowed.
DisallowIn = 1 << 1,
@@ -378,7 +384,7 @@ module ts {
JavaScriptFile = 1 << 6,
// Context flags set directly by the parser.
ParserGeneratedFlags = StrictMode | DisallowIn | Yield | GeneratorParameter | Decorator | ThisNodeHasError,
ParserGeneratedFlags = DisallowIn | Yield | GeneratorParameter | Decorator | ThisNodeHasError,
// Context flags computed by aggregating child flags upwards.
@@ -606,6 +612,11 @@ module ts {
typeArguments?: NodeArray<TypeNode>;
}
export interface TypePredicateNode extends TypeNode {
parameterName: Identifier;
type: TypeNode;
}
export interface TypeQueryNode extends TypeNode {
exprName: EntityName;
}
@@ -793,7 +804,7 @@ module ts {
expression: UnaryExpression;
}
export interface Statement extends Node, ModuleElement {
export interface Statement extends Node {
_statementBrand: any;
}
@@ -896,10 +907,6 @@ module ts {
block: Block;
}
export interface ModuleElement extends Node {
_moduleElementBrand: any;
}
export interface ClassLikeDeclaration extends Declaration {
name?: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
@@ -931,6 +938,7 @@ module ts {
export interface TypeAliasDeclaration extends Declaration, Statement {
name: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
type: TypeNode;
}
@@ -946,16 +954,16 @@ module ts {
members: NodeArray<EnumMember>;
}
export interface ModuleDeclaration extends Declaration, ModuleElement {
export interface ModuleDeclaration extends Declaration, Statement {
name: Identifier | LiteralExpression;
body: ModuleBlock | ModuleDeclaration;
}
export interface ModuleBlock extends Node, ModuleElement {
statements: NodeArray<ModuleElement>
export interface ModuleBlock extends Node, Statement {
statements: NodeArray<Statement>
}
export interface ImportEqualsDeclaration extends Declaration, ModuleElement {
export interface ImportEqualsDeclaration extends Declaration, Statement {
name: Identifier;
// 'EntityName' for an internal module reference, 'ExternalModuleReference' for an external
@@ -971,7 +979,7 @@ module ts {
// import "mod" => importClause = undefined, moduleSpecifier = "mod"
// In rest of the cases, module specifier is string literal corresponding to module
// ImportClause information is shown at its declaration below.
export interface ImportDeclaration extends ModuleElement {
export interface ImportDeclaration extends Statement {
importClause?: ImportClause;
moduleSpecifier: Expression;
}
@@ -991,7 +999,7 @@ module ts {
name: Identifier;
}
export interface ExportDeclaration extends Declaration, ModuleElement {
export interface ExportDeclaration extends Declaration, Statement {
exportClause?: NamedExports;
moduleSpecifier?: Expression;
}
@@ -1011,7 +1019,7 @@ module ts {
export type ImportSpecifier = ImportOrExportSpecifier;
export type ExportSpecifier = ImportOrExportSpecifier;
export interface ExportAssignment extends Declaration, ModuleElement {
export interface ExportAssignment extends Declaration, Statement {
isExportEquals?: boolean;
expression: Expression;
}
@@ -1127,23 +1135,32 @@ module ts {
// Source files are declarations when they are external modules.
export interface SourceFile extends Declaration {
statements: NodeArray<ModuleElement>;
statements: NodeArray<Statement>;
endOfFileToken: Node;
fileName: string;
text: string;
amdDependencies: {path: string; name: string}[];
amdModuleName: string;
moduleName: string;
referencedFiles: FileReference[];
/**
* lib.d.ts should have a reference comment like
*
* /// <reference no-default-lib="true"/>
*
* If any other file has this comment, it signals not to include lib.d.ts
* because this containing file is intended to act as a default library.
*/
hasNoDefaultLib: boolean;
languageVersion: ScriptTarget;
// The first node that causes this file to be an external module
/* @internal */ externalModuleIndicator: Node;
/* @internal */ isDefaultLib: boolean;
/* @internal */ identifiers: Map<string>;
/* @internal */ nodeCount: number;
/* @internal */ identifierCount: number;
@@ -1159,6 +1176,8 @@ module ts {
// Stores a line map for the file.
// This field should never be used directly to obtain line map, use getLineMap function instead.
/* @internal */ lineMap: number[];
/* @internal */ classifiableNames?: Map<string>;
}
export interface ScriptReferenceHost {
@@ -1168,7 +1187,7 @@ module ts {
}
export interface ParseConfigHost {
readDirectory(rootDir: string, extension: string): string[];
readDirectory(rootDir: string, extension: string, exclude: string[]): string[];
}
export interface WriteFileCallback {
@@ -1193,8 +1212,9 @@ module ts {
*/
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback): EmitResult;
getSyntacticDiagnostics(sourceFile?: SourceFile): Diagnostic[];
getOptionsDiagnostics(): Diagnostic[];
getGlobalDiagnostics(): Diagnostic[];
getSyntacticDiagnostics(sourceFile?: SourceFile): Diagnostic[];
getSemanticDiagnostics(sourceFile?: SourceFile): Diagnostic[];
getDeclarationDiagnostics(sourceFile?: SourceFile): Diagnostic[];
@@ -1209,6 +1229,8 @@ module ts {
// language service).
/* @internal */ getDiagnosticsProducingTypeChecker(): TypeChecker;
/* @internal */ getClassifiableNames(): Map<string>;
/* @internal */ getNodeCount(): number;
/* @internal */ getIdentifierCount(): number;
/* @internal */ getSymbolCount(): number;
@@ -1376,6 +1398,12 @@ module ts {
NotAccessible,
CannotBeNamed
}
export interface TypePredicate {
parameterName: string;
parameterIndex: number;
type: Type;
}
/* @internal */
export type AnyImportSyntax = ImportDeclaration | ImportEqualsDeclaration;
@@ -1396,7 +1424,10 @@ module ts {
/* @internal */
export interface EmitResolver {
hasGlobalName(name: string): boolean;
getExpressionNameSubstitution(node: Identifier, getGeneratedNameForNode: (node: Node) => string): string;
getReferencedExportContainer(node: Identifier): SourceFile | ModuleDeclaration | EnumDeclaration;
getReferencedImportDeclaration(node: Identifier): Declaration;
getReferencedNestedRedeclaration(node: Identifier): Declaration;
isNestedRedeclaration(node: Declaration): boolean;
isValueAliasDeclaration(node: Node): boolean;
isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean;
isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean;
@@ -1411,12 +1442,11 @@ module ts {
isEntityNameVisible(entityName: EntityName | Expression, enclosingDeclaration: Node): SymbolVisibilityResult;
// Returns the constant value this property access resolves to, or 'undefined' for a non-constant
getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number;
resolvesToSomeValue(location: Node, name: string): boolean;
getBlockScopedVariableId(node: Identifier): number;
getReferencedValueDeclaration(reference: Identifier): Declaration;
serializeTypeOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): string | string[];
serializeParameterTypesOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): (string | string[])[];
serializeReturnTypeOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): string | string[];
serializeTypeOfNode(node: Node): string | string[];
serializeParameterTypesOfNode(node: Node): (string | string[])[];
serializeReturnTypeOfNode(node: Node): string | string[];
}
export const enum SymbolFlags {
@@ -1493,8 +1523,15 @@ module ts {
HasExports = Class | Enum | Module,
HasMembers = Class | Interface | TypeLiteral | ObjectLiteral,
BlockScoped = BlockScopedVariable | Class | Enum,
PropertyOrAccessor = Property | Accessor,
Export = ExportNamespace | ExportType | ExportValue,
/* @internal */
// The set of things we consider semantically classifiable. Used to speed up the LS during
// classification.
Classifiable = Class | Enum | TypeAlias | Interface | TypeParameter | Module,
}
export interface Symbol {
@@ -1516,12 +1553,15 @@ module ts {
export interface SymbolLinks {
target?: Symbol; // Resolved (non-alias) target of an alias
type?: Type; // Type of value symbol
declaredType?: Type; // Type of class, interface, enum, or type parameter
declaredType?: Type; // Type of class, interface, enum, type alias, or type parameter
typeParameters?: TypeParameter[]; // Type parameters of type alias (undefined if non-generic)
instantiations?: Map<Type>; // Instantiations of generic type alias (undefined if non-generic)
mapper?: TypeMapper; // Type mapper for instantiation alias
referenced?: boolean; // True if alias symbol has been referenced as a value
unionType?: UnionType; // Containing union type for union property
resolvedExports?: SymbolTable; // Resolved exports of module
exportsChecked?: boolean; // True if exports of external module have been checked
isNestedRedeclaration?: boolean; // True if symbol is block scoped redeclaration
}
/* @internal */
@@ -1582,14 +1622,15 @@ module ts {
Tuple = 0x00002000, // Tuple
Union = 0x00004000, // Union
Anonymous = 0x00008000, // Anonymous
Instantiated = 0x00010000, // Instantiated anonymous type
/* @internal */
FromSignature = 0x00010000, // Created for signature assignment check
ObjectLiteral = 0x00020000, // Originates in an object literal
FromSignature = 0x00020000, // Created for signature assignment check
ObjectLiteral = 0x00040000, // Originates in an object literal
/* @internal */
ContainsUndefinedOrNull = 0x00040000, // Type is or contains Undefined or Null type
/* @internal */
ContainsObjectLiteral = 0x00080000, // Type is or contains object literal type
ESSymbol = 0x00100000, // Type of symbol primitive introduced in ES6
ContainsUndefinedOrNull = 0x00080000, // Type is or contains Undefined or Null type
/* @internal */
ContainsObjectLiteral = 0x00100000, // Type is or contains object literal type
ESSymbol = 0x00200000, // Type of symbol primitive introduced in ES6
/* @internal */
Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null,
@@ -1628,10 +1669,8 @@ module ts {
typeParameters: TypeParameter[]; // Type parameters (undefined if non-generic)
outerTypeParameters: TypeParameter[]; // Outer type parameters (undefined if none)
localTypeParameters: TypeParameter[]; // Local type parameters (undefined if none)
}
export interface InterfaceTypeWithBaseTypes extends InterfaceType {
baseTypes: ObjectType[];
resolvedBaseConstructorType?: Type; // Resolved base constructor type of class
resolvedBaseTypes: ObjectType[]; // Resolved base types
}
export interface InterfaceTypeWithDeclaredMembers extends InterfaceType {
@@ -1703,6 +1742,7 @@ module ts {
declaration: SignatureDeclaration; // Originating declaration
typeParameters: TypeParameter[]; // Type parameters (undefined if non-generic)
parameters: Symbol[]; // Parameters
typePredicate?: TypePredicate; // Type predicate
/* @internal */
resolvedReturnType: Type; // Resolved return type
/* @internal */
@@ -1731,7 +1771,6 @@ module ts {
/* @internal */
export interface TypeMapper {
(t: TypeParameter): Type;
mappings?: Map<Type>; // Type mapping cache
}
/* @internal */
@@ -1823,6 +1862,10 @@ module ts {
experimentalDecorators?: boolean;
emitDecoratorMetadata?: boolean;
/* @internal */ stripInternal?: boolean;
// Skip checking lib.d.ts to help speed up tests.
/* @internal */ skipDefaultLibCheck?: boolean;
[option: string]: string | number | boolean;
}
+69 -6
View File
@@ -1,7 +1,7 @@
/// <reference path="binder.ts" />
/* @internal */
module ts {
namespace ts {
export interface ReferencePathMatchResult {
fileReference?: FileReference
diagnosticMessage?: DiagnosticMessage
@@ -42,7 +42,7 @@ module ts {
// Pool writers to avoid needing to allocate them for every symbol we write.
let stringWriters: StringSymbolWriter[] = [];
export function getSingleLineStringWriter(): StringSymbolWriter {
if (stringWriters.length == 0) {
if (stringWriters.length === 0) {
let str = "";
let writeText: (text: string) => void = text => str += text;
@@ -426,7 +426,7 @@ module ts {
// Specialized signatures can have string literals as their parameters' type names
return node.parent.kind === SyntaxKind.Parameter;
case SyntaxKind.ExpressionWithTypeArguments:
return true;
return !isExpressionWithTypeArgumentsInClassExtendsClause(node);
// Identifiers and qualified names may be type nodes, depending on their context. Climb
// above them to find the lowest container
@@ -460,7 +460,7 @@ module ts {
}
switch (parent.kind) {
case SyntaxKind.ExpressionWithTypeArguments:
return true;
return !isExpressionWithTypeArgumentsInClassExtendsClause(parent);
case SyntaxKind.TypeParameter:
return node === (<TypeParameterDeclaration>parent).constraint;
case SyntaxKind.PropertyDeclaration:
@@ -872,7 +872,6 @@ module ts {
while (node.parent.kind === SyntaxKind.QualifiedName) {
node = node.parent;
}
return node.parent.kind === SyntaxKind.TypeQuery;
case SyntaxKind.Identifier:
if (node.parent.kind === SyntaxKind.TypeQuery) {
@@ -920,6 +919,8 @@ module ts {
return node === (<ComputedPropertyName>parent).expression;
case SyntaxKind.Decorator:
return true;
case SyntaxKind.ExpressionWithTypeArguments:
return (<ExpressionWithTypeArguments>parent).expression === node && isExpressionWithTypeArgumentsInClassExtendsClause(parent);
default:
if (isExpression(parent)) {
return true;
@@ -1177,6 +1178,41 @@ module ts {
return false;
}
// Return true if the given identifier is classified as an IdentifierName
export function isIdentifierName(node: Identifier): boolean {
let parent = node.parent;
switch (parent.kind) {
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.EnumMember:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.PropertyAccessExpression:
// Name in member declaration or property name in property access
return (<Declaration | PropertyAccessExpression>parent).name === node;
case SyntaxKind.QualifiedName:
// Name on right hand side of dot in a type query
if ((<QualifiedName>parent).right === node) {
while (parent.kind === SyntaxKind.QualifiedName) {
parent = parent.parent;
}
return parent.kind === SyntaxKind.TypeQuery;
}
return false;
case SyntaxKind.BindingElement:
case SyntaxKind.ImportSpecifier:
// Property name in binding element or import specifier
return (<BindingElement | ImportSpecifier>parent).propertyName === node;
case SyntaxKind.ExportSpecifier:
// Any name in an export specifier
return true;
}
return false;
}
// An alias symbol is created by one of the following declarations:
// import <symbol> = ...
// import <symbol> from ...
@@ -1878,6 +1914,12 @@ module ts {
return token >= SyntaxKind.FirstAssignment && token <= SyntaxKind.LastAssignment;
}
export function isExpressionWithTypeArgumentsInClassExtendsClause(node: Node): boolean {
return node.kind === SyntaxKind.ExpressionWithTypeArguments &&
(<HeritageClause>node.parent).token === SyntaxKind.ExtendsKeyword &&
node.parent.parent.kind === SyntaxKind.ClassDeclaration;
}
// Returns false if this heritage clause element's expression contains something unsupported
// (i.e. not a name or dotted name).
export function isSupportedExpressionWithTypeArguments(node: ExpressionWithTypeArguments): boolean {
@@ -1985,9 +2027,24 @@ module ts {
return result;
}
const carriageReturnLineFeed = "\r\n";
const lineFeed = "\n";
export function getNewLineCharacter(options: CompilerOptions): string {
if (options.newLine === NewLineKind.CarriageReturnLineFeed) {
return carriageReturnLineFeed;
}
else if (options.newLine === NewLineKind.LineFeed) {
return lineFeed;
}
else if (sys) {
return sys.newLine
}
return carriageReturnLineFeed;
}
}
module ts {
namespace ts {
export function getDefaultLibFileName(options: CompilerOptions): string {
return options.target === ScriptTarget.ES6 ? "lib.es6.d.ts" : "lib.d.ts";
}
@@ -2033,6 +2090,12 @@ module ts {
return start <= textSpanEnd(span) && end >= span.start;
}
export function decodedTextSpanIntersectsWith(start1: number, length1: number, start2: number, length2: number) {
let end1 = start1 + length1;
let end2 = start2 + length2;
return start2 <= end1 && end2 >= start1;
}
export function textSpanIntersectsWithPosition(span: TextSpan, position: number) {
return position <= textSpanEnd(span) && position >= span.start;
}
+1 -5
View File
@@ -1,7 +1,6 @@
/// <reference path='harness.ts' />
/// <reference path='runnerbase.ts' />
/// <reference path='typeWriter.ts' />
/// <reference path='syntacticCleaner.ts' />
const enum CompilerTestType {
Conformance,
@@ -18,7 +17,7 @@ class CompilerBaselineRunner extends RunnerBase {
public options: string;
constructor(public testType?: CompilerTestType) {
constructor(public testType: CompilerTestType) {
super();
this.errors = true;
this.emit = true;
@@ -171,7 +170,6 @@ class CompilerBaselineRunner extends RunnerBase {
}
});
it('Correct JS output for ' + fileName, () => {
if (!ts.fileExtensionIs(lastUnit.name, '.d.ts') && this.emit) {
if (result.files.length === 0 && result.errors.length === 0) {
@@ -195,8 +193,6 @@ class CompilerBaselineRunner extends RunnerBase {
jsCode += '//// [' + Harness.Path.getFileName(result.files[i].fileName) + ']\r\n';
jsCode += getByteOrderMarkText(result.files[i]);
jsCode += result.files[i].code;
// Re-enable this if we want to do another comparison of old vs new compiler baselines
// jsCode += SyntacticCleaner.clean(result.files[i].code);
}
if (result.declFilesCode.length > 0) {
-74
View File
@@ -1,74 +0,0 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Allows for executing a program with command-line arguments and reading the result
interface IExec {
exec: (fileName: string, cmdLineArgs: string[], handleResult: (ExecResult: ExecResult) => void) => void;
}
class ExecResult {
public stdout = "";
public stderr = "";
public exitCode: number;
}
class WindowsScriptHostExec implements IExec {
public exec(fileName: string, cmdLineArgs: string[], handleResult: (ExecResult: ExecResult) => void) : void {
var result = new ExecResult();
var shell = new ActiveXObject('WScript.Shell');
try {
var process = shell.Exec(fileName + ' ' + cmdLineArgs.join(' '));
} catch(e) {
result.stderr = e.message;
result.exitCode = 1;
handleResult(result);
return;
}
// Wait for it to finish running
while (process.Status != 0) { /* todo: sleep? */ }
result.exitCode = process.ExitCode;
if(!process.StdOut.AtEndOfStream) result.stdout = process.StdOut.ReadAll();
if(!process.StdErr.AtEndOfStream) result.stderr = process.StdErr.ReadAll();
handleResult(result);
}
}
class NodeExec implements IExec {
public exec(fileName: string, cmdLineArgs: string[], handleResult: (ExecResult: ExecResult) => void) : void {
var nodeExec = require('child_process').exec;
var result = new ExecResult();
result.exitCode = null;
var cmdLine = fileName + ' ' + cmdLineArgs.join(' ');
var process = nodeExec(cmdLine, function(error: any, stdout: string, stderr: string) {
result.stdout = stdout;
result.stderr = stderr;
result.exitCode = error ? error.code : 0;
handleResult(result);
});
}
}
var Exec: IExec = function() : IExec {
var global = <any>Function("return this;").call(null);
if(typeof global.ActiveXObject !== "undefined") {
return new WindowsScriptHostExec();
} else {
return new NodeExec();
}
}();
+8 -4
View File
@@ -343,7 +343,8 @@ module FourSlash {
if (!resolvedResult.isLibFile) {
this.languageServiceAdapterHost.addScript(Harness.Compiler.defaultLibFileName, Harness.Compiler.defaultLibSourceFile.text);
}
} else {
}
else {
// resolveReference file-option is not specified then do not resolve any files and include all inputFiles
ts.forEachKey(this.inputFiles, fileName => {
if (!Harness.isLibraryFile(fileName)) {
@@ -830,6 +831,7 @@ module FourSlash {
if (expectedText !== undefined) {
assert.notEqual(actualQuickInfoText, expectedText, this.messageAtLastKnownMarker("quick info text"));
}
// TODO: should be '==='?
if (expectedDocumentation != undefined) {
assert.notEqual(actualQuickInfoDocumentation, expectedDocumentation, this.messageAtLastKnownMarker("quick info doc comment"));
}
@@ -837,6 +839,7 @@ module FourSlash {
if (expectedText !== undefined) {
assert.equal(actualQuickInfoText, expectedText, this.messageAtLastKnownMarker("quick info text"));
}
// TODO: should be '==='?
if (expectedDocumentation != undefined) {
assert.equal(actualQuickInfoDocumentation, expectedDocumentation, assertionMessage("quick info doc"));
}
@@ -1825,7 +1828,7 @@ module FourSlash {
}
private verifyProjectInfo(expected: string[]) {
if (this.testType == FourSlashTestType.Server) {
if (this.testType === FourSlashTestType.Server) {
let actual = (<ts.server.SessionClient>this.languageService).getProjectInfo(
this.activeFile.fileName,
/* needFileNameList */ true
@@ -1942,7 +1945,7 @@ module FourSlash {
}
}
if (expected != actual) {
if (expected !== actual) {
this.raiseError('verifyNavigationItemsCount failed - found: ' + actual + ' navigation items, expected: ' + expected + '.');
}
}
@@ -1989,7 +1992,7 @@ module FourSlash {
var items = this.languageService.getNavigationBarItems(this.activeFile.fileName);
var actual = this.getNavigationBarItemsCount(items);
if (expected != actual) {
if (expected !== actual) {
this.raiseError('verifyGetScriptLexicalStructureListCount failed - found: ' + actual + ' navigation items, expected: ' + expected + '.');
}
}
@@ -2407,6 +2410,7 @@ module FourSlash {
globalOptions[match[1]] = match[2];
}
}
// TODO: should be '==='?
} else if (line == '' || lineLength === 0) {
// Previously blank lines between fourslash content caused it to be considered as 2 files,
// Remove this behavior since it just causes errors now
+114 -150
View File
@@ -99,7 +99,7 @@ module Utils {
}
try {
var content = ts.sys.readFile(Harness.userSpecifiedroot + path);
var content = ts.sys.readFile(Harness.userSpecifiedRoot + path);
}
catch (err) {
return undefined;
@@ -732,7 +732,8 @@ module Harness {
}
// Settings
export var userSpecifiedroot = "";
export let userSpecifiedRoot = "";
export let lightMode = false;
/** Functionality for compiling TypeScript code */
export module Compiler {
@@ -808,12 +809,20 @@ module Harness {
}
}
export function createSourceFileAndAssertInvariants(fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, assertInvariants = true) {
export function createSourceFileAndAssertInvariants(
fileName: string,
sourceText: string,
languageVersion: ts.ScriptTarget) {
// We'll only assert invariants outside of light mode.
const shouldAssertInvariants = !Harness.lightMode;
// Only set the parent nodes if we're asserting invariants. We don't need them otherwise.
var result = ts.createSourceFile(fileName, sourceText, languageVersion, /*setParentNodes:*/ assertInvariants);
if (assertInvariants) {
var result = ts.createSourceFile(fileName, sourceText, languageVersion, /*setParentNodes:*/ shouldAssertInvariants);
if (shouldAssertInvariants) {
Utils.assertInvariants(result, /*parent:*/ undefined);
}
return result;
}
@@ -832,13 +841,14 @@ module Harness {
return ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
}
export function createCompilerHost(inputFiles: { unitName: string; content: string; }[],
writeFile: (fn: string, contents: string, writeByteOrderMark: boolean) => void,
scriptTarget: ts.ScriptTarget,
useCaseSensitiveFileNames: boolean,
// the currentDirectory is needed for rwcRunner to passed in specified current directory to compiler host
currentDirectory?: string,
newLineKind?: ts.NewLineKind): ts.CompilerHost {
export function createCompilerHost(
inputFiles: { unitName: string; content: string; }[],
writeFile: (fn: string, contents: string, writeByteOrderMark: boolean) => void,
scriptTarget: ts.ScriptTarget,
useCaseSensitiveFileNames: boolean,
// the currentDirectory is needed for rwcRunner to passed in specified current directory to compiler host
currentDirectory?: string,
newLineKind?: ts.NewLineKind): ts.CompilerHost {
// Local get canonical file name function, that depends on passed in parameter for useCaseSensitiveFileNames
function getCanonicalFileName(fileName: string): string {
@@ -899,7 +909,7 @@ module Harness {
private compileOptions: ts.CompilerOptions;
private settings: Harness.TestCaseParser.CompilerSetting[] = [];
private lastErrors: HarnessDiagnostic[];
private lastErrors: ts.Diagnostic[];
public reset() {
this.inputFiles = [];
@@ -932,17 +942,19 @@ module Harness {
}
public emitAll(ioHost?: IEmitterIOHost) {
this.compileFiles(this.inputFiles, [],(result) => {
result.files.forEach(file => {
ioHost.writeFile(file.fileName, file.code, false);
});
result.declFilesCode.forEach(file => {
ioHost.writeFile(file.fileName, file.code, false);
});
result.sourceMaps.forEach(file => {
ioHost.writeFile(file.fileName, file.code, false);
});
},() => { }, this.compileOptions);
this.compileFiles(this.inputFiles,
/*otherFiles*/ [],
/*onComplete*/ result => {
result.files.forEach(writeFile);
result.declFilesCode.forEach(writeFile);
result.sourceMaps.forEach(writeFile);
},
/*settingsCallback*/ () => { },
this.compileOptions);
function writeFile(file: GeneratedFile) {
ioHost.writeFile(file.fileName, file.code, false);
}
}
public compileFiles(inputFiles: { unitName: string; content: string }[],
@@ -951,8 +963,7 @@ module Harness {
settingsCallback?: (settings: ts.CompilerOptions) => void,
options?: ts.CompilerOptions,
// Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file
currentDirectory?: string,
assertInvariants = true) {
currentDirectory?: string) {
options = options || { noResolve: false };
options.target = options.target || ts.ScriptTarget.ES3;
@@ -964,14 +975,39 @@ module Harness {
settingsCallback(null);
}
var newLine = '\r\n';
let newLine = '\r\n';
options.skipDefaultLibCheck = true;
// Files from built\local that are requested by test "@includeBuiltFiles" to be in the context.
// Treat them as library files, so include them in build, but not in baselines.
var includeBuiltFiles: { unitName: string; content: string }[] = [];
var useCaseSensitiveFileNames = ts.sys.useCaseSensitiveFileNames;
this.settings.forEach(setting => {
this.settings.forEach(setCompilerOptionForSetting);
var fileOutputs: GeneratedFile[] = [];
var programFiles = inputFiles.concat(includeBuiltFiles).map(file => file.unitName);
var compilerHost = createCompilerHost(
inputFiles.concat(includeBuiltFiles).concat(otherFiles),
(fn, contents, writeByteOrderMark) => fileOutputs.push({ fileName: fn, code: contents, writeByteOrderMark: writeByteOrderMark }),
options.target, useCaseSensitiveFileNames, currentDirectory, options.newLine);
var program = ts.createProgram(programFiles, options, compilerHost);
var emitResult = program.emit();
var errors = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
this.lastErrors = errors;
var result = new CompilerResult(fileOutputs, errors, program, ts.sys.getCurrentDirectory(), emitResult.sourceMaps);
onComplete(result, program);
// reset what newline means in case the last test changed it
ts.sys.newLine = newLine;
return options;
function setCompilerOptionForSetting(setting: Harness.TestCaseParser.CompilerSetting) {
switch (setting.flag.toLowerCase()) {
// "fileName", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outdir", "noimplicitany", "noresolve"
case "module":
@@ -1050,6 +1086,10 @@ module Harness {
options.outDir = setting.value;
break;
case 'skipdefaultlibcheck':
options.skipDefaultLibCheck = setting.value === "true";
break;
case 'sourceroot':
options.sourceRoot = setting.value;
break;
@@ -1078,10 +1118,6 @@ module Harness {
}
break;
case 'normalizenewline':
newLine = setting.value;
break;
case 'comments':
options.removeComments = setting.value === 'false';
break;
@@ -1125,7 +1161,7 @@ module Harness {
case 'inlinesourcemap':
options.inlineSourceMap = setting.value === 'true';
break;
case 'inlinesources':
options.inlineSources = setting.value === 'true';
break;
@@ -1133,30 +1169,7 @@ module Harness {
default:
throw new Error('Unsupported compiler setting ' + setting.flag);
}
});
var fileOutputs: GeneratedFile[] = [];
var programFiles = inputFiles.concat(includeBuiltFiles).map(file => file.unitName);
var program = ts.createProgram(programFiles, options, createCompilerHost(inputFiles.concat(includeBuiltFiles).concat(otherFiles),
(fn, contents, writeByteOrderMark) => fileOutputs.push({ fileName: fn, code: contents, writeByteOrderMark: writeByteOrderMark }),
options.target, useCaseSensitiveFileNames, currentDirectory, options.newLine));
var emitResult = program.emit();
var errors: HarnessDiagnostic[] = [];
ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics).forEach(err => {
// TODO: new compiler formats errors after this point to add . and newlines so we'll just do it manually for now
errors.push(getMinimalDiagnostic(err));
});
this.lastErrors = errors;
var result = new CompilerResult(fileOutputs, errors, program, ts.sys.getCurrentDirectory(), emitResult.sourceMaps);
onComplete(result, program);
// reset what newline means in case the last test changed it
ts.sys.newLine = newLine;
return options;
}
}
public compileDeclarationFiles(inputFiles: { unitName: string; content: string; }[],
@@ -1235,70 +1248,50 @@ module Harness {
return normalized;
}
export function getMinimalDiagnostic(err: ts.Diagnostic): HarnessDiagnostic {
var errorLineInfo = err.file ? err.file.getLineAndCharacterOfPosition(err.start) : { line: -1, character: -1 };
return {
fileName: err.file && err.file.fileName,
start: err.start,
end: err.start + err.length,
line: errorLineInfo.line + 1,
character: errorLineInfo.character + 1,
message: ts.flattenDiagnosticMessageText(err.messageText, ts.sys.newLine),
category: ts.DiagnosticCategory[err.category].toLowerCase(),
code: err.code
};
}
export function minimalDiagnosticsToString(diagnostics: HarnessDiagnostic[]) {
export function minimalDiagnosticsToString(diagnostics: ts.Diagnostic[]) {
// This is basically copied from tsc.ts's reportError to replicate what tsc does
var errorOutput = "";
ts.forEach(diagnostics, diagnotic => {
if (diagnotic.fileName) {
errorOutput += diagnotic.fileName + "(" + diagnotic.line + "," + diagnotic.character + "): ";
ts.forEach(diagnostics, diagnostic => {
if (diagnostic.file) {
var lineAndCharacter = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
errorOutput += diagnostic.file.fileName + "(" + (lineAndCharacter.line + 1) + "," + (lineAndCharacter.character + 1) + "): ";
}
errorOutput += diagnotic.category + " TS" + diagnotic.code + ": " + diagnotic.message + ts.sys.newLine;
errorOutput += ts.DiagnosticCategory[diagnostic.category].toLowerCase() + " TS" + diagnostic.code + ": " + ts.flattenDiagnosticMessageText(diagnostic.messageText, ts.sys.newLine) + ts.sys.newLine;
});
return errorOutput;
}
function compareDiagnostics(d1: HarnessDiagnostic, d2: HarnessDiagnostic) {
return ts.compareValues(d1.fileName, d2.fileName) ||
ts.compareValues(d1.start, d2.start) ||
ts.compareValues(d1.end, d2.end) ||
ts.compareValues(d1.code, d2.code) ||
ts.compareValues(d1.message, d2.message) ||
0;
}
export function getErrorBaseline(inputFiles: { unitName: string; content: string }[], diagnostics: HarnessDiagnostic[]) {
diagnostics.sort(compareDiagnostics);
export function getErrorBaseline(inputFiles: { unitName: string; content: string }[], diagnostics: ts.Diagnostic[]) {
diagnostics.sort(ts.compareDiagnostics);
var outputLines: string[] = [];
// Count up all the errors we find so we don't miss any
var totalErrorsReported = 0;
function outputErrorText(error: Harness.Compiler.HarnessDiagnostic) {
var errLines = RunnerBase.removeFullPaths(error.message)
function outputErrorText(error: ts.Diagnostic) {
var message = ts.flattenDiagnosticMessageText(error.messageText, ts.sys.newLine);
var errLines = RunnerBase.removeFullPaths(message)
.split('\n')
.map(s => s.length > 0 && s.charAt(s.length - 1) === '\r' ? s.substr(0, s.length - 1) : s)
.filter(s => s.length > 0)
.map(s => '!!! ' + error.category + " TS" + error.code + ": " + s);
.map(s => '!!! ' + ts.DiagnosticCategory[error.category].toLowerCase() + " TS" + error.code + ": " + s);
errLines.forEach(e => outputLines.push(e));
totalErrorsReported++;
}
// Report global errors
var globalErrors = diagnostics.filter(err => !err.fileName);
var globalErrors = diagnostics.filter(err => !err.file);
globalErrors.forEach(outputErrorText);
// 'merge' the lines of each input file with any errors associated with it
inputFiles.filter(f => f.content !== undefined).forEach(inputFile => {
// Filter down to the errors in the file
var fileErrors = diagnostics.filter(e => {
var errFn = e.fileName;
return errFn && errFn === inputFile.unitName;
var errFn = e.file;
return errFn && errFn.fileName === inputFile.unitName;
});
@@ -1334,18 +1327,19 @@ module Harness {
outputLines.push(' ' + line);
fileErrors.forEach(err => {
// Does any error start or continue on to this line? Emit squiggles
if ((err.end >= thisLineStart) && ((err.start < nextLineStart) || (lineIndex === lines.length - 1))) {
let end = ts.textSpanEnd(err);
if ((end >= thisLineStart) && ((err.start < nextLineStart) || (lineIndex === lines.length - 1))) {
// How many characters from the start of this line the error starts at (could be positive or negative)
var relativeOffset = err.start - thisLineStart;
// How many characters of the error are on this line (might be longer than this line in reality)
var length = (err.end - err.start) - Math.max(0, thisLineStart - err.start);
var length = (end - err.start) - Math.max(0, thisLineStart - err.start);
// Calculate the start of the squiggle
var squiggleStart = Math.max(0, relativeOffset);
// TODO/REVIEW: this doesn't work quite right in the browser if a multi file test has files whose names are just the right length relative to one another
outputLines.push(' ' + line.substr(0, squiggleStart).replace(/[^\s]/g, ' ') + new Array(Math.min(length, line.length - squiggleStart) + 1).join('~'));
// If the error ended here, or we're at the end of the file, emit its message
if ((lineIndex === lines.length - 1) || nextLineStart > err.end) {
if ((lineIndex === lines.length - 1) || nextLineStart > end) {
// Just like above, we need to do a split on a string instead of on a regex
// because the JS engine does regexes wrong
@@ -1361,12 +1355,12 @@ module Harness {
});
var numLibraryDiagnostics = ts.countWhere(diagnostics, diagnostic => {
return diagnostic.fileName && (isLibraryFile(diagnostic.fileName) || isBuiltFile(diagnostic.fileName));
return diagnostic.file && (isLibraryFile(diagnostic.file.fileName) || isBuiltFile(diagnostic.file.fileName));
});
var numTest262HarnessDiagnostics = ts.countWhere(diagnostics, diagnostic => {
// Count an error generated from tests262-harness folder.This should only apply for test262
return diagnostic.fileName && diagnostic.fileName.indexOf("test262-harness") >= 0;
return diagnostic.file && diagnostic.file.fileName.indexOf("test262-harness") >= 0;
});
// Verify we didn't miss any errors in total
@@ -1376,29 +1370,30 @@ module Harness {
ts.sys.newLine + ts.sys.newLine + outputLines.join('\r\n');
}
export function collateOutputs(outputFiles: Harness.Compiler.GeneratedFile[], clean?: (s: string) => string) {
export function collateOutputs(outputFiles: Harness.Compiler.GeneratedFile[]): string {
// Collect, test, and sort the fileNames
function cleanName(fn: string) {
var lastSlash = ts.normalizeSlashes(fn).lastIndexOf('/');
return fn.substr(lastSlash + 1).toLowerCase();
}
outputFiles.sort((a, b) => cleanName(a.fileName).localeCompare(cleanName(b.fileName)));
// Emit them
var result = '';
ts.forEach(outputFiles, outputFile => {
for (let outputFile of outputFiles) {
// Some extra spacing if this isn't the first file
if (result.length) result = result + '\r\n\r\n';
if (result.length) {
result += '\r\n\r\n';
}
// FileName header + content
result = result + '/*====== ' + outputFile.fileName + ' ======*/\r\n';
if (clean) {
result = result + clean(outputFile.code);
} else {
result = result + outputFile.code;
}
});
result += '/*====== ' + outputFile.fileName + ' ======*/\r\n';
result += outputFile.code;
}
return result;
function cleanName(fn: string) {
var lastSlash = ts.normalizeSlashes(fn).lastIndexOf('/');
return fn.substr(lastSlash + 1).toLowerCase();
}
}
/** The harness' compiler instance used when tests are actually run. Reseting or changing settings of this compiler instance must be done within a test case (i.e., describe/it) */
@@ -1419,17 +1414,6 @@ module Harness {
//harnessCompiler.compileString(code, unitName, callback);
}
export interface HarnessDiagnostic {
fileName: string;
start: number;
end: number;
line: number;
character: number;
message: string;
category: string;
code: number;
}
export interface GeneratedFile {
fileName: string;
code: string;
@@ -1459,12 +1443,12 @@ module Harness {
/** Contains the code and errors of a compilation and some helper methods to check its status. */
export class CompilerResult {
public files: GeneratedFile[] = [];
public errors: HarnessDiagnostic[] = [];
public errors: ts.Diagnostic[] = [];
public declFilesCode: GeneratedFile[] = [];
public sourceMaps: GeneratedFile[] = [];
/** @param fileResults an array of strings for the fileName and an ITextWriter with its code */
constructor(fileResults: GeneratedFile[], errors: HarnessDiagnostic[], public program: ts.Program,
constructor(fileResults: GeneratedFile[], errors: ts.Diagnostic[], public program: ts.Program,
public currentDirectoryForProgram: string, private sourceMapData: ts.SourceMapData[]) {
fileResults.forEach(emittedFile => {
@@ -1489,15 +1473,6 @@ module Harness {
return Harness.SourceMapRecoder.getSourceMapRecord(this.sourceMapData, this.program, this.files);
}
}
public isErrorAt(line: number, column: number, message: string) {
for (var i = 0; i < this.errors.length; i++) {
if ((this.errors[i].line + 1) === line && (this.errors[i].character + 1) === column && this.errors[i].message === message)
return true;
}
return false;
}
}
}
@@ -1520,15 +1495,6 @@ module Harness {
// Regex for parsing options in the format "@Alpha: Value of any sort"
var optionRegex = /^[\/]{2}\s*@(\w+)\s*:\s*(\S*)/gm; // multiple matches on multiple lines
// List of allowed metadata names
var fileMetadataNames = ["filename", "comments", "declaration", "module",
"nolib", "sourcemap", "target", "out", "outdir", "noemithelpers", "noemitonerror",
"noimplicitany", "noresolve", "newline", "normalizenewline", "emitbom",
"errortruncation", "usecasesensitivefilenames", "preserveconstenums",
"includebuiltfile", "suppressimplicitanyindexerrors", "stripinternal",
"isolatedmodules", "inlinesourcemap", "maproot", "sourceroot",
"inlinesources", "emitdecoratormetadata", "experimentaldecorators"];
function extractCompilerSettings(content: string): CompilerSetting[] {
var opts: CompilerSetting[] = [];
@@ -1562,10 +1528,8 @@ module Harness {
if (testMetaData) {
// Comment line, check for global/file @options and record them
optionRegex.lastIndex = 0;
var fileNameIndex = fileMetadataNames.indexOf(testMetaData[1].toLowerCase());
if (fileNameIndex === -1) {
throw new Error('Unrecognized metadata name "' + testMetaData[1] + '". Available file metadata names are: ' + fileMetadataNames.join(', '));
} else if (fileNameIndex === 0) {
var metaDataName = testMetaData[1].toLowerCase();
if (metaDataName === "filename") {
currentFileOptions[testMetaData[1]] = testMetaData[2];
} else {
continue;
@@ -1651,9 +1615,9 @@ module Harness {
function baselinePath(fileName: string, type: string, baselineFolder: string, subfolder?: string) {
if (subfolder !== undefined) {
return Harness.userSpecifiedroot + baselineFolder + '/' + subfolder + '/' + type + '/' + fileName;
return Harness.userSpecifiedRoot + baselineFolder + '/' + subfolder + '/' + type + '/' + fileName;
} else {
return Harness.userSpecifiedroot + baselineFolder + '/' + type + '/' + fileName;
return Harness.userSpecifiedRoot + baselineFolder + '/' + type + '/' + fileName;
}
}
@@ -1762,7 +1726,7 @@ module Harness {
}
export function getDefaultLibraryFile(): { unitName: string, content: string } {
var libFile = Harness.userSpecifiedroot + Harness.libFolder + "/" + "lib.d.ts";
var libFile = Harness.userSpecifiedRoot + Harness.libFolder + "/" + "lib.d.ts";
return {
unitName: libFile,
content: IO.readFile(libFile)
+1 -1
View File
@@ -583,7 +583,7 @@ module Harness.LanguageService {
// This host is just a proxy for the clientHost, it uses the client
// host to answer server queries about files on disk
var serverHost = new SessionServerHost(clientHost);
var server = new ts.server.Session(serverHost, serverHost);
var server = new ts.server.Session(serverHost, Buffer.byteLength, process.hrtime, serverHost);
// Fake the connection between the client and the server
serverHost.writeMessage = client.onMessage.bind(client);
-19
View File
@@ -1,19 +0,0 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
/// <reference path="exec.ts" />
/// <reference path="generate.ts" />
/// <reference path="harness.ts" />
/// <reference path="diff.ts" />
+3 -3
View File
@@ -110,6 +110,7 @@ class ProjectRunner extends RunnerBase {
else if (url.indexOf(diskProjectPath) === 0) {
// Replace the disk specific path into the project root path
url = url.substr(diskProjectPath.length);
// TODO: should be '!=='?
if (url.charCodeAt(0) != ts.CharacterCodes.slash) {
url = "/" + url;
}
@@ -240,7 +241,7 @@ class ProjectRunner extends RunnerBase {
if (Harness.Compiler.isJS(fileName)) {
// Make sure if there is URl we have it cleaned up
var indexOfSourceMapUrl = data.lastIndexOf("//# sourceMappingURL=");
if (indexOfSourceMapUrl != -1) {
if (indexOfSourceMapUrl !== -1) {
data = data.substring(0, indexOfSourceMapUrl + 21) + cleanProjectUrl(data.substring(indexOfSourceMapUrl + 21));
}
}
@@ -323,9 +324,8 @@ class ProjectRunner extends RunnerBase {
sourceFile => {
return { unitName: sourceFile.fileName, content: sourceFile.text };
});
var diagnostics = ts.map(compilerResult.errors, error => Harness.Compiler.getMinimalDiagnostic(error));
return Harness.Compiler.getErrorBaseline(inputFiles, diagnostics);
return Harness.Compiler.getErrorBaseline(inputFiles, compilerResult.errors);
}
var name = 'Compiling project for ' + testCase.scenario + ': testcase ' + testCaseFileName;
+42 -35
View File
@@ -18,6 +18,7 @@
/// <reference path='fourslashRunner.ts' />
/// <reference path='projectsRunner.ts' />
/// <reference path='rwcRunner.ts' />
/// <reference path='harness.ts' />
function runTests(runners: RunnerBase[]) {
for (var i = iterations; i > 0; i--) {
@@ -38,41 +39,47 @@ var testConfigFile =
(Harness.IO.fileExists(testconfig) ? Harness.IO.readFile(testconfig) : '');
if (testConfigFile !== '') {
// TODO: not sure why this is crashing mocha
//var testConfig = JSON.parse(testConfigRaw);
var testConfig = testConfigFile.match(/test:\s\['(.*)'\]/);
var options = testConfig ? [testConfig[1]] : [];
for (var i = 0; i < options.length; i++) {
switch (options[i]) {
case 'compiler':
runners.push(new CompilerBaselineRunner(CompilerTestType.Conformance));
runners.push(new CompilerBaselineRunner(CompilerTestType.Regressions));
runners.push(new ProjectRunner());
break;
case 'conformance':
runners.push(new CompilerBaselineRunner(CompilerTestType.Conformance));
break;
case 'project':
runners.push(new ProjectRunner());
break;
case 'fourslash':
runners.push(new FourSlashRunner(FourSlashTestType.Native));
break;
case 'fourslash-shims':
runners.push(new FourSlashRunner(FourSlashTestType.Shims));
break;
case 'fourslash-server':
runners.push(new FourSlashRunner(FourSlashTestType.Server));
break;
case 'fourslash-generated':
runners.push(new GeneratedFourslashRunner(FourSlashTestType.Native));
break;
case 'rwc':
runners.push(new RWCRunner());
break;
case 'test262':
runners.push(new Test262BaselineRunner());
break;
var testConfig = JSON.parse(testConfigFile);
if (testConfig.light) {
Harness.lightMode = true;
}
if (testConfig.test && testConfig.test.length > 0) {
for (let option of testConfig.test) {
if (!option) {
continue;
}
switch (option) {
case 'compiler':
runners.push(new CompilerBaselineRunner(CompilerTestType.Conformance));
runners.push(new CompilerBaselineRunner(CompilerTestType.Regressions));
runners.push(new ProjectRunner());
break;
case 'conformance':
runners.push(new CompilerBaselineRunner(CompilerTestType.Conformance));
break;
case 'project':
runners.push(new ProjectRunner());
break;
case 'fourslash':
runners.push(new FourSlashRunner(FourSlashTestType.Native));
break;
case 'fourslash-shims':
runners.push(new FourSlashRunner(FourSlashTestType.Shims));
break;
case 'fourslash-server':
runners.push(new FourSlashRunner(FourSlashTestType.Server));
break;
case 'fourslash-generated':
runners.push(new GeneratedFourslashRunner(FourSlashTestType.Native));
break;
case 'rwc':
runners.push(new RWCRunner());
break;
case 'test262':
runners.push(new Test262BaselineRunner());
break;
}
}
}
}
+1 -1
View File
@@ -12,7 +12,7 @@ class RunnerBase {
}
public enumerateFiles(folder: string, regex?: RegExp, options?: { recursive: boolean }): string[] {
return Harness.IO.listFiles(Harness.userSpecifiedroot + folder, regex, { recursive: (options ? options.recursive : false) });
return Harness.IO.listFiles(Harness.userSpecifiedRoot + folder, regex, { recursive: (options ? options.recursive : false) });
}
/** Setup the runner's tests so that they are ready to be executed by the harness
+9 -10
View File
@@ -1,6 +1,5 @@
/// <reference path='harness.ts'/>
/// <reference path='runnerbase.ts' />
/// <reference path='syntacticCleaner.ts' />
/// <reference path='loggedIO.ts' />
/// <reference path='..\compiler\commandLineParser.ts'/>
@@ -75,7 +74,7 @@ module RWC {
});
// Add files to compilation
for(let fileRead of ioLog.filesRead) {
for (let fileRead of ioLog.filesRead) {
// Check if the file is already added into the set of input files.
var resolvedPath = ts.normalizeSlashes(ts.sys.resolvePath(fileRead.path));
var inInputList = ts.forEach(inputFiles, inputFile => inputFile.unitName === resolvedPath);
@@ -107,14 +106,14 @@ module RWC {
opts.options.noLib = true;
// Emit the results
compilerOptions = harnessCompiler.compileFiles(inputFiles, otherFiles, compileResult => {
compilerResult = compileResult;
},
compilerOptions = harnessCompiler.compileFiles(
inputFiles,
otherFiles,
newCompilerResults => { compilerResult = newCompilerResults; },
/*settingsCallback*/ undefined, opts.options,
// Since all Rwc json file specified current directory in its json file, we need to pass this information to compilerHost
// so that when the host is asked for current directory, it should give the value from json rather than from process
currentDirectory,
/*assertInvariants:*/ false);
// Since each RWC json file specifies its current directory in its json file, we need
// to pass this information in explicitly instead of acquiring it from the process.
currentDirectory);
});
function getHarnessCompilerInputUnit(fileName: string) {
@@ -132,7 +131,7 @@ module RWC {
it('has the expected emitted code', () => {
Harness.Baseline.runBaseline('has the expected emitted code', baseName + '.output.js', () => {
return Harness.Compiler.collateOutputs(compilerResult.files, s => SyntacticCleaner.clean(s));
return Harness.Compiler.collateOutputs(compilerResult.files);
}, false, baselineOpts);
});
+15 -15
View File
@@ -46,7 +46,7 @@ module Harness.SourceMapRecoder {
}
function isSourceMappingSegmentEnd() {
if (decodingIndex == sourceMapMappings.length) {
if (decodingIndex === sourceMapMappings.length) {
return true;
}
@@ -95,7 +95,7 @@ module Harness.SourceMapRecoder {
var currentByte = base64FormatDecode();
// If msb is set, we still have more bits to continue
moreDigits = (currentByte & 32) != 0;
moreDigits = (currentByte & 32) !== 0;
// least significant 5 bits are the next msbs in the final value.
value = value | ((currentByte & 31) << shiftCount);
@@ -103,7 +103,7 @@ module Harness.SourceMapRecoder {
}
// Least significant bit if 1 represents negative and rest of the msb is actual absolute value
if ((value & 1) == 0) {
if ((value & 1) === 0) {
// + number
value = value >> 1;
}
@@ -182,7 +182,7 @@ module Harness.SourceMapRecoder {
}
}
// Dont support reading mappings that dont have information about original source and its line numbers
if (createErrorIfCondition(!isSourceMappingSegmentEnd(), "Unsupported Error Format: There are more entries after " + (decodeOfEncodedMapping.nameIndex == -1 ? "sourceColumn" : "nameIndex"))) {
if (createErrorIfCondition(!isSourceMappingSegmentEnd(), "Unsupported Error Format: There are more entries after " + (decodeOfEncodedMapping.nameIndex === -1 ? "sourceColumn" : "nameIndex"))) {
return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping };
}
@@ -249,7 +249,7 @@ module Harness.SourceMapRecoder {
mapString += " name (" + sourceMapNames[mapEntry.nameIndex] + ")";
}
else {
if (mapEntry.nameIndex != -1 || getAbsentNameIndex) {
if (mapEntry.nameIndex !== -1 || getAbsentNameIndex) {
mapString += " nameIndex (" + mapEntry.nameIndex + ")";
}
}
@@ -262,12 +262,12 @@ module Harness.SourceMapRecoder {
var decodeResult = SourceMapDecoder.decodeNextEncodedSourceMapSpan();
var decodedErrors: string[];
if (decodeResult.error
|| decodeResult.sourceMapSpan.emittedLine != sourceMapSpan.emittedLine
|| decodeResult.sourceMapSpan.emittedColumn != sourceMapSpan.emittedColumn
|| decodeResult.sourceMapSpan.sourceLine != sourceMapSpan.sourceLine
|| decodeResult.sourceMapSpan.sourceColumn != sourceMapSpan.sourceColumn
|| decodeResult.sourceMapSpan.sourceIndex != sourceMapSpan.sourceIndex
|| decodeResult.sourceMapSpan.nameIndex != sourceMapSpan.nameIndex) {
|| decodeResult.sourceMapSpan.emittedLine !== sourceMapSpan.emittedLine
|| decodeResult.sourceMapSpan.emittedColumn !== sourceMapSpan.emittedColumn
|| decodeResult.sourceMapSpan.sourceLine !== sourceMapSpan.sourceLine
|| decodeResult.sourceMapSpan.sourceColumn !== sourceMapSpan.sourceColumn
|| decodeResult.sourceMapSpan.sourceIndex !== sourceMapSpan.sourceIndex
|| decodeResult.sourceMapSpan.nameIndex !== sourceMapSpan.nameIndex) {
if (decodeResult.error) {
decodedErrors = ["!!^^ !!^^ There was decoding error in the sourcemap at this location: " + decodeResult.error];
}
@@ -288,7 +288,7 @@ module Harness.SourceMapRecoder {
}
export function recordNewSourceFileSpan(sourceMapSpan: ts.SourceMapSpan, newSourceFileCode: string) {
assert.isTrue(spansOnSingleLine.length == 0 || spansOnSingleLine[0].sourceMapSpan.emittedLine !== sourceMapSpan.emittedLine, "new file source map span should be on new line. We currently handle only that scenario");
assert.isTrue(spansOnSingleLine.length === 0 || spansOnSingleLine[0].sourceMapSpan.emittedLine !== sourceMapSpan.emittedLine, "new file source map span should be on new line. We currently handle only that scenario");
recordSourceMapSpan(sourceMapSpan);
assert.isTrue(spansOnSingleLine.length === 1);
@@ -395,9 +395,9 @@ module Harness.SourceMapRecoder {
var tsCodeLineMap = ts.computeLineStarts(sourceText);
for (var i = 0; i < tsCodeLineMap.length; i++) {
writeSourceMapIndent(prevEmittedCol, i == 0 ? markerIds[index] : " >");
writeSourceMapIndent(prevEmittedCol, i === 0 ? markerIds[index] : " >");
sourceMapRecoder.Write(getTextOfLine(i, tsCodeLineMap, sourceText));
if (i == tsCodeLineMap.length - 1) {
if (i === tsCodeLineMap.length - 1) {
sourceMapRecoder.WriteLine("");
}
}
@@ -447,7 +447,7 @@ module Harness.SourceMapRecoder {
for (var j = 0; j < sourceMapData.sourceMapDecodedMappings.length; j++) {
var decodedSourceMapping = sourceMapData.sourceMapDecodedMappings[j];
var currentSourceFile = program.getSourceFile(sourceMapData.inputSourceFileNames[decodedSourceMapping.sourceIndex]);
if (currentSourceFile != prevSourceFile) {
if (currentSourceFile !== prevSourceFile) {
SourceMapSpanWriter.recordNewSourceFileSpan(decodedSourceMapping, currentSourceFile.text);
prevSourceFile = currentSourceFile;
}
-30
View File
@@ -1,30 +0,0 @@
// Use this to get emitter-agnostic baselines
class SyntacticCleaner {
static clean(sourceFileContents: string) {
return sourceFileContents;
}
}
/* TODO: Re-implement or maybe delete
class SyntacticCleaner extends TypeScript.SyntaxWalker {
private emit: string[] = [];
public visitToken(token: TypeScript.ISyntaxToken): void {
this.emit.push(token.text());
if (token.kind() === TypeScript.SyntaxKind.SemicolonToken) {
this.emit.push('\r\n');
} else {
this.emit.push(' ');
}
}
static clean(sourceFileContents: string): string {
var parsed = TypeScript.Parser.parse('_emitted.ts', TypeScript.SimpleText.fromString(sourceFileContents), TypeScript.LanguageVersion.EcmaScript5, false);
var cleaner = new SyntacticCleaner();
cleaner.visitSourceUnit(parsed.sourceUnit());
return cleaner.emit.join('');
}
}
*/
+1 -2
View File
@@ -1,6 +1,5 @@
/// <reference path='harness.ts' />
/// <reference path='runnerbase.ts' />
/// <reference path='syntacticCleaner.ts' />
class Test262BaselineRunner extends RunnerBase {
private static basePath = 'internal/cases/test262';
@@ -65,7 +64,7 @@ class Test262BaselineRunner extends RunnerBase {
it('has the expected emitted code', () => {
Harness.Baseline.runBaseline('has the expected emitted code', testState.filename + '.output.js', () => {
var files = testState.compilerResult.files.filter(f=> f.fileName !== Test262BaselineRunner.helpersFilePath);
return Harness.Compiler.collateOutputs(files, s => SyntacticCleaner.clean(s));
return Harness.Compiler.collateOutputs(files);
}, false, Test262BaselineRunner.baselineOptions);
});
+4 -1
View File
@@ -41,7 +41,10 @@ class TypeWriterWalker {
var lineAndCharacter = this.currentSourceFile.getLineAndCharacterOfPosition(actualPos);
var sourceText = ts.getTextOfNodeFromSourceText(this.currentSourceFile.text, node);
var type = this.checker.getTypeAtLocation(node);
// Workaround to ensure we output 'C' instead of 'typeof C' for base class expressions
// var type = this.checker.getTypeAtLocation(node);
var type = node.parent && ts.isExpressionWithTypeArgumentsInClassExtendsClause(node.parent) && this.checker.getTypeAtLocation(node.parent) || this.checker.getTypeAtLocation(node);
ts.Debug.assert(type !== undefined, "type doesn't exist");
var symbol = this.checker.getSymbolAtLocation(node);
+1 -1
View File
@@ -1150,7 +1150,7 @@ interface ArrayConstructor {
(arrayLength?: number): any[];
<T>(arrayLength: number): T[];
<T>(...items: T[]): T[];
isArray(arg: any): boolean;
isArray(arg: any): arg is Array<any>;
prototype: Array<any>;
}
+11
View File
@@ -0,0 +1,11 @@
interface DOMTokenList {
[Symbol.iterator](): IterableIterator<string>;
}
interface NodeList {
[Symbol.iterator](): IterableIterator<Node>
}
interface NodeListOf<TNode extends Node> {
[Symbol.iterator](): IterableIterator<TNode>
}
+14 -7
View File
@@ -7677,10 +7677,10 @@ declare var MediaQueryList: {
interface MediaSource extends EventTarget {
activeSourceBuffers: SourceBufferList;
duration: number;
readyState: string;
readyState: number;
sourceBuffers: SourceBufferList;
addSourceBuffer(type: string): SourceBuffer;
endOfStream(error?: string): void;
endOfStream(error?: number): void;
removeSourceBuffer(sourceBuffer: SourceBuffer): void;
}
@@ -8409,7 +8409,7 @@ declare var PopStateEvent: {
interface Position {
coords: Coordinates;
timestamp: Date;
timestamp: number;
}
declare var Position: {
@@ -11090,9 +11090,17 @@ interface WebGLRenderingContext {
stencilMaskSeparate(face: number, mask: number): void;
stencilOp(fail: number, zfail: number, zpass: number): void;
stencilOpSeparate(face: number, fail: number, zfail: number, zpass: number): void;
texImage2D(target: number, level: number, internalformat: number, width: number, height: number, border: number, format: number, type: number, pixels: ArrayBufferView): void;
texImage2D(target: number, level: number, internalformat: number, format: number, type: number, image: HTMLImageElement): void;
texImage2D(target: number, level: number, internalformat: number, format: number, type: number, canvas: HTMLCanvasElement): void;
texImage2D(target: number, level: number, internalformat: number, format: number, type: number, video: HTMLVideoElement): void;
texImage2D(target: number, level: number, internalformat: number, format: number, type: number, pixels: ImageData): void;
texParameterf(target: number, pname: number, param: number): void;
texParameteri(target: number, pname: number, param: number): void;
texSubImage2D(target: number, level: number, xoffset: number, yoffset: number, width: number, height: number, format: number, type: number, pixels: ArrayBufferView): void;
texSubImage2D(target: number, level: number, xoffset: number, yoffset: number, format: number, type: number, image: HTMLImageElement): void;
texSubImage2D(target: number, level: number, xoffset: number, yoffset: number, format: number, type: number, canvas: HTMLCanvasElement): void;
texSubImage2D(target: number, level: number, xoffset: number, yoffset: number, format: number, type: number, video: HTMLVideoElement): void;
texSubImage2D(target: number, level: number, xoffset: number, yoffset: number, format: number, type: number, pixels: ImageData): void;
uniform1f(location: WebGLUniformLocation, x: number): void;
uniform1fv(location: WebGLUniformLocation, v: any): void;
@@ -12332,10 +12340,11 @@ interface DocumentEvent {
createEvent(eventInterface:"AriaRequestEvent"): AriaRequestEvent;
createEvent(eventInterface:"AudioProcessingEvent"): AudioProcessingEvent;
createEvent(eventInterface:"BeforeUnloadEvent"): BeforeUnloadEvent;
createEvent(eventInterface:"ClipboardEvent"): ClipboardEvent;
createEvent(eventInterface:"CloseEvent"): CloseEvent;
createEvent(eventInterface:"CommandEvent"): CommandEvent;
createEvent(eventInterface:"CompositionEvent"): CompositionEvent;
createEvent(eventInterface: "CustomEvent"): CustomEvent;
createEvent(eventInterface:"CustomEvent"): CustomEvent;
createEvent(eventInterface:"DeviceMotionEvent"): DeviceMotionEvent;
createEvent(eventInterface:"DeviceOrientationEvent"): DeviceOrientationEvent;
createEvent(eventInterface:"DragEvent"): DragEvent;
@@ -12358,8 +12367,6 @@ interface DocumentEvent {
createEvent(eventInterface:"MouseEvent"): MouseEvent;
createEvent(eventInterface:"MouseEvents"): MouseEvent;
createEvent(eventInterface:"MouseWheelEvent"): MouseWheelEvent;
createEvent(eventInterface:"MSGestureEvent"): MSGestureEvent;
createEvent(eventInterface:"MSPointerEvent"): MSPointerEvent;
createEvent(eventInterface:"MutationEvent"): MutationEvent;
createEvent(eventInterface:"MutationEvents"): MutationEvent;
createEvent(eventInterface:"NavigationCompletedEvent"): NavigationCompletedEvent;
@@ -12971,4 +12978,4 @@ declare function addEventListener(type: "unload", listener: (ev: Event) => any,
declare function addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void;
declare function addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void;
declare function addEventListener(type: "wheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void;
declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
+6 -1
View File
@@ -41,6 +41,11 @@ declare module Intl {
currency?: string;
currencyDisplay?: string;
useGrouping?: boolean;
minimumintegerDigits?: number;
minimumFractionDigits?: number;
maximumFractionDigits?: number;
minimumSignificantDigits?: number;
maximumSignificantDigits?: number;
}
interface ResolvedNumberFormatOptions {
@@ -103,7 +108,7 @@ declare module Intl {
}
interface DateTimeFormat {
format(date: number): string;
format(date?: Date | number): string;
resolvedOptions(): ResolvedDateTimeFormatOptions;
}
var DateTimeFormat: {
+4 -4
View File
@@ -1,6 +1,6 @@
/// <reference path="session.ts" />
module ts.server {
namespace ts.server {
export interface SessionClientHost extends LanguageServiceHost {
writeMessage(message: string): void;
@@ -219,7 +219,7 @@ module ts.server {
var request = this.processRequest<protocol.CompletionDetailsRequest>(CommandNames.CompletionDetails, args);
var response = this.processResponse<protocol.CompletionDetailsResponse>(request);
Debug.assert(response.body.length == 1, "Unexpected length of completion details response body.");
Debug.assert(response.body.length === 1, "Unexpected length of completion details response body.");
return response.body[0];
}
@@ -429,8 +429,8 @@ module ts.server {
if (!this.lastRenameEntry ||
this.lastRenameEntry.fileName !== fileName ||
this.lastRenameEntry.position !== position ||
this.lastRenameEntry.findInStrings != findInStrings ||
this.lastRenameEntry.findInComments != findInComments) {
this.lastRenameEntry.findInStrings !== findInStrings ||
this.lastRenameEntry.findInComments !== findInComments) {
this.getRenameInfo(fileName, position, findInStrings, findInComments);
}
+44 -43
View File
@@ -2,9 +2,8 @@
/// <reference path="..\services\services.ts" />
/// <reference path="protocol.d.ts" />
/// <reference path="session.ts" />
/// <reference path="node.d.ts" />
module ts.server {
namespace ts.server {
export interface Logger {
close(): void;
isVerbose(): boolean;
@@ -28,7 +27,7 @@ module ts.server {
});
}
class ScriptInfo {
export class ScriptInfo {
svc: ScriptVersionCache;
children: ScriptInfo[] = []; // files referenced by this file
defaultProject: Project; // project to use by default for file
@@ -36,7 +35,7 @@ module ts.server {
formatCodeOptions = ts.clone(CompilerService.defaultFormatCodeOptions);
constructor(private host: ServerHost, public fileName: string, public content: string, public isOpen = false) {
this.svc = ScriptVersionCache.fromString(content);
this.svc = ScriptVersionCache.fromString(host, content);
}
setFormatOptions(formatOptions: protocol.FormatOptions): void {
@@ -80,7 +79,7 @@ module ts.server {
}
}
class LSHost implements ts.LanguageServiceHost {
export class LSHost implements ts.LanguageServiceHost {
ls: ts.LanguageService = null;
compilationSettings: ts.CompilerOptions;
filenameToScript: ts.Map<ScriptInfo> = {};
@@ -273,7 +272,7 @@ module ts.server {
}
}
interface ProjectOptions {
export interface ProjectOptions {
// these fields can be present in the project file
files?: string[];
compilerOptions?: ts.CompilerOptions;
@@ -376,7 +375,7 @@ module ts.server {
}
}
interface ProjectOpenResult {
export interface ProjectOpenResult {
success?: boolean;
errorMsg?: string;
project?: Project;
@@ -392,11 +391,11 @@ module ts.server {
return copiedList;
}
interface ProjectServiceEventHandler {
export interface ProjectServiceEventHandler {
(eventName: string, project: Project, fileName: string): void;
}
interface HostConfiguration {
export interface HostConfiguration {
formatCodeOptions: ts.FormatCodeOptions;
hostInfo: string;
}
@@ -629,7 +628,7 @@ module ts.server {
for (var i = 0, len = this.openFilesReferenced.length; i < len; i++) {
var f = this.openFilesReferenced[i];
// if f was referenced by the removed project, remember it
if (f.defaultProject == removedProject) {
if (f.defaultProject === removedProject) {
f.defaultProject = undefined;
orphanFiles.push(f);
}
@@ -656,7 +655,7 @@ module ts.server {
for (var i = 0, len = this.inferredProjects.length; i < len; i++) {
var inferredProject = this.inferredProjects[i];
inferredProject.updateGraph();
if (inferredProject != excludedProject) {
if (inferredProject !== excludedProject) {
if (inferredProject.getSourceFile(info)) {
info.defaultProject = inferredProject;
referencingProjects.push(inferredProject);
@@ -710,7 +709,7 @@ module ts.server {
var rootFile = this.openFileRoots[i];
var rootedProject = rootFile.defaultProject;
var referencingProjects = this.findReferencingProjects(rootFile, rootedProject);
if (referencingProjects.length == 0) {
if (referencingProjects.length === 0) {
rootFile.defaultProject = rootedProject;
openFileRoots.push(rootFile);
}
@@ -916,7 +915,7 @@ module ts.server {
return rawConfig.error;
}
else {
var parsedCommandLine = ts.parseConfigFile(rawConfig.config, ts.sys, dirPath);
var parsedCommandLine = ts.parseConfigFile(rawConfig.config, this.host, dirPath);
if (parsedCommandLine.errors && (parsedCommandLine.errors.length > 0)) {
return { errorMsg: "tsconfig option errors" };
}
@@ -953,7 +952,7 @@ module ts.server {
}
class CompilerService {
export class CompilerService {
host: LSHost;
languageService: ts.LanguageService;
classifier: ts.Classifier;
@@ -985,7 +984,7 @@ module ts.server {
static defaultFormatCodeOptions: ts.FormatCodeOptions = {
IndentSize: 4,
TabSize: 4,
NewLineCharacter: ts.sys.newLine,
NewLineCharacter: ts.sys ? ts.sys.newLine : '\n',
ConvertTabsToSpaces: true,
InsertSpaceAfterCommaDelimiter: true,
InsertSpaceAfterSemicolonInForStatements: true,
@@ -999,7 +998,7 @@ module ts.server {
}
interface LineCollection {
export interface LineCollection {
charCount(): number;
lineCount(): number;
isLeaf(): boolean;
@@ -1013,7 +1012,7 @@ module ts.server {
leaf?: LineLeaf;
}
enum CharRangeSection {
export enum CharRangeSection {
PreStart,
Start,
Entire,
@@ -1022,7 +1021,7 @@ module ts.server {
PostEnd
}
interface ILineIndexWalker {
export interface ILineIndexWalker {
goSubtree: boolean;
done: boolean;
leaf(relativeStart: number, relativeLength: number, lineCollection: LineLeaf): void;
@@ -1082,7 +1081,7 @@ module ts.server {
for (var k = this.endBranch.length - 1; k >= 0; k--) {
(<LineNode>this.endBranch[k]).updateCounts();
if (this.endBranch[k].charCount() == 0) {
if (this.endBranch[k].charCount() === 0) {
lastZeroCount = this.endBranch[k];
if (k > 0) {
branchParent = <LineNode>this.endBranch[k - 1];
@@ -1147,7 +1146,7 @@ module ts.server {
post(relativeStart: number, relativeLength: number, lineCollection: LineCollection, parent: LineCollection, nodeType: CharRangeSection): LineCollection {
// have visited the path for start of range, now looking for end
// if range is on single line, we will never make this state transition
if (lineCollection == this.lineCollectionAtBranch) {
if (lineCollection === this.lineCollectionAtBranch) {
this.state = CharRangeSection.End;
}
// always pop stack because post only called when child has been visited
@@ -1159,7 +1158,7 @@ module ts.server {
// currentNode corresponds to parent, but in the new tree
var currentNode = this.stack[this.stack.length - 1];
if ((this.state == CharRangeSection.Entire) && (nodeType == CharRangeSection.Start)) {
if ((this.state === CharRangeSection.Entire) && (nodeType === CharRangeSection.Start)) {
// if range is on single line, we will never make this state transition
this.state = CharRangeSection.Start;
this.branchNode = currentNode;
@@ -1176,12 +1175,12 @@ module ts.server {
switch (nodeType) {
case CharRangeSection.PreStart:
this.goSubtree = false;
if (this.state != CharRangeSection.End) {
if (this.state !== CharRangeSection.End) {
currentNode.add(lineCollection);
}
break;
case CharRangeSection.Start:
if (this.state == CharRangeSection.End) {
if (this.state === CharRangeSection.End) {
this.goSubtree = false;
}
else {
@@ -1191,7 +1190,7 @@ module ts.server {
}
break;
case CharRangeSection.Entire:
if (this.state != CharRangeSection.End) {
if (this.state !== CharRangeSection.End) {
child = fresh(lineCollection);
currentNode.add(child);
this.startPath[this.startPath.length] = child;
@@ -1208,7 +1207,7 @@ module ts.server {
this.goSubtree = false;
break;
case CharRangeSection.End:
if (this.state != CharRangeSection.End) {
if (this.state !== CharRangeSection.End) {
this.goSubtree = false;
}
else {
@@ -1221,7 +1220,7 @@ module ts.server {
break;
case CharRangeSection.PostEnd:
this.goSubtree = false;
if (this.state != CharRangeSection.Start) {
if (this.state !== CharRangeSection.Start) {
currentNode.add(lineCollection);
}
break;
@@ -1233,10 +1232,10 @@ module ts.server {
}
// just gather text from the leaves
leaf(relativeStart: number, relativeLength: number, ll: LineLeaf) {
if (this.state == CharRangeSection.Start) {
if (this.state === CharRangeSection.Start) {
this.initialText = ll.text.substring(0, relativeStart);
}
else if (this.state == CharRangeSection.Entire) {
else if (this.state === CharRangeSection.Entire) {
this.initialText = ll.text.substring(0, relativeStart);
this.trailingText = ll.text.substring(relativeStart + relativeLength);
}
@@ -1248,7 +1247,7 @@ module ts.server {
}
// text change information
class TextChange {
export class TextChange {
constructor(public pos: number, public deleteLen: number, public insertedText?: string) {
}
@@ -1263,6 +1262,7 @@ module ts.server {
versions: LineIndexSnapshot[] = [];
minVersion = 0; // no versions earlier than min version will maintain change history
private currentVersion = 0;
private host: ServerHost;
static changeNumberThreshold = 8;
static changeLengthThreshold = 256;
@@ -1290,7 +1290,7 @@ module ts.server {
}
reloadFromFile(filename: string, cb?: () => any) {
var content = ts.sys.readFile(filename);
var content = this.host.readFile(filename);
this.reload(content);
if (cb)
cb();
@@ -1360,10 +1360,11 @@ module ts.server {
}
}
static fromString(script: string) {
static fromString(host: ServerHost, script: string) {
var svc = new ScriptVersionCache();
var snap = new LineIndexSnapshot(0, svc);
svc.versions[svc.currentVersion] = snap;
svc.host = host;
snap.index = new LineIndex();
var lm = LineIndex.linesFromText(script);
snap.index.load(lm.lines);
@@ -1371,7 +1372,7 @@ module ts.server {
}
}
class LineIndexSnapshot implements ts.IScriptSnapshot {
export class LineIndexSnapshot implements ts.IScriptSnapshot {
index: LineIndex;
changesSincePreviousVersion: TextChange[] = [];
@@ -1499,8 +1500,8 @@ module ts.server {
function editFlat(source: string, s: number, dl: number, nt = "") {
return source.substring(0, s) + nt + source.substring(s + dl, source.length);
}
if (this.root.charCount() == 0) {
// TODO: assert deleteLength == 0
if (this.root.charCount() === 0) {
// TODO: assert deleteLength === 0
if (newText) {
this.load(LineIndex.linesFromText(newText).lines);
return this;
@@ -1528,7 +1529,7 @@ module ts.server {
// check whether last characters deleted are line break
var e = pos + deleteLength;
var lineInfo = this.charOffsetToLineNumberAndPos(e);
if ((lineInfo && (lineInfo.offset == 0))) {
if ((lineInfo && (lineInfo.offset === 0))) {
// move range end just past line that will merge with previous line
deleteLength += lineInfo.text.length;
// store text by appending to end of insertedText
@@ -1574,7 +1575,7 @@ module ts.server {
interiorNodes[i].totalChars = charCount;
interiorNodes[i].totalLines = lineCount;
}
if (interiorNodes.length == 1) {
if (interiorNodes.length === 1) {
return interiorNodes[0];
}
else {
@@ -1585,7 +1586,7 @@ module ts.server {
static linesFromText(text: string) {
var lineStarts = ts.computeLineStarts(text);
if (lineStarts.length == 0) {
if (lineStarts.length === 0) {
return { lines: <string[]>[], lineMap: lineStarts };
}
var lines = <string[]>new Array(lineStarts.length);
@@ -1605,7 +1606,7 @@ module ts.server {
}
}
class LineNode implements LineCollection {
export class LineNode implements LineCollection {
totalChars = 0;
totalLines = 0;
children: LineCollection[] = [];
@@ -1821,7 +1822,7 @@ module ts.server {
findChildIndex(child: LineCollection) {
var childIndex = 0;
var clen = this.children.length;
while ((this.children[childIndex] != child) && (childIndex < clen)) childIndex++;
while ((this.children[childIndex] !== child) && (childIndex < clen)) childIndex++;
return childIndex;
}
@@ -1830,7 +1831,7 @@ module ts.server {
var clen = this.children.length;
var nodeCount = nodes.length;
// if child is last and there is more room and only one node to place, place it
if ((clen < lineCollectionCapacity) && (childIndex == (clen - 1)) && (nodeCount == 1)) {
if ((clen < lineCollectionCapacity) && (childIndex === (clen - 1)) && (nodeCount === 1)) {
this.add(nodes[0]);
this.updateCounts();
return [];
@@ -1854,13 +1855,13 @@ module ts.server {
var splitNode = <LineNode>splitNodes[0];
while (nodeIndex < nodeCount) {
splitNode.add(nodes[nodeIndex++]);
if (splitNode.children.length == lineCollectionCapacity) {
if (splitNode.children.length === lineCollectionCapacity) {
splitNodeIndex++;
splitNode = <LineNode>splitNodes[splitNodeIndex];
}
}
for (i = splitNodes.length - 1; i >= 0; i--) {
if (splitNodes[i].children.length == 0) {
if (splitNodes[i].children.length === 0) {
splitNodes.length--;
}
}
@@ -1891,7 +1892,7 @@ module ts.server {
}
}
class LineLeaf implements LineCollection {
export class LineLeaf implements LineCollection {
udata: any;
constructor(public text: string) {
+2 -2
View File
@@ -584,9 +584,9 @@ declare module NodeJS {
export interface Response extends Message {
request_seq: number;
success: boolean;
/** Contains error message if success == false. */
/** Contains error message if success === false. */
message?: string;
/** Contains message body if success == true. */
/** Contains message body if success === true. */
body?: any;
}
+3 -3
View File
@@ -1,7 +1,7 @@
/**
* Declaration module describing the TypeScript Server protocol
*/
declare module ts.server.protocol {
declare namespace ts.server.protocol {
/**
* A TypeScript Server message
*/
@@ -67,12 +67,12 @@ declare module ts.server.protocol {
command: string;
/**
* Contains error message if success == false.
* Contains error message if success === false.
*/
message?: string;
/**
* Contains message body if success == true.
* Contains message body if success === true.
*/
body?: any;
}
+6 -6
View File
@@ -1,7 +1,7 @@
/// <reference path="node.d.ts" />
/// <reference path="session.ts" />
module ts.server {
namespace ts.server {
var nodeproto: typeof NodeJS._debugger = require('_debugger');
var readline: NodeJS.ReadLine = require('readline');
var path: NodeJS.Path = require('path');
@@ -11,7 +11,7 @@ module ts.server {
input: process.stdin,
output: process.stdout,
terminal: false,
});
});
class Logger implements ts.server.Logger {
fd = -1;
@@ -123,7 +123,7 @@ module ts.server {
if (err) {
watchedFile.callback(watchedFile.fileName);
}
else if (watchedFile.mtime.getTime() != stats.mtime.getTime()) {
else if (watchedFile.mtime.getTime() !== stats.mtime.getTime()) {
watchedFile.mtime = WatchedFileSet.getModifiedTime(watchedFile.fileName);
watchedFile.callback(watchedFile.fileName);
}
@@ -138,7 +138,7 @@ module ts.server {
var count = 0;
var nextToCheck = this.nextFileToCheck;
var firstCheck = -1;
while ((count < this.chunkSize) && (nextToCheck != firstCheck)) {
while ((count < this.chunkSize) && (nextToCheck !== firstCheck)) {
this.poll(nextToCheck);
if (firstCheck < 0) {
firstCheck = nextToCheck;
@@ -170,11 +170,11 @@ module ts.server {
removeFile(file: WatchedFile) {
this.watchedFiles = WatchedFileSet.copyListRemovingItem(file, this.watchedFiles);
}
}
}
class IOSession extends Session {
constructor(host: ServerHost, logger: ts.server.Logger) {
super(host, logger);
super(host, Buffer.byteLength, process.hrtime, logger);
}
exit() {
+21 -17
View File
@@ -1,10 +1,9 @@
/// <reference path="..\compiler\commandLineParser.ts" />
/// <reference path="..\services\services.ts" />
/// <reference path="node.d.ts" />
/// <reference path="protocol.d.ts" />
/// <reference path="editorServices.ts" />
module ts.server {
namespace ts.server {
var spaceCache:string[] = [];
interface StackTraceError extends Error {
@@ -31,7 +30,7 @@ module ts.server {
if (a < b) {
return -1;
}
else if (a == b) {
else if (a === b) {
return 0;
}
else return 1;
@@ -43,7 +42,7 @@ module ts.server {
}
else if (a.file == b.file) {
var n = compareNumber(a.start.line, b.start.line);
if (n == 0) {
if (n === 0) {
return compareNumber(a.start.offset, b.start.offset);
}
else return n;
@@ -61,7 +60,7 @@ module ts.server {
};
}
interface PendingErrorCheck {
export interface PendingErrorCheck {
fileName: string;
project: Project;
}
@@ -114,11 +113,16 @@ module ts.server {
pendingOperation = false;
fileHash: ts.Map<number> = {};
nextFileId = 1;
errorTimer: NodeJS.Timer;
errorTimer: any; /*NodeJS.Timer | number*/
immediateId: any;
changeSeq = 0;
constructor(private host: ServerHost, private logger: Logger) {
constructor(
private host: ServerHost,
private byteLength: (buf: string, encoding?: string) => number,
private hrtime: (start?: number[]) => number[],
private logger: Logger
) {
this.projectService =
new ProjectService(host, logger, (eventName,project,fileName) => {
this.handleEvent(eventName, project, fileName);
@@ -129,7 +133,7 @@ module ts.server {
if (eventName == "context") {
this.projectService.log("got context event, updating diagnostics for" + fileName, "Info");
this.updateErrorCheck([{ fileName, project }], this.changeSeq,
(n) => n == this.changeSeq, 100);
(n) => n === this.changeSeq, 100);
}
}
@@ -149,17 +153,17 @@ module ts.server {
this.host.write(line + this.host.newLine);
}
send(msg: NodeJS._debugger.Message) {
send(msg: protocol.Message) {
var json = JSON.stringify(msg);
if (this.logger.isVerbose()) {
this.logger.info(msg.type + ": " + json);
}
this.sendLineToClient('Content-Length: ' + (1 + Buffer.byteLength(json, 'utf8')) +
this.sendLineToClient('Content-Length: ' + (1 + this.byteLength(json, 'utf8')) +
'\r\n\r\n' + json);
}
event(info: any, eventName: string) {
var ev: NodeJS._debugger.Event = {
var ev: protocol.Event = {
seq: 0,
type: "event",
event: eventName,
@@ -546,7 +550,7 @@ module ts.server {
// getFormattingEditsAfterKeytroke either empty or pertaining
// only to the previous line. If all this is true, then
// add edits necessary to properly indent the current line.
if ((key == "\n") && ((!edits) || (edits.length == 0) || allEditsBeforePos(edits, position))) {
if ((key == "\n") && ((!edits) || (edits.length === 0) || allEditsBeforePos(edits, position))) {
var scriptInfo = compilerService.host.getScriptInfo(file);
if (scriptInfo) {
var lineInfo = scriptInfo.getLineInfo(line);
@@ -622,7 +626,7 @@ module ts.server {
}
return completions.entries.reduce((result: protocol.CompletionEntry[], entry: ts.CompletionEntry) => {
if (completions.isMemberCompletion || (entry.name.toLowerCase().indexOf(prefix.toLowerCase()) == 0)) {
if (completions.isMemberCompletion || (entry.name.toLowerCase().indexOf(prefix.toLowerCase()) === 0)) {
result.push(entry);
}
return result;
@@ -689,7 +693,7 @@ module ts.server {
}, []);
if (checkList.length > 0) {
this.updateErrorCheck(checkList, this.changeSeq,(n) => n == this.changeSeq, delay)
this.updateErrorCheck(checkList, this.changeSeq,(n) => n === this.changeSeq, delay)
}
}
@@ -704,7 +708,7 @@ module ts.server {
compilerService.host.editScript(file, start, end, insertString);
this.changeSeq++;
}
this.updateProjectStructure(this.changeSeq, (n) => n == this.changeSeq);
this.updateProjectStructure(this.changeSeq, (n) => n === this.changeSeq);
}
}
@@ -838,7 +842,7 @@ module ts.server {
onMessage(message: string) {
if (this.logger.isVerbose()) {
this.logger.info("request: " + message);
var start = process.hrtime();
var start = this.hrtime();
}
try {
var request = <protocol.Request>JSON.parse(message);
@@ -980,7 +984,7 @@ module ts.server {
}
if (this.logger.isVerbose()) {
var elapsed = process.hrtime(start);
var elapsed = this.hrtime(start);
var seconds = elapsed[0]
var nanoseconds = elapsed[1];
var elapsedMs = ((1e9 * seconds) + nanoseconds)/1000000.0;
+2 -2
View File
@@ -4,7 +4,7 @@
/// <reference path='services.ts' />
/* @internal */
module ts.BreakpointResolver {
namespace ts.BreakpointResolver {
/**
* Get the breakpoint span in given sourceFile
*/
@@ -75,7 +75,7 @@ module ts.BreakpointResolver {
return textSpan(node);
}
if (node.parent.kind == SyntaxKind.ArrowFunction && (<FunctionLikeDeclaration>node.parent).body == node) {
if (node.parent.kind === SyntaxKind.ArrowFunction && (<FunctionLikeDeclaration>node.parent).body === node) {
// If this is body of arrow function, it is allowed to have the breakpoint
return textSpan(node);
}
+1 -1
View File
@@ -4,7 +4,7 @@
///<reference path='references.ts' />
/* @internal */
module ts.formatting {
namespace ts.formatting {
export interface TextRangeWithKind extends TextRange {
kind: SyntaxKind;
+3 -3
View File
@@ -1,7 +1,7 @@
/// <reference path="references.ts"/>
/* @internal */
module ts.formatting {
namespace ts.formatting {
export class FormattingContext {
public currentTokenSpan: TextRangeWithKind;
public nextTokenSpan: TextRangeWithKind;
@@ -59,7 +59,7 @@ module ts.formatting {
if (this.tokensAreOnSameLine === undefined) {
let startLine = this.sourceFile.getLineAndCharacterOfPosition(this.currentTokenSpan.pos).line;
let endLine = this.sourceFile.getLineAndCharacterOfPosition(this.nextTokenSpan.pos).line;
this.tokensAreOnSameLine = (startLine == endLine);
this.tokensAreOnSameLine = (startLine === endLine);
}
return this.tokensAreOnSameLine;
@@ -84,7 +84,7 @@ module ts.formatting {
private NodeIsOnOneLine(node: Node): boolean {
let startLine = this.sourceFile.getLineAndCharacterOfPosition(node.getStart(this.sourceFile)).line;
let endLine = this.sourceFile.getLineAndCharacterOfPosition(node.getEnd()).line;
return startLine == endLine;
return startLine === endLine;
}
private BlockIsOnOneLine(node: Node): boolean {
@@ -1,7 +1,7 @@
/// <reference path="references.ts"/>
/* @internal */
module ts.formatting {
namespace ts.formatting {
export const enum FormattingRequestKind {
FormatDocument,
FormatSelection,
+2 -2
View File
@@ -2,7 +2,7 @@
/// <reference path="..\..\compiler\scanner.ts"/>
/* @internal */
module ts.formatting {
namespace ts.formatting {
let scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false);
export interface FormattingScanner {
@@ -224,7 +224,7 @@ module ts.formatting {
}
function isOnToken(): boolean {
let current = (lastTokenInfo && lastTokenInfo.token.kind) || scanner.getToken();
let current = (lastTokenInfo && lastTokenInfo.token.kind) || scanner.getToken();
let startPos = (lastTokenInfo && lastTokenInfo.token.pos) || scanner.getStartPos();
return startPos < endPos && current !== SyntaxKind.EndOfFileToken && !isTrivia(current);
}
+1 -1
View File
@@ -1,7 +1,7 @@
///<reference path='references.ts' />
/* @internal */
module ts.formatting {
namespace ts.formatting {
export class Rule {
constructor(
public Descriptor: RuleDescriptor,
+1 -1
View File
@@ -1,7 +1,7 @@
///<reference path='references.ts' />
/* @internal */
module ts.formatting {
namespace ts.formatting {
export const enum RuleAction {
Ignore = 0x00000001,
Space = 0x00000002,
+1 -1
View File
@@ -1,7 +1,7 @@
///<reference path='references.ts' />
/* @internal */
module ts.formatting {
namespace ts.formatting {
export class RuleDescriptor {
constructor(public LeftTokenRange: Shared.TokenRange, public RightTokenRange: Shared.TokenRange) {
}
+1 -1
View File
@@ -2,7 +2,7 @@
/* @internal */
module ts.formatting {
namespace ts.formatting {
export const enum RuleFlags {
None,
CanDeleteNewLines
+1 -1
View File
@@ -1,7 +1,7 @@
///<reference path='references.ts' />
/* @internal */
module ts.formatting {
namespace ts.formatting {
export class RuleOperation {
public Context: RuleOperationContext;
public Action: RuleAction;
@@ -1,7 +1,7 @@
///<reference path='references.ts' />
/* @internal */
module ts.formatting {
namespace ts.formatting {
export class RuleOperationContext {
private customContextChecks: { (context: FormattingContext): boolean; }[];
@@ -14,7 +14,7 @@ module ts.formatting {
public IsAny(): boolean {
return this == RuleOperationContext.Any;
return this === RuleOperationContext.Any;
}
public InContext(context: FormattingContext): boolean {
+5 -4
View File
@@ -1,7 +1,7 @@
///<reference path='references.ts' />
/* @internal */
module ts.formatting {
namespace ts.formatting {
export class Rules {
public getRuleName(rule: Rule) {
let o: ts.Map<any> = <any>this;
@@ -193,7 +193,7 @@ module ts.formatting {
// Insert space after function keyword for anonymous functions
public SpaceAfterAnonymousFunctionKeyword: Rule;
public NoSpaceAfterAnonymousFunctionKeyword: Rule;
// Insert space after @ in decorator
public SpaceBeforeAt: Rule;
public NoSpaceAfterAt: Rule;
@@ -470,8 +470,9 @@ module ts.formatting {
switch (context.contextNode.kind) {
case SyntaxKind.BinaryExpression:
case SyntaxKind.ConditionalExpression:
case SyntaxKind.TypePredicate:
return true;
// equals in binding elements: function foo([[x, y] = [1, 2]])
case SyntaxKind.BindingElement:
// equals in type X = ...
@@ -691,7 +692,7 @@ module ts.formatting {
}
static IsNotFormatOnEnter(context: FormattingContext): boolean {
return context.formattingRequestKind != FormattingRequestKind.FormatOnEnter;
return context.formattingRequestKind !== FormattingRequestKind.FormatOnEnter;
}
static IsModuleDeclContext(context: FormattingContext): boolean {
+6 -6
View File
@@ -1,7 +1,7 @@
///<reference path='references.ts' />
/* @internal */
module ts.formatting {
namespace ts.formatting {
export class RulesMap {
public map: RulesBucket[];
public mapRowLength: number;
@@ -41,15 +41,15 @@ module ts.formatting {
}
private FillRule(rule: Rule, rulesBucketConstructionStateList: RulesBucketConstructionState[]): void {
let specificRule = rule.Descriptor.LeftTokenRange != Shared.TokenRange.Any &&
rule.Descriptor.RightTokenRange != Shared.TokenRange.Any;
let specificRule = rule.Descriptor.LeftTokenRange !== Shared.TokenRange.Any &&
rule.Descriptor.RightTokenRange !== Shared.TokenRange.Any;
rule.Descriptor.LeftTokenRange.GetTokens().forEach((left) => {
rule.Descriptor.RightTokenRange.GetTokens().forEach((right) => {
let rulesBucketIndex = this.GetRuleBucketIndex(left, right);
let rulesBucket = this.map[rulesBucketIndex];
if (rulesBucket == undefined) {
if (rulesBucket === undefined) {
rulesBucket = this.map[rulesBucketIndex] = new RulesBucket();
}
@@ -124,7 +124,7 @@ module ts.formatting {
public IncreaseInsertionIndex(maskPosition: RulesPosition): void {
let value = (this.rulesInsertionIndexBitmap >> maskPosition) & Mask;
value++;
Debug.assert((value & Mask) == value, "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules.");
Debug.assert((value & Mask) === value, "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules.");
let temp = this.rulesInsertionIndexBitmap & ~(Mask << maskPosition);
temp |= value << maskPosition;
@@ -147,7 +147,7 @@ module ts.formatting {
public AddRule(rule: Rule, specificTokens: boolean, constructionState: RulesBucketConstructionState[], rulesBucketIndex: number): void {
let position: RulesPosition;
if (rule.Operation.Action == RuleAction.Ignore) {
if (rule.Operation.Action === RuleAction.Ignore) {
position = specificTokens ?
RulesPosition.IgnoreRulesSpecific :
RulesPosition.IgnoreRulesAny;
+2 -1
View File
@@ -1,7 +1,7 @@
/// <reference path="references.ts"/>
/* @internal */
module ts.formatting {
namespace ts.formatting {
export class RulesProvider {
private globalRules: Rules;
private options: ts.FormatCodeOptions;
@@ -25,6 +25,7 @@ module ts.formatting {
}
public ensureUpToDate(options: ts.FormatCodeOptions) {
// TODO: Should this be '==='?
if (this.options == null || !ts.compareDataObjects(this.options, options)) {
let activeRules = this.createActiveRules(options);
let rulesMap = RulesMap.create(activeRules);
+1 -1
View File
@@ -1,7 +1,7 @@
///<reference path='..\services.ts' />
/* @internal */
module ts.formatting {
namespace ts.formatting {
export module SmartIndenter {
const enum Value {
+3 -3
View File
@@ -1,7 +1,7 @@
///<reference path='references.ts' />
/* @internal */
module ts.formatting {
namespace ts.formatting {
export module Shared {
export interface ITokenAccess {
GetTokens(): SyntaxKind[];
@@ -54,7 +54,7 @@ module ts.formatting {
}
public Contains(tokenValue: SyntaxKind): boolean {
return tokenValue == this.token;
return tokenValue === this.token;
}
}
@@ -112,7 +112,7 @@ module ts.formatting {
static AnyIncludingMultilineComments = TokenRange.FromTokens(TokenRange.Any.GetTokens().concat([SyntaxKind.MultiLineCommentTrivia]));
static Keywords = TokenRange.FromRange(SyntaxKind.FirstKeyword, SyntaxKind.LastKeyword);
static BinaryOperators = TokenRange.FromRange(SyntaxKind.FirstBinaryOperator, SyntaxKind.LastBinaryOperator);
static BinaryKeywordOperators = TokenRange.FromTokens([SyntaxKind.InKeyword, SyntaxKind.InstanceOfKeyword, SyntaxKind.OfKeyword]);
static BinaryKeywordOperators = TokenRange.FromTokens([SyntaxKind.InKeyword, SyntaxKind.InstanceOfKeyword, SyntaxKind.OfKeyword, SyntaxKind.IsKeyword]);
static UnaryPrefixOperators = TokenRange.FromTokens([SyntaxKind.PlusPlusToken, SyntaxKind.MinusMinusToken, SyntaxKind.TildeToken, SyntaxKind.ExclamationToken]);
static UnaryPrefixExpressions = TokenRange.FromTokens([SyntaxKind.NumericLiteral, SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.OpenBracketToken, SyntaxKind.OpenBraceToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword]);
static UnaryPreincrementExpressions = TokenRange.FromTokens([SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword]);
+1 -1
View File
@@ -1,5 +1,5 @@
/* @internal */
module ts.NavigateTo {
namespace ts.NavigateTo {
type RawNavigateToItem = { name: string; fileName: string; matchKind: PatternMatchKind; isCaseSensitive: boolean; declaration: Declaration };
export function getNavigateToItems(program: Program, cancellationToken: CancellationTokenObject, searchValue: string, maxResultCount: number): NavigateToItem[] {
+1 -1
View File
@@ -1,7 +1,7 @@
/// <reference path='services.ts' />
/* @internal */
module ts.NavigationBar {
namespace ts.NavigationBar {
export function getNavigationBarItems(sourceFile: SourceFile): ts.NavigationBarItem[] {
// If the source file has any child items, then it included in the tree
// and takes lexical ownership of all other top-level items.
+1 -1
View File
@@ -1,5 +1,5 @@
/* @internal */
module ts {
namespace ts {
export module OutliningElementsCollector {
export function collectElements(sourceFile: SourceFile): OutliningSpan[] {
let elements: OutliningSpan[] = [];
+3 -3
View File
@@ -1,5 +1,5 @@
/* @internal */
module ts {
namespace ts {
// Note(cyrusn): this enum is ordered from strongest match type to weakest match type.
export enum PatternMatchKind {
exact,
@@ -686,7 +686,7 @@ module ts {
if (charIsPunctuation(identifier.charCodeAt(i - 1)) ||
charIsPunctuation(identifier.charCodeAt(i)) ||
lastIsDigit != currentIsDigit ||
lastIsDigit !== currentIsDigit ||
hasTransitionFromLowerToUpper ||
hasTransitionFromUpperToLower) {
@@ -757,7 +757,7 @@ module ts {
// 3) HTMLDocument -> HTML, Document
//
// etc.
if (index != wordStart &&
if (index !== wordStart &&
index + 1 < identifier.length) {
let currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index));
let nextIsLower = isLowerCaseLetter(identifier.charCodeAt(index + 1));
+125 -83
View File
@@ -10,7 +10,7 @@
/// <reference path='formatting\formatting.ts' />
/// <reference path='formatting\smartIndenter.ts' />
module ts {
namespace ts {
/** The version of the language service API */
export let servicesVersion = "0.4"
@@ -167,7 +167,7 @@ module ts {
}
public getFullWidth(): number {
return this.end - this.getFullStart();
return this.end - this.pos;
}
public getLeadingTriviaWidth(sourceFile?: SourceFile): number {
@@ -735,7 +735,7 @@ module ts {
public endOfFileToken: Node;
public amdDependencies: { name: string; path: string }[];
public amdModuleName: string;
public moduleName: string;
public referencedFiles: FileReference[];
public syntacticDiagnostics: Diagnostic[];
@@ -743,6 +743,7 @@ module ts {
public parseDiagnostics: Diagnostic[];
public bindDiagnostics: Diagnostic[];
public isDefaultLib: boolean;
public hasNoDefaultLib: boolean;
public externalModuleIndicator: Node; // The first node that causes this file to be an external module
public nodeCount: number;
@@ -960,6 +961,7 @@ module ts {
log? (s: string): void;
trace? (s: string): void;
error? (s: string): void;
useCaseSensitiveFileNames? (): boolean;
}
//
@@ -971,6 +973,9 @@ module ts {
getSyntacticDiagnostics(fileName: string): Diagnostic[];
getSemanticDiagnostics(fileName: string): Diagnostic[];
// TODO: Rename this to getProgramDiagnostics to better indicate that these are any
// diagnostics present for the program level, and not just 'options' diagnostics.
getCompilerOptionsDiagnostics(): Diagnostic[];
/**
@@ -1632,12 +1637,12 @@ module ts {
// at each language service public entry point, since we don't know when
// set of scripts handled by the host changes.
class HostCache {
private fileNameToEntry: Map<HostFileInformation>;
private fileNameToEntry: FileMap<HostFileInformation>;
private _compilationSettings: CompilerOptions;
constructor(private host: LanguageServiceHost, private getCanonicalFileName: (fileName: string) => string) {
constructor(private host: LanguageServiceHost, getCanonicalFileName: (fileName: string) => string) {
// script id => script index
this.fileNameToEntry = {};
this.fileNameToEntry = createFileMap<HostFileInformation>(getCanonicalFileName);
// Initialize the list with the root file names
let rootFileNames = host.getScriptFileNames();
@@ -1653,10 +1658,6 @@ module ts {
return this._compilationSettings;
}
private normalizeFileName(fileName: string): string {
return this.getCanonicalFileName(normalizeSlashes(fileName));
}
private createEntry(fileName: string) {
let entry: HostFileInformation;
let scriptSnapshot = this.host.getScriptSnapshot(fileName);
@@ -1668,15 +1669,16 @@ module ts {
};
}
return this.fileNameToEntry[this.normalizeFileName(fileName)] = entry;
this.fileNameToEntry.set(fileName, entry);
return entry;
}
private getEntry(fileName: string): HostFileInformation {
return lookUp(this.fileNameToEntry, this.normalizeFileName(fileName));
return this.fileNameToEntry.get(fileName);
}
private contains(fileName: string): boolean {
return hasProperty(this.fileNameToEntry, this.normalizeFileName(fileName));
return this.fileNameToEntry.contains(fileName);
}
public getOrCreateEntry(fileName: string): HostFileInformation {
@@ -1690,10 +1692,9 @@ module ts {
public getRootFileNames(): string[] {
let fileNames: string[] = [];
forEachKey(this.fileNameToEntry, key => {
let entry = this.getEntry(key);
if (entry) {
fileNames.push(entry.hostFileName);
this.fileNameToEntry.forEachValue(value => {
if (value) {
fileNames.push(value.hostFileName);
}
});
@@ -1765,8 +1766,10 @@ module ts {
* Extra compiler options that will unconditionally be used bu this function are:
* - isolatedModules = true
* - allowNonTsExtensions = true
* - noLib = true
* - noResolve = true
*/
export function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[]): string {
export function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[], moduleName?: string): string {
let options = compilerOptions ? clone(compilerOptions) : getDefaultCompilerOptions();
options.isolatedModules = true;
@@ -1774,15 +1777,23 @@ module ts {
// Filename can be non-ts file.
options.allowNonTsExtensions = true;
// Parse
var inputFileName = fileName || "module.ts";
var sourceFile = createSourceFile(inputFileName, input, options.target);
// We are not returning a sourceFile for lib file when asked by the program,
// so pass --noLib to avoid reporting a file not found error.
options.noLib = true;
// Store syntactic diagnostics
if (diagnostics && sourceFile.parseDiagnostics) {
diagnostics.push(...sourceFile.parseDiagnostics);
// We are not doing a full typecheck, we are not resolving the whole context,
// so pass --noResolve to avoid reporting missing file errors.
options.noResolve = true;
// Parse
let inputFileName = fileName || "module.ts";
let sourceFile = createSourceFile(inputFileName, input, options.target);
if (moduleName) {
sourceFile.moduleName = moduleName;
}
let newLine = getNewLineCharacter(options);
// Output
let outputText: string;
@@ -1797,14 +1808,13 @@ module ts {
useCaseSensitiveFileNames: () => false,
getCanonicalFileName: fileName => fileName,
getCurrentDirectory: () => "",
getNewLine: () => (sys && sys.newLine) || "\r\n"
getNewLine: () => newLine
};
var program = createProgram([inputFileName], options, compilerHost);
if (diagnostics) {
diagnostics.push(...program.getGlobalDiagnostics());
}
addRange(/*to*/ diagnostics, /*from*/ program.getSyntacticDiagnostics(sourceFile));
addRange(/*to*/ diagnostics, /*from*/ program.getOptionsDiagnostics());
// Emit
program.emit();
@@ -1873,20 +1883,28 @@ module ts {
return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents:*/ true);
}
export function createDocumentRegistry(): DocumentRegistry {
function createGetCanonicalFileName(useCaseSensitivefileNames: boolean): (fileName: string) => string {
return useCaseSensitivefileNames
? ((fileName) => fileName)
: ((fileName) => fileName.toLowerCase());
}
export function createDocumentRegistry(useCaseSensitiveFileNames?: boolean): DocumentRegistry {
// Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have
// for those settings.
let buckets: Map<Map<DocumentRegistryEntry>> = {};
let buckets: Map<FileMap<DocumentRegistryEntry>> = {};
let getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames);
function getKeyFromCompilationSettings(settings: CompilerOptions): string {
return "_" + settings.target; // + "|" + settings.propagateEnumConstantoString()
}
function getBucketForCompilationSettings(settings: CompilerOptions, createIfMissing: boolean): Map<DocumentRegistryEntry> {
function getBucketForCompilationSettings(settings: CompilerOptions, createIfMissing: boolean): FileMap<DocumentRegistryEntry> {
let key = getKeyFromCompilationSettings(settings);
let bucket = lookUp(buckets, key);
if (!bucket && createIfMissing) {
buckets[key] = bucket = {};
buckets[key] = bucket = createFileMap<DocumentRegistryEntry>(getCanonicalFileName);
}
return bucket;
}
@@ -1896,7 +1914,7 @@ module ts {
let entries = lookUp(buckets, name);
let sourceFiles: { name: string; refCount: number; references: string[]; }[] = [];
for (let i in entries) {
let entry = entries[i];
let entry = entries.get(i);
sourceFiles.push({
name: i,
refCount: entry.languageServiceRefCount,
@@ -1928,18 +1946,19 @@ module ts {
acquiring: boolean): SourceFile {
let bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true);
let entry = lookUp(bucket, fileName);
let entry = bucket.get(fileName);
if (!entry) {
Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?");
// Have never seen this file with these settings. Create a new source file for it.
let sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents:*/ false);
bucket[fileName] = entry = {
entry = {
sourceFile: sourceFile,
languageServiceRefCount: 0,
owners: []
};
bucket.set(fileName, entry);
}
else {
// We have an entry for this file. However, it may be for a different version of
@@ -1967,12 +1986,12 @@ module ts {
let bucket = getBucketForCompilationSettings(compilationSettings, false);
Debug.assert(bucket !== undefined);
let entry = lookUp(bucket, fileName);
let entry = bucket.get(fileName);
entry.languageServiceRefCount--;
Debug.assert(entry.languageServiceRefCount >= 0);
if (entry.languageServiceRefCount === 0) {
delete bucket[fileName];
bucket.remove(fileName);
}
}
@@ -2400,9 +2419,7 @@ module ts {
}
}
function getCanonicalFileName(fileName: string) {
return useCaseSensitivefileNames ? fileName : fileName.toLowerCase();
}
let getCanonicalFileName = createGetCanonicalFileName(useCaseSensitivefileNames);
function getValidSourceFile(fileName: string): SourceFile {
fileName = normalizeSlashes(fileName);
@@ -2776,7 +2793,7 @@ module ts {
function getCompilerOptionsDiagnostics() {
synchronizeHostData();
return program.getGlobalDiagnostics();
return program.getOptionsDiagnostics().concat(program.getGlobalDiagnostics());
}
/// Completion
@@ -4168,7 +4185,7 @@ module ts {
var result: DefinitionInfo[] = [];
forEach((<UnionType>type).types, t => {
if (t.symbol) {
result.push(...getDefinitionFromSymbol(t.symbol, node));
addRange(/*to*/ result, /*from*/ getDefinitionFromSymbol(t.symbol, node));
}
});
return result;
@@ -5756,7 +5773,8 @@ module ts {
node = node.parent;
}
return node.parent.kind === SyntaxKind.TypeReference || node.parent.kind === SyntaxKind.ExpressionWithTypeArguments;
return node.parent.kind === SyntaxKind.TypeReference ||
(node.parent.kind === SyntaxKind.ExpressionWithTypeArguments && !isExpressionWithTypeArgumentsInClassExtendsClause(<ExpressionWithTypeArguments>node.parent));
}
function isNamespaceReference(node: Node): boolean {
@@ -5937,6 +5955,7 @@ module ts {
let typeChecker = program.getTypeChecker();
let result: number[] = [];
let classifiableNames = program.getClassifiableNames();
processNode(sourceFile);
return { spans: result, endOfLineState: EndOfLineState.None };
@@ -5949,6 +5968,9 @@ module ts {
function classifySymbol(symbol: Symbol, meaningAtPosition: SemanticMeaning): ClassificationType {
let flags = symbol.getFlags();
if ((flags & SymbolFlags.Classifiable) === SymbolFlags.None) {
return;
}
if (flags & SymbolFlags.Class) {
return ClassificationType.className;
@@ -5984,20 +6006,28 @@ module ts {
*/
function hasValueSideModule(symbol: Symbol): boolean {
return forEach(symbol.declarations, declaration => {
return declaration.kind === SyntaxKind.ModuleDeclaration && getModuleInstanceState(declaration) == ModuleInstanceState.Instantiated;
return declaration.kind === SyntaxKind.ModuleDeclaration &&
getModuleInstanceState(declaration) === ModuleInstanceState.Instantiated;
});
}
}
function processNode(node: Node) {
// Only walk into nodes that intersect the requested span.
if (node && textSpanIntersectsWith(span, node.getStart(), node.getWidth())) {
if (node.kind === SyntaxKind.Identifier && node.getWidth() > 0) {
let symbol = typeChecker.getSymbolAtLocation(node);
if (symbol) {
let type = classifySymbol(symbol, getMeaningFromLocation(node));
if (type) {
pushClassification(node.getStart(), node.getWidth(), type);
if (node && textSpanIntersectsWith(span, node.getFullStart(), node.getFullWidth())) {
if (node.kind === SyntaxKind.Identifier && !nodeIsMissing(node)) {
let identifier = <Identifier>node;
// Only bother calling into the typechecker if this is an identifier that
// could possibly resolve to a type name. This makes classification run
// in a third of the time it would normally take.
if (classifiableNames[identifier.text]) {
let symbol = typeChecker.getSymbolAtLocation(node);
if (symbol) {
let type = classifySymbol(symbol, getMeaningFromLocation(node));
if (type) {
pushClassification(node.getStart(), node.getWidth(), type);
}
}
}
}
@@ -6050,6 +6080,8 @@ module ts {
function getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications {
// doesn't use compiler - no need to synchronize with host
let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
let spanStart = span.start;
let spanLength = span.length;
// Make a scanner we can get trivia from.
let triviaScanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ false, sourceFile.text);
@@ -6066,48 +6098,55 @@ module ts {
result.push(type);
}
function classifyLeadingTrivia(token: Node): void {
let tokenStart = skipTrivia(sourceFile.text, token.pos, /*stopAfterLineBreak:*/ false);
if (tokenStart === token.pos) {
return;
}
// token has trivia. Classify them appropriately.
function classifyLeadingTriviaAndGetTokenStart(token: Node): number {
triviaScanner.setTextPos(token.pos);
while (true) {
let start = triviaScanner.getTextPos();
// only bother scanning if we have something that could be trivia.
if (!couldStartTrivia(sourceFile.text, start)) {
return start;
}
let kind = triviaScanner.scan();
let end = triviaScanner.getTextPos();
let width = end - start;
// The moment we get something that isn't trivia, then stop processing.
if (!isTrivia(kind)) {
return;
return start;
}
// Don't bother with newlines/whitespace.
if (kind === SyntaxKind.NewLineTrivia || kind === SyntaxKind.WhitespaceTrivia) {
continue;
}
// Only bother with the trivia if it at least intersects the span of interest.
if (textSpanIntersectsWith(span, start, width)) {
if (isComment(kind)) {
classifyComment(token, kind, start, width);
if (isComment(kind)) {
classifyComment(token, kind, start, width);
// Classifying a comment might cause us to reuse the trivia scanner
// (because of jsdoc comments). So after we classify the comment make
// sure we set the scanner position back to where it needs to be.
triviaScanner.setTextPos(end);
continue;
}
if (kind === SyntaxKind.ConflictMarkerTrivia) {
let text = sourceFile.text;
let ch = text.charCodeAt(start);
// for the <<<<<<< and >>>>>>> markers, we just add them in as comments
// in the classification stream.
if (ch === CharacterCodes.lessThan || ch === CharacterCodes.greaterThan) {
pushClassification(start, width, ClassificationType.comment);
continue;
}
if (kind === SyntaxKind.ConflictMarkerTrivia) {
let text = sourceFile.text;
let ch = text.charCodeAt(start);
// for the <<<<<<< and >>>>>>> markers, we just add them in as comments
// in the classification stream.
if (ch === CharacterCodes.lessThan || ch === CharacterCodes.greaterThan) {
pushClassification(start, width, ClassificationType.comment);
continue;
}
// for the ======== add a comment for the first line, and then lex all
// subsequent lines up until the end of the conflict marker.
Debug.assert(ch === CharacterCodes.equals);
classifyDisabledMergeCode(text, start, end);
}
// for the ======== add a comment for the first line, and then lex all
// subsequent lines up until the end of the conflict marker.
Debug.assert(ch === CharacterCodes.equals);
classifyDisabledMergeCode(text, start, end);
}
}
}
@@ -6226,12 +6265,14 @@ module ts {
}
function classifyToken(token: Node): void {
classifyLeadingTrivia(token);
let tokenStart = classifyLeadingTriviaAndGetTokenStart(token);
if (token.getWidth() > 0) {
let tokenWidth = token.end - tokenStart;
Debug.assert(tokenWidth >= 0);
if (tokenWidth > 0) {
let type = classifyTokenType(token.kind, token);
if (type) {
pushClassification(token.getStart(), token.getWidth(), type);
pushClassification(tokenStart, tokenWidth, type);
}
}
}
@@ -6336,9 +6377,10 @@ module ts {
}
// Ignore nodes that don't intersect the original span to classify.
if (textSpanIntersectsWith(span, element.getFullStart(), element.getFullWidth())) {
if (decodedTextSpanIntersectsWith(spanStart, spanLength, element.pos, element.getFullWidth())) {
let children = element.getChildren(sourceFile);
for (let child of children) {
for (let i = 0, n = children.length; i < n; i++) {
let child = children[i];
if (isToken(child)) {
classifyToken(child);
}
+31 -12
View File
@@ -19,7 +19,7 @@
var debugObjectHost = (<any>this);
/* @internal */
module ts {
namespace ts {
export interface ScriptSnapshotShim {
/** Gets a portion of the script snapshot specified by [start, end). */
getText(start: number, end: number): string;
@@ -56,6 +56,7 @@ module ts {
getDefaultLibFileName(options: string): string;
getNewLine?(): string;
getProjectVersion?(): string;
useCaseSensitiveFileNames?(): boolean;
}
/** Public interface of the the of a config service shim instance.*/
@@ -233,6 +234,7 @@ module ts {
public getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange {
var oldSnapshotShim = <ScriptSnapshotShimAdapter>oldSnapshot;
var encoded = this.scriptSnapshotShim.getChangeRange(oldSnapshotShim.scriptSnapshotShim);
// TODO: should this be '==='?
if (encoded == null) {
return null;
}
@@ -245,16 +247,22 @@ module ts {
export class LanguageServiceShimHostAdapter implements LanguageServiceHost {
private files: string[];
private loggingEnabled = false;
private tracingEnabled = false;
constructor(private shimHost: LanguageServiceShimHost) {
}
public log(s: string): void {
this.shimHost.log(s);
if (this.loggingEnabled) {
this.shimHost.log(s);
}
}
public trace(s: string): void {
this.shimHost.trace(s);
if (this.tracingEnabled) {
this.shimHost.trace(s);
}
}
public error(s: string): void {
@@ -270,8 +278,13 @@ module ts {
return this.shimHost.getProjectVersion();
}
public useCaseSensitiveFileNames(): boolean {
return this.shimHost.useCaseSensitiveFileNames ? this.shimHost.useCaseSensitiveFileNames() : false;
}
public getCompilationSettings(): CompilerOptions {
var settingsJson = this.shimHost.getCompilationSettings();
// TODO: should this be '==='?
if (settingsJson == null || settingsJson == "") {
throw Error("LanguageServiceShimHostAdapter.getCompilationSettings: empty compilationSettings");
return null;
@@ -344,15 +357,15 @@ module ts {
}
}
function simpleForwardCall(logger: Logger, actionDescription: string, action: () => any, noPerfLogging: boolean): any {
if (!noPerfLogging) {
function simpleForwardCall(logger: Logger, actionDescription: string, action: () => any, logPerformance: boolean): any {
if (logPerformance) {
logger.log(actionDescription);
var start = Date.now();
}
var result = action();
if (!noPerfLogging) {
if (logPerformance) {
var end = Date.now();
logger.log(actionDescription + " completed in " + (end - start) + " msec");
if (typeof (result) === "string") {
@@ -367,9 +380,9 @@ module ts {
return result;
}
function forwardJSONCall(logger: Logger, actionDescription: string, action: () => any, noPerfLogging: boolean): string {
function forwardJSONCall(logger: Logger, actionDescription: string, action: () => any, logPerformance: boolean): string {
try {
var result = simpleForwardCall(logger, actionDescription, action, noPerfLogging);
var result = simpleForwardCall(logger, actionDescription, action, logPerformance);
return JSON.stringify({ result: result });
}
catch (err) {
@@ -408,6 +421,7 @@ module ts {
class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim {
private logger: Logger;
private logPerformance = false;
constructor(factory: ShimFactory,
private host: LanguageServiceShimHost,
@@ -417,7 +431,7 @@ module ts {
}
public forwardJSONCall(actionDescription: string, action: () => any): string {
return forwardJSONCall(this.logger, actionDescription, action, /*noPerfLogging:*/ false);
return forwardJSONCall(this.logger, actionDescription, action, this.logPerformance);
}
/// DISPOSE
@@ -806,6 +820,7 @@ module ts {
class ClassifierShimObject extends ShimBase implements ClassifierShim {
public classifier: Classifier;
private logPerformance = false;
constructor(factory: ShimFactory, private logger: Logger) {
super(factory);
@@ -815,7 +830,7 @@ module ts {
public getEncodedLexicalClassifications(text: string, lexState: EndOfLineState, syntacticClassifierAbsent?: boolean): string {
return forwardJSONCall(this.logger, "getEncodedLexicalClassifications",
() => convertClassifications(this.classifier.getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent)),
/*noPerfLogging:*/ true);
this.logPerformance);
}
/// COLORIZATION
@@ -833,13 +848,14 @@ module ts {
}
class CoreServicesShimObject extends ShimBase implements CoreServicesShim {
private logPerformance = false;
constructor(factory: ShimFactory, public logger: Logger, private host: CoreServicesShimHostAdapter) {
super(factory);
}
private forwardJSONCall(actionDescription: string, action: () => any): any {
return forwardJSONCall(this.logger, actionDescription, action, /*noPerfLogging:*/ false);
return forwardJSONCall(this.logger, actionDescription, action, this.logPerformance);
}
public getPreProcessedFileInfo(fileName: string, sourceTextSnapshot: IScriptSnapshot): string {
@@ -909,7 +925,7 @@ module ts {
export class TypeScriptServicesFactory implements ShimFactory {
private _shims: Shim[] = [];
private documentRegistry: DocumentRegistry = createDocumentRegistry();
private documentRegistry: DocumentRegistry;
/*
* Returns script API version.
@@ -920,6 +936,9 @@ module ts {
public createLanguageServiceShim(host: LanguageServiceShimHost): LanguageServiceShim {
try {
if (this.documentRegistry === undefined) {
this.documentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames());
}
var hostAdapter = new LanguageServiceShimHostAdapter(host);
var languageService = createLanguageService(hostAdapter, this.documentRegistry);
return new LanguageServiceShimObject(this, host, languageService);
+1 -1
View File
@@ -1,6 +1,6 @@
///<reference path='services.ts' />
/* @internal */
module ts.SignatureHelp {
namespace ts.SignatureHelp {
// A partially written generic type expression is not guaranteed to have the correct syntax tree. the expression could be parsed as less than/greater than expression or a comma expression
// or some other combination depending on what the user has typed so far. For the purposes of signature help we need to consider any location after "<" as a possible generic type reference.
+2 -2
View File
@@ -1,6 +1,6 @@
// These utilities are common to multiple language service features.
/* @internal */
module ts {
namespace ts {
export interface ListItemInfo {
listItemIndex: number;
list: Node;
@@ -502,7 +502,7 @@ module ts {
// Display-part writer helpers
/* @internal */
module ts {
namespace ts {
export function isFirstDeclarationOfSymbolParameter(symbol: Symbol) {
return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === SyntaxKind.Parameter;
}