Merge branch 'master' into es6Typings

Conflicts:
	tests/baselines/reference/arrayTypeOfTypeOf.errors.txt
	tests/baselines/reference/redefineArray.errors.txt
This commit is contained in:
Mohamed Hegazy
2014-11-10 16:46:02 -08:00
764 changed files with 31661 additions and 26690 deletions
+1
View File
@@ -32,6 +32,7 @@ build.json
tests/webhost/*.d.ts
tests/webhost/webtsc.js
tests/*.js
tests/*.js.map
tests/*.d.ts
*.config
scripts/debug.bat
+4 -2
View File
@@ -1,12 +1,14 @@
language: node_js
node_js:
- '0.10'
- '0.10'
sudo: false
before_script: npm install -g codeclimate-test-reporter
after_script:
- cat coverage/lcov.info | codeclimate
- cat coverage/lcov.info | codeclimate
addons:
code_climate:
+13 -12
View File
@@ -82,8 +82,9 @@ var harnessSources = [
].map(function (f) {
return path.join(harnessDirectory, f);
}).concat([
"services/colorization.ts",
"services/documentRegistry.ts"
"services/colorization.ts",
"services/documentRegistry.ts",
"services/preProcessFile.ts"
].map(function (f) {
return path.join(unittestsDirectory, f);
}));
@@ -134,7 +135,7 @@ function concatenateFiles(destinationFile, sourceFiles) {
fs.renameSync(temp, destinationFile);
}
var useDebugMode = false;
var useDebugMode = true;
var generateDeclarations = false;
var host = (process.env.host || process.env.TYPESCRIPT_HOST || "node");
var compilerFilename = "tsc.js";
@@ -149,15 +150,16 @@ var compilerFilename = "tsc.js";
function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, noOutFile) {
file(outFile, prereqs, function() {
var dir = useBuiltCompiler ? builtLocalDirectory : LKGDirectory;
var options = "-removeComments --module commonjs -noImplicitAny "; //" -propagateEnumConstants "
var options = "-removeComments --module commonjs -noImplicitAny ";
if (generateDeclarations) {
options += "--declaration ";
}
if (useDebugMode) {
options += "--preserveConstEnums ";
}
var cmd = host + " " + dir + compilerFilename + " " + options + " ";
if (useDebugMode) {
cmd = cmd + " " + path.join(harnessDirectory, "external/es5compat.ts") + " " + path.join(harnessDirectory, "external/json2.ts") + " ";
}
cmd = cmd + sources.join(" ") + (!noOutFile ? " -out " + outFile : "");
if (useDebugMode) {
cmd = cmd + " -sourcemap -mapRoot file:///" + path.resolve(path.dirname(outFile));
@@ -259,12 +261,11 @@ task("local", ["generate-diagnostics", "lib", tscFile, servicesFile]);
// Local target to build the compiler and services
desc("Emit debug mode files with sourcemaps");
task("debug", function() {
useDebugMode = true;
desc("Sets release mode flag");
task("release", function() {
useDebugMode = false;
});
// Set the default task to "local"
task("default", ["local"]);
@@ -313,7 +314,7 @@ task("generate-spec", [specMd])
// Makes a new LKG. This target does not build anything, but errors if not all the outputs are present in the built/local directory
desc("Makes a new LKG out of the built js files");
task("LKG", libraryTargets, function() {
task("LKG", ["clean", "release", "local"].concat(libraryTargets), function() {
var expectedFiles = [tscFile, servicesFile].concat(libraryTargets);
var missingFiles = expectedFiles.filter(function (f) {
return !fs.existsSync(f);
+3110 -3104
View File
File diff suppressed because it is too large Load Diff
+8372 -9265
View File
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
+327 -253
View File
File diff suppressed because it is too large Load Diff
+61 -18
View File
@@ -5,25 +5,51 @@
module ts {
export function isInstantiated(node: Node): boolean {
export const enum ModuleInstanceState {
NonInstantiated = 0,
Instantiated = 1,
ConstEnumOnly = 2
}
export function getModuleInstanceState(node: Node): ModuleInstanceState {
// A module is uninstantiated if it contains only
// 1. interface declarations
if (node.kind === SyntaxKind.InterfaceDeclaration) {
return false;
return ModuleInstanceState.NonInstantiated;
}
// 2. non - exported import declarations
// 2. const enum declarations don't make module instantiated
else if (node.kind === SyntaxKind.EnumDeclaration && isConstEnumDeclaration(<EnumDeclaration>node)) {
return ModuleInstanceState.ConstEnumOnly;
}
// 3. non - exported import declarations
else if (node.kind === SyntaxKind.ImportDeclaration && !(node.flags & NodeFlags.Export)) {
return false;
return ModuleInstanceState.NonInstantiated;
}
// 3. other uninstantiated module declarations.
else if (node.kind === SyntaxKind.ModuleBlock && !forEachChild(node, isInstantiated)) {
return false;
// 4. other uninstantiated module declarations.
else if (node.kind === SyntaxKind.ModuleBlock) {
var state = ModuleInstanceState.NonInstantiated;
forEachChild(node, n => {
switch (getModuleInstanceState(n)) {
case ModuleInstanceState.NonInstantiated:
// child is non-instantiated - continue searching
return false;
case ModuleInstanceState.ConstEnumOnly:
// child is const enum only - record state and continue searching
state = ModuleInstanceState.ConstEnumOnly;
return false;
case ModuleInstanceState.Instantiated:
// child is instantiated - record state and stop
state = ModuleInstanceState.Instantiated;
return true;
}
});
return state;
}
else if (node.kind === SyntaxKind.ModuleDeclaration && !isInstantiated((<ModuleDeclaration>node).body)) {
return false;
else if (node.kind === SyntaxKind.ModuleDeclaration) {
return getModuleInstanceState((<ModuleDeclaration>node).body);
}
else {
return true;
return ModuleInstanceState.Instantiated;
}
}
@@ -58,12 +84,13 @@ module ts {
if (symbolKind & SymbolFlags.Value && !symbol.valueDeclaration) symbol.valueDeclaration = node;
}
// TODO(jfreeman): Implement getDeclarationName for property name
function getDeclarationName(node: Declaration): string {
if (node.name) {
if (node.kind === SyntaxKind.ModuleDeclaration && node.name.kind === SyntaxKind.StringLiteral) {
return '"' + node.name.text + '"';
return '"' + (<LiteralExpression>node.name).text + '"';
}
return node.name.text;
return (<Identifier>node.name).text;
}
switch (node.kind) {
case SyntaxKind.Constructor: return "__constructor";
@@ -74,7 +101,7 @@ module ts {
}
function getDisplayName(node: Declaration): string {
return node.name ? identifierToString(node.name) : getDeclarationName(node);
return node.name ? declarationNameToString(node.name) : getDeclarationName(node);
}
function declareSymbol(symbols: SymbolTable, parent: Symbol, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags): Symbol {
@@ -248,11 +275,22 @@ module ts {
if (node.name.kind === SyntaxKind.StringLiteral) {
bindDeclaration(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes, /*isBlockScopeContainer*/ true);
}
else if (isInstantiated(node)) {
bindDeclaration(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes, /*isBlockScopeContainer*/ true);
}
else {
bindDeclaration(node, SymbolFlags.NamespaceModule, SymbolFlags.NamespaceModuleExcludes, /*isBlockScopeContainer*/ true);
var state = getModuleInstanceState(node);
if (state === ModuleInstanceState.NonInstantiated) {
bindDeclaration(node, SymbolFlags.NamespaceModule, SymbolFlags.NamespaceModuleExcludes, /*isBlockScopeContainer*/ true);
}
else {
bindDeclaration(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes, /*isBlockScopeContainer*/ true);
if (state === ModuleInstanceState.ConstEnumOnly) {
// mark value module as module that contains only enums
node.symbol.constEnumOnlyModule = true;
}
else if (node.symbol.constEnumOnlyModule) {
// const only value module was merged with instantiated module - reset flag
node.symbol.constEnumOnlyModule = false;
}
}
}
}
@@ -364,7 +402,12 @@ module ts {
bindDeclaration(<Declaration>node, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes, /*isBlockScopeContainer*/ false);
break;
case SyntaxKind.EnumDeclaration:
bindDeclaration(<Declaration>node, SymbolFlags.Enum, SymbolFlags.EnumExcludes, /*isBlockScopeContainer*/ false);
if (isConstEnumDeclaration(<EnumDeclaration>node)) {
bindDeclaration(<Declaration>node, SymbolFlags.ConstEnum, SymbolFlags.ConstEnumExcludes, /*isBlockScopeContainer*/ false);
}
else {
bindDeclaration(<Declaration>node, SymbolFlags.RegularEnum, SymbolFlags.RegularEnumExcludes, /*isBlockScopeContainer*/ false);
}
break;
case SyntaxKind.ModuleDeclaration:
bindModuleDeclaration(<ModuleDeclaration>node);
+663 -374
View File
File diff suppressed because it is too large Load Diff
+7 -2
View File
@@ -24,7 +24,7 @@ module ts {
type: "boolean",
},
{
name: "emitBOM",
name: "emitBOM",
type: "boolean"
},
{
@@ -102,7 +102,7 @@ module ts {
{
name: "target",
shortName: "t",
type: { "es3": ScriptTarget.ES3, "es5": ScriptTarget.ES5 , "es6": ScriptTarget.ES6 },
type: { "es3": ScriptTarget.ES3, "es5": ScriptTarget.ES5, "es6": ScriptTarget.ES6 },
description: Diagnostics.Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES6_experimental,
paramType: Diagnostics.VERSION,
error: Diagnostics.Argument_for_target_option_must_be_es3_es5_or_es6
@@ -118,6 +118,11 @@ module ts {
shortName: "w",
type: "boolean",
description: Diagnostics.Watch_input_files,
},
{
name: "preserveConstEnums",
type: "boolean",
description: Diagnostics.Do_not_erase_const_enum_declarations_in_generated_code
}
];
+29 -8
View File
@@ -1,10 +1,30 @@
/// <reference path="types.ts"/>
module 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.
// x & y is True if both x and y are True.
// x | y is False if both x and y are False.
// x | y is Maybe if either x or y is Maybe, but neither x or y is True.
// x | y is True if either x or y is True.
export const enum Ternary {
False = 0,
Maybe = 1,
True = -1
}
export interface Map<T> {
[index: string]: T;
}
export const enum Comparison {
LessThan = -1,
EqualTo = 0,
GreaterThan = 1
}
export interface StringSet extends Map<any> { }
export function forEach<T, U>(array: T[], callback: (element: T) => U): U {
@@ -79,6 +99,7 @@ module ts {
export function concatenate<T>(array1: T[], array2: T[]): T[] {
if (!array2 || !array2.length) return array1;
if (!array1 || !array1.length) return array2;
return array1.concat(array2);
}
@@ -312,11 +333,11 @@ module ts {
};
}
export function compareValues<T>(a: T, b: T): number {
if (a === b) return 0;
if (a === undefined) return -1;
if (b === undefined) return 1;
return a < b ? -1 : 1;
export function compareValues<T>(a: T, b: T): Comparison {
if (a === b) return Comparison.EqualTo;
if (a === undefined) return Comparison.LessThan;
if (b === undefined) return Comparison.GreaterThan;
return a < b ? Comparison.LessThan : Comparison.GreaterThan;
}
function getDiagnosticFilename(diagnostic: Diagnostic): string {
@@ -341,7 +362,7 @@ module ts {
var previousDiagnostic = diagnostics[0];
for (var i = 1; i < diagnostics.length; i++) {
var currentDiagnostic = diagnostics[i];
var isDupe = compareDiagnostics(currentDiagnostic, previousDiagnostic) === 0;
var isDupe = compareDiagnostics(currentDiagnostic, previousDiagnostic) === Comparison.EqualTo;
if (!isDupe) {
newDiagnostics.push(currentDiagnostic);
previousDiagnostic = currentDiagnostic;
@@ -616,7 +637,7 @@ module ts {
getSignatureConstructor: () => <any>Signature
}
export enum AssertionLevel {
export const enum AssertionLevel {
None = 0,
Normal = 1,
Aggressive = 2,
@@ -630,7 +651,7 @@ module ts {
return currentAssertionLevel >= level;
}
export function assert(expression: any, message?: string, verboseDebugInfo?: () => string): void {
export function assert(expression: boolean, message?: string, verboseDebugInfo?: () => string): void {
if (!expression) {
var verboseDebugString = "";
if (verboseDebugInfo) {
@@ -120,7 +120,8 @@ module ts {
const_declarations_must_be_initialized: { code: 1155, category: DiagnosticCategory.Error, key: "'const' declarations must be initialized" },
const_declarations_can_only_be_declared_inside_a_block: { code: 1156, category: DiagnosticCategory.Error, key: "'const' declarations can only be declared inside a block." },
let_declarations_can_only_be_declared_inside_a_block: { code: 1157, category: DiagnosticCategory.Error, key: "'let' declarations can only be declared inside a block." },
Aliased_type_cannot_be_an_object_type_literal_Use_an_interface_declaration_instead: { code: 1158, category: DiagnosticCategory.Error, key: "Aliased type cannot be an object type literal. Use an interface declaration instead." },
Invalid_template_literal_expected: { code: 1158, category: DiagnosticCategory.Error, key: "Invalid template literal; expected '}'" },
Tagged_templates_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1159, category: DiagnosticCategory.Error, key: "Tagged templates are only available when targeting ECMAScript 6 and higher." },
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." },
@@ -143,7 +144,7 @@ module ts {
Named_properties_0_of_types_1_and_2_are_not_identical: { code: 2319, category: DiagnosticCategory.Error, key: "Named properties '{0}' of types '{1}' and '{2}' are not identical." },
Interface_0_cannot_simultaneously_extend_types_1_and_2: { code: 2320, category: DiagnosticCategory.Error, key: "Interface '{0}' cannot simultaneously extend types '{1}' and '{2}'." },
Excessive_stack_depth_comparing_types_0_and_1: { code: 2321, category: DiagnosticCategory.Error, key: "Excessive stack depth comparing types '{0}' and '{1}'." },
Type_0_is_not_assignable_to_type_1: { code: 2323, category: DiagnosticCategory.Error, key: "Type '{0}' is not assignable to type '{1}'." },
Type_0_is_not_assignable_to_type_1: { code: 2322, category: DiagnosticCategory.Error, key: "Type '{0}' is not assignable to type '{1}'." },
Property_0_is_missing_in_type_1: { code: 2324, category: DiagnosticCategory.Error, key: "Property '{0}' is missing in type '{1}'." },
Property_0_is_private_in_type_1_but_not_in_type_2: { code: 2325, category: DiagnosticCategory.Error, key: "Property '{0}' is private in type '{1}' but not in type '{2}'." },
Types_of_property_0_are_incompatible: { code: 2326, category: DiagnosticCategory.Error, key: "Types of property '{0}' are incompatible." },
@@ -268,6 +269,7 @@ module ts {
The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly: { code: 2453, category: DiagnosticCategory.Error, key: "The type argument for type parameter '{0}' cannot be inferred from the usage. Consider specifying the type arguments explicitly." },
Type_argument_candidate_1_is_not_a_valid_type_argument_because_it_is_not_a_supertype_of_candidate_0: { code: 2455, category: DiagnosticCategory.Error, key: "Type argument candidate '{1}' is not a valid type argument because it is not a supertype of candidate '{0}'." },
Type_alias_0_circularly_references_itself: { code: 2456, category: DiagnosticCategory.Error, key: "Type alias '{0}' circularly references itself." },
Type_alias_name_cannot_be_0: { code: 2457, category: DiagnosticCategory.Error, key: "Type alias name cannot be '{0}'" },
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_name_1_from_private_module_2: { code: 4001, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using name '{1}' from private module '{2}'." },
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}'." },
@@ -350,6 +352,12 @@ module ts {
Exported_type_alias_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4079, category: DiagnosticCategory.Error, key: "Exported type alias '{0}' has or is using name '{1}' from external module {2} but cannot be named." },
Exported_type_alias_0_has_or_is_using_name_1_from_private_module_2: { code: 4080, category: DiagnosticCategory.Error, key: "Exported type alias '{0}' has or is using name '{1}' from private module '{2}'." },
Exported_type_alias_0_has_or_is_using_private_name_1: { code: 4081, category: DiagnosticCategory.Error, key: "Exported type alias '{0}' has or is using private name '{1}'." },
Enum_declarations_must_all_be_const_or_non_const: { code: 4082, category: DiagnosticCategory.Error, key: "Enum declarations must all be const or non-const." },
In_const_enum_declarations_member_initializer_must_be_constant_expression: { code: 4083, category: DiagnosticCategory.Error, key: "In 'const' enum declarations member initializer must be constant expression.", isEarly: true },
const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment: { code: 4084, category: DiagnosticCategory.Error, key: "'const' enums can only be used in property or index access expressions or the right hand side of an import declaration or export assignment." },
Index_expression_arguments_in_const_enums_must_be_of_type_string: { code: 4085, category: DiagnosticCategory.Error, key: "Index expression arguments in 'const' enums must be of type 'string'." },
const_enum_member_initializer_was_evaluated_to_a_non_finite_value: { code: 4086, category: DiagnosticCategory.Error, key: "'const' enum member initializer was evaluated to a non-finite value." },
const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN: { code: 4087, category: DiagnosticCategory.Error, key: "'const' enum member initializer was evaluated to disallowed value 'NaN'." },
The_current_host_does_not_support_the_0_option: { code: 5001, category: DiagnosticCategory.Error, key: "The current host does not support the '{0}' option." },
Cannot_find_the_common_subdirectory_path_for_the_input_files: { code: 5009, category: DiagnosticCategory.Error, key: "Cannot find the common subdirectory path for the input files." },
Cannot_read_file_0_Colon_1: { code: 5012, category: DiagnosticCategory.Error, key: "Cannot read file '{0}': {1}" },
@@ -364,6 +372,7 @@ module ts {
Specifies_the_location_where_debugger_should_locate_TypeScript_files_instead_of_source_locations: { code: 6004, category: DiagnosticCategory.Message, key: "Specifies the location where debugger should locate TypeScript files instead of source locations." },
Watch_input_files: { code: 6005, category: DiagnosticCategory.Message, key: "Watch input files." },
Redirect_output_structure_to_the_directory: { code: 6006, category: DiagnosticCategory.Message, key: "Redirect output structure to the directory." },
Do_not_erase_const_enum_declarations_in_generated_code: { code: 6007, category: DiagnosticCategory.Message, key: "Do not erase const enum declarations in generated code." },
Do_not_emit_comments_to_output: { code: 6009, category: DiagnosticCategory.Message, key: "Do not emit comments to output." },
Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES6_experimental: { code: 6015, category: DiagnosticCategory.Message, key: "Specify ECMAScript target version: 'ES3' (default), 'ES5', or 'ES6' (experimental)" },
Specify_module_code_generation_Colon_commonjs_or_amd: { code: 6016, category: DiagnosticCategory.Message, key: "Specify module code generation: 'commonjs' or 'amd'" },
+38 -8
View File
@@ -471,10 +471,14 @@
"category": "Error",
"code": 1157
},
"Aliased type cannot be an object type literal. Use an interface declaration instead.": {
"Invalid template literal; expected '}'": {
"category": "Error",
"code": 1158
},
"Tagged templates are only available when targeting ECMAScript 6 and higher.": {
"category": "Error",
"code": 1159
},
"Duplicate identifier '{0}'.": {
"category": "Error",
@@ -568,10 +572,6 @@
"category": "Error",
"code": 2322
},
"Type '{0}' is not assignable to type '{1}'.": {
"category": "Error",
"code": 2323
},
"Property '{0}' is missing in type '{1}'.": {
"category": "Error",
"code": 2324
@@ -1072,6 +1072,10 @@
"category": "Error",
"code": 2456
},
"Type alias name cannot be '{0}'": {
"category": "Error",
"code": 2457
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
@@ -1401,13 +1405,35 @@
"category": "Error",
"code": 4081
},
"Enum declarations must all be const or non-const.": {
"category": "Error",
"code": 4082
},
"In 'const' enum declarations member initializer must be constant expression.": {
"category": "Error",
"code": 4083,
"isEarly": true
},
"'const' enums can only be used in property or index access expressions or the right hand side of an import declaration or export assignment.": {
"category": "Error",
"code": 4084
},
"Index expression arguments in 'const' enums must be of type 'string'.": {
"category": "Error",
"code": 4085
},
"'const' enum member initializer was evaluated to a non-finite value.": {
"category": "Error",
"code": 4086
},
"'const' enum member initializer was evaluated to disallowed value 'NaN'.": {
"category": "Error",
"code": 4087
},
"The current host does not support the '{0}' option.": {
"category": "Error",
"code": 5001
},
"Cannot find the common subdirectory path for the input files.": {
"category": "Error",
"code": 5009
@@ -1460,6 +1486,10 @@
"category": "Message",
"code": 6006
},
"Do not erase const enum declarations in generated code.": {
"category": "Message",
"code": 6007
},
"Do not emit comments to output.": {
"category": "Message",
"code": 6009
+204 -40
View File
@@ -86,8 +86,9 @@ module ts {
var getAccessor: AccessorDeclaration;
var setAccessor: AccessorDeclaration;
forEach(node.members, (member: Declaration) => {
// TODO(jfreeman): Handle computed names for accessor matching
if ((member.kind === SyntaxKind.GetAccessor || member.kind === SyntaxKind.SetAccessor) &&
member.name.text === accessor.name.text &&
(<Identifier>member.name).text === (<Identifier>accessor.name).text &&
(member.flags & NodeFlags.Static) === (accessor.flags & NodeFlags.Static)) {
if (!firstAccessor) {
firstAccessor = <AccessorDeclaration>member;
@@ -577,7 +578,8 @@ module ts {
node.kind === SyntaxKind.EnumDeclaration) {
// Declaration and has associated name use it
if ((<Declaration>node).name) {
scopeName = (<Declaration>node).name.text;
// TODO(jfreeman): Ask shkamat about what this name should be for source maps
scopeName = (<Identifier>(<Declaration>node).name).text;
}
recordScopeNameStart(scopeName);
}
@@ -786,27 +788,136 @@ module ts {
}
}
function emitLiteral(node: LiteralExpression) {
var text = getSourceTextOfLocalNode(node);
if (node.kind === SyntaxKind.StringLiteral && compilerOptions.sourceMap) {
function emitLiteral(node: LiteralExpression): void {
var text = getLiteralText();
if (compilerOptions.sourceMap && (node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind))) {
writer.writeLiteral(text);
}
else {
write(text);
}
function getLiteralText() {
if (compilerOptions.target < ScriptTarget.ES6 && isTemplateLiteralKind(node.kind)) {
return getTemplateLiteralAsStringLiteral(node)
}
return getSourceTextOfLocalNode(node);
}
}
function getTemplateLiteralAsStringLiteral(node: LiteralExpression): string {
return '"' + escapeString(node.text) + '"';
}
function emitTemplateExpression(node: TemplateExpression): void {
// In ES6 mode and above, we can simply emit each portion of a template in order, but in
// ES3 & ES5 we must convert the template expression into a series of string concatenations.
if (compilerOptions.target >= ScriptTarget.ES6) {
forEachChild(node, emit);
return;
}
Debug.assert(node.parent.kind !== SyntaxKind.TaggedTemplateExpression);
var templateNeedsParens = isExpression(node.parent)
&& node.parent.kind !== SyntaxKind.ParenExpression
&& comparePrecedenceToBinaryPlus(node.parent) !== Comparison.LessThan;
if (templateNeedsParens) {
write("(");
}
emitLiteral(node.head);
forEach(node.templateSpans, templateSpan => {
// Check if the expression has operands and binds its operands less closely than binary '+'.
// If it does, we need to wrap the expression in parentheses. Otherwise, something like
// `abc${ 1 << 2}`
// becomes
// "abc" + 1 << 2 + ""
// which is really
// ("abc" + 1) << (2 + "")
// rather than
// "abc" + (1 << 2) + ""
var needsParens = templateSpan.expression.kind !== SyntaxKind.ParenExpression
&& comparePrecedenceToBinaryPlus(templateSpan.expression) !== Comparison.GreaterThan;
write(" + ");
if (needsParens) {
write("(");
}
emit(templateSpan.expression);
if (needsParens) {
write(")");
}
// Only emit if the literal is non-empty.
// The binary '+' operator is left-associative, so the first string concatenation will force
// the result up to this point to be a string. Emitting a '+ ""' has no semantic effect.
if (templateSpan.literal.text.length !== 0) {
write(" + ")
emitLiteral(templateSpan.literal);
}
});
if (templateNeedsParens) {
write(")");
}
/**
* Returns whether the expression has lesser, greater,
* or equal precedence to the binary '+' operator
*/
function comparePrecedenceToBinaryPlus(expression: Expression): Comparison {
// All binary expressions have lower precedence than '+' apart from '*', '/', and '%'.
// All unary operators have a higher precedence apart from yield.
// Arrow functions and conditionals have a lower precedence,
// although we convert the former into regular function expressions in ES5 mode,
// and in ES6 mode this function won't get called anyway.
//
// TODO (drosen): Note that we need to account for the upcoming 'yield' and
// spread ('...') unary operators that are anticipated for ES6.
Debug.assert(compilerOptions.target <= ScriptTarget.ES5);
switch (expression.kind) {
case SyntaxKind.BinaryExpression:
switch ((<BinaryExpression>expression).operator) {
case SyntaxKind.AsteriskToken:
case SyntaxKind.SlashToken:
case SyntaxKind.PercentToken:
return Comparison.GreaterThan;
case SyntaxKind.PlusToken:
return Comparison.EqualTo;
default:
return Comparison.LessThan;
}
case SyntaxKind.ConditionalExpression:
return Comparison.LessThan;
default:
return Comparison.GreaterThan;
}
}
}
function emitTemplateSpan(span: TemplateSpan) {
emit(span.expression);
emit(span.literal);
}
// This function specifically handles numeric/string literals for enum and accessor 'identifiers'.
// In a sense, it does not actually emit identifiers as much as it declares a name for a specific property.
function emitQuotedIdentifier(node: Identifier) {
function emitExpressionForPropertyName(node: DeclarationName) {
if (node.kind === SyntaxKind.StringLiteral) {
emitLiteral(node);
emitLiteral(<LiteralExpression>node);
}
else {
write("\"");
if (node.kind === SyntaxKind.NumericLiteral) {
write(node.text);
write((<LiteralExpression>node).text);
}
else {
write(getSourceTextOfLocalNode(node));
@@ -922,19 +1033,29 @@ module ts {
emitTrailingComments(node);
}
function emitPropertyAccess(node: PropertyAccess) {
function tryEmitConstantValue(node: PropertyAccess | IndexedAccess): boolean {
var constantValue = resolver.getConstantValue(node);
if (constantValue !== undefined) {
write(constantValue.toString() + " /* " + identifierToString(node.right) + " */");
var propertyName = node.kind === SyntaxKind.PropertyAccess ? declarationNameToString((<PropertyAccess>node).right) : getTextOfNode((<IndexedAccess>node).index);
write(constantValue.toString() + " /* " + propertyName + " */");
return true;
}
else {
emit(node.left);
write(".");
emit(node.right);
return false;
}
function emitPropertyAccess(node: PropertyAccess) {
if (tryEmitConstantValue(node)) {
return;
}
emit(node.left);
write(".");
emit(node.right);
}
function emitIndexedAccess(node: IndexedAccess) {
if (tryEmitConstantValue(node)) {
return;
}
emit(node.object);
write("[");
emit(node.index);
@@ -977,6 +1098,13 @@ module ts {
}
}
function emitTaggedTemplateExpression(node: TaggedTemplateExpression): void {
Debug.assert(compilerOptions.target >= ScriptTarget.ES6, "Trying to emit a tagged template in pre-ES6 mode.");
emit(node.tag);
write(" ");
emit(node.template);
}
function emitParenExpression(node: ParenExpression) {
if (node.expression.kind === SyntaxKind.TypeAssertion) {
var operand = (<TypeAssertion>node.expression).operand;
@@ -1225,6 +1353,10 @@ module ts {
emitToken(SyntaxKind.CloseBraceToken, node.clauses.end);
}
function isOnSameLine(node1: Node, node2: Node) {
return getLineOfLocalPosition(skipTrivia(currentSourceFile.text, node1.pos)) === getLineOfLocalPosition(skipTrivia(currentSourceFile.text, node2.pos));
}
function emitCaseOrDefaultClause(node: CaseOrDefaultClause) {
if (node.kind === SyntaxKind.CaseClause) {
write("case ");
@@ -1234,9 +1366,16 @@ module ts {
else {
write("default:");
}
increaseIndent();
emitLines(node.statements);
decreaseIndent();
if (node.statements.length === 1 && isOnSameLine(node, node.statements[0])) {
write(" ");
emit(node.statements[0]);
}
else {
increaseIndent();
emitLines(node.statements);
decreaseIndent();
}
}
function emitThrowStatement(node: ThrowStatement) {
@@ -1327,7 +1466,7 @@ module ts {
emitTrailingComments(node);
}
function emitDefaultValueAssignments(node: FunctionDeclaration) {
function emitDefaultValueAssignments(node: FunctionLikeDeclaration) {
forEach(node.parameters, param => {
if (param.initializer) {
writeLine();
@@ -1347,7 +1486,7 @@ module ts {
});
}
function emitRestParameter(node: FunctionDeclaration) {
function emitRestParameter(node: FunctionLikeDeclaration) {
if (hasRestParameters(node)) {
var restIndex = node.parameters.length - 1;
var restParam = node.parameters[restIndex];
@@ -1393,7 +1532,7 @@ module ts {
emitTrailingComments(node);
}
function emitFunctionDeclaration(node: FunctionDeclaration) {
function emitFunctionDeclaration(node: FunctionLikeDeclaration) {
if (!node.body) {
return emitPinnedOrTripleSlashComments(node);
}
@@ -1421,7 +1560,7 @@ module ts {
}
}
function emitSignatureParameters(node: FunctionDeclaration) {
function emitSignatureParameters(node: FunctionLikeDeclaration) {
increaseIndent();
write("(");
if (node) {
@@ -1431,7 +1570,7 @@ module ts {
decreaseIndent();
}
function emitSignatureAndBody(node: FunctionDeclaration) {
function emitSignatureAndBody(node: FunctionLikeDeclaration) {
emitSignatureParameters(node);
write(" {");
scopeEmitStart(node);
@@ -1528,7 +1667,8 @@ module ts {
});
}
function emitMemberAccess(memberName: Identifier) {
// TODO(jfreeman): Account for computed property name
function emitMemberAccess(memberName: DeclarationName) {
if (memberName.kind === SyntaxKind.StringLiteral || memberName.kind === SyntaxKind.NumericLiteral) {
write("[");
emitNode(memberName);
@@ -1601,7 +1741,7 @@ module ts {
write(".prototype");
}
write(", ");
emitQuotedIdentifier((<AccessorDeclaration>member).name);
emitExpressionForPropertyName((<AccessorDeclaration>member).name);
emitEnd((<AccessorDeclaration>member).name);
write(", {");
increaseIndent();
@@ -1760,6 +1900,11 @@ module ts {
}
function emitEnumDeclaration(node: EnumDeclaration) {
// const enums are completely erased during compilation.
var isConstEnum = isConstEnumDeclaration(node);
if (isConstEnum && !compilerOptions.preserveConstEnums) {
return;
}
emitLeadingComments(node);
if (!(node.flags & NodeFlags.Export)) {
emitStart(node);
@@ -1777,7 +1922,7 @@ module ts {
write(") {");
increaseIndent();
scopeEmitStart(node);
emitEnumMemberDeclarations();
emitEnumMemberDeclarations(isConstEnum);
decreaseIndent();
writeLine();
emitToken(SyntaxKind.CloseBraceToken, node.members.end);
@@ -1800,7 +1945,7 @@ module ts {
}
emitTrailingComments(node);
function emitEnumMemberDeclarations() {
function emitEnumMemberDeclarations(isConstEnum: boolean) {
forEach(node.members, member => {
writeLine();
emitLeadingComments(member);
@@ -1809,16 +1954,16 @@ module ts {
write("[");
write(resolver.getLocalNameOfContainer(node));
write("[");
emitQuotedIdentifier(member.name);
emitExpressionForPropertyName(member.name);
write("] = ");
if (member.initializer) {
if (member.initializer && !isConstEnum) {
emit(member.initializer);
}
else {
write(resolver.getEnumMemberValue(member).toString());
}
write("] = ");
emitQuotedIdentifier(member.name);
emitExpressionForPropertyName(member.name);
emitEnd(member);
write(";");
emitTrailingComments(member);
@@ -1834,7 +1979,7 @@ module ts {
}
function emitModuleDeclaration(node: ModuleDeclaration) {
if (!isInstantiated(node)) {
if (getModuleInstanceState(node) !== ModuleInstanceState.Instantiated) {
return emitPinnedOrTripleSlashComments(node);
}
emitLeadingComments(node);
@@ -1886,7 +2031,7 @@ module ts {
// preserve old compiler's behavior: emit 'var' for import declaration (even if we do not consider them referenced) when
// - current file is not external module
// - import declaration is top level and target is value imported by entity name
emitImportDeclaration = !isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportedViaEntityName(node);
emitImportDeclaration = !isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportWithEntityName(node);
}
if (emitImportDeclaration) {
@@ -1930,7 +2075,10 @@ module ts {
function getExternalImportDeclarations(node: SourceFile): ImportDeclaration[] {
var result: ImportDeclaration[] = [];
forEach(node.statements, stat => {
if (stat.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>stat).externalModuleName && resolver.isReferencedImportDeclaration(stat)) {
if (stat.kind === SyntaxKind.ImportDeclaration
&& (<ImportDeclaration>stat).externalModuleName
&& resolver.isReferencedImportDeclaration(<ImportDeclaration>stat)) {
result.push(<ImportDeclaration>stat);
}
});
@@ -2085,7 +2233,15 @@ module ts {
case SyntaxKind.NumericLiteral:
case SyntaxKind.StringLiteral:
case SyntaxKind.RegularExpressionLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.TemplateHead:
case SyntaxKind.TemplateMiddle:
case SyntaxKind.TemplateTail:
return emitLiteral(<LiteralExpression>node);
case SyntaxKind.TemplateExpression:
return emitTemplateExpression(<TemplateExpression>node);
case SyntaxKind.TemplateSpan:
return emitTemplateSpan(<TemplateSpan>node);
case SyntaxKind.QualifiedName:
return emitPropertyAccess(<QualifiedName>node);
case SyntaxKind.ArrayLiteral:
@@ -2102,6 +2258,8 @@ module ts {
return emitCallExpression(<CallExpression>node);
case SyntaxKind.NewExpression:
return emitNewExpression(<NewExpression>node);
case SyntaxKind.TaggedTemplateExpression:
return emitTaggedTemplateExpression(<TaggedTemplateExpression>node);
case SyntaxKind.TypeAssertion:
return emit((<TypeAssertion>node).operand);
case SyntaxKind.ParenExpression:
@@ -2109,7 +2267,7 @@ module ts {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
return emitFunctionDeclaration(<FunctionDeclaration>node);
return emitFunctionDeclaration(<FunctionLikeDeclaration>node);
case SyntaxKind.PrefixOperator:
case SyntaxKind.PostfixOperator:
return emitUnaryExpression(<UnaryExpression>node);
@@ -2352,7 +2510,7 @@ module ts {
var getSymbolVisibilityDiagnosticMessage: (symbolAccesibilityResult: SymbolAccessiblityResult) => {
errorNode: Node;
diagnosticMessage: DiagnosticMessage;
typeName?: Identifier
typeName?: DeclarationName
}
function createTextWriterWithSymbolWriter(): EmitTextWriterWithSymbolWriter {
@@ -2596,6 +2754,9 @@ module ts {
if (resolver.isDeclarationVisible(node)) {
emitJsDocComments(node);
emitDeclarationFlags(node);
if (isConstEnumDeclaration(node)) {
write("const ")
}
write("enum ");
emitSourceTextOfNode(node.name);
write(" {");
@@ -2675,7 +2836,7 @@ module ts {
break;
default:
Debug.fail("This is unknown parent for type parameter: " + SyntaxKind[node.parent.kind]);
Debug.fail("This is unknown parent for type parameter: " + node.parent.kind);
}
return {
@@ -2811,11 +2972,12 @@ module ts {
function emitPropertyDeclaration(node: PropertyDeclaration) {
emitJsDocComments(node);
emitDeclarationFlags(node);
emitVariableDeclaration(node);
emitVariableDeclaration(<VariableDeclaration>node);
write(";");
writeLine();
}
// TODO(jfreeman): Factor out common part of property definition, but treat name differently
function emitVariableDeclaration(node: VariableDeclaration) {
// If we are emitting property it isn't moduleElement and hence we already know it needs to be emitted
// so there is no check needed to see if declaration is visible
@@ -2843,6 +3005,7 @@ module ts {
}
// This check is to ensure we don't report error on constructor parameter property as that error would be reported during parameter emit
else if (node.kind === SyntaxKind.Property) {
// TODO(jfreeman): Deal with computed properties in error reporting.
if (node.flags & NodeFlags.Static) {
diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
@@ -2926,6 +3089,7 @@ module ts {
return {
diagnosticMessage: diagnosticMessage,
errorNode: <Node>node.parameters[0],
// TODO(jfreeman): Investigate why we are passing node.name instead of node.parameters[0].name
typeName: node.name
};
}
@@ -2953,7 +3117,7 @@ module ts {
}
}
function emitFunctionDeclaration(node: FunctionDeclaration) {
function emitFunctionDeclaration(node: FunctionLikeDeclaration) {
// If we are emitting Method/Constructor it isn't moduleElement and hence already determined to be emitting
// so no need to verify if the declaration is visible
if ((node.kind !== SyntaxKind.FunctionDeclaration || resolver.isDeclarationVisible(node)) &&
@@ -3071,7 +3235,7 @@ module ts {
break;
default:
Debug.fail("This is unknown kind for signature: " + SyntaxKind[node.kind]);
Debug.fail("This is unknown kind for signature: " + node.kind);
}
return {
@@ -3156,7 +3320,7 @@ module ts {
break;
default:
Debug.fail("This is unknown parent for parameter: " + SyntaxKind[node.parent.kind]);
Debug.fail("This is unknown parent for parameter: " + node.parent.kind);
}
return {
@@ -3172,7 +3336,7 @@ module ts {
case SyntaxKind.Constructor:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.Method:
return emitFunctionDeclaration(<FunctionDeclaration>node);
return emitFunctionDeclaration(<FunctionLikeDeclaration>node);
case SyntaxKind.ConstructSignature:
return emitConstructSignatureDeclaration(<SignatureDeclaration>node);
case SyntaxKind.CallSignature:
+325 -173
View File
@@ -62,80 +62,10 @@ module ts {
return identifier.length >= 3 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ && identifier.charCodeAt(2) === CharacterCodes._ ? identifier.substr(1) : identifier;
}
// TODO(jfreeman): Implement declarationNameToString for computed properties
// Return display name of an identifier
export function identifierToString(identifier: Identifier) {
return identifier.kind === SyntaxKind.Missing ? "(Missing)" : getTextOfNode(identifier);
}
export function isExpression(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.ThisKeyword:
case SyntaxKind.SuperKeyword:
case SyntaxKind.NullKeyword:
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
case SyntaxKind.RegularExpressionLiteral:
case SyntaxKind.ArrayLiteral:
case SyntaxKind.ObjectLiteral:
case SyntaxKind.PropertyAccess:
case SyntaxKind.IndexedAccess:
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.TypeAssertion:
case SyntaxKind.ParenExpression:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.PrefixOperator:
case SyntaxKind.PostfixOperator:
case SyntaxKind.BinaryExpression:
case SyntaxKind.ConditionalExpression:
case SyntaxKind.OmittedExpression:
return true;
case SyntaxKind.QualifiedName:
while (node.parent.kind === SyntaxKind.QualifiedName) node = node.parent;
return node.parent.kind === SyntaxKind.TypeQuery;
case SyntaxKind.Identifier:
if (node.parent.kind === SyntaxKind.TypeQuery) {
return true;
}
// Fall through
case SyntaxKind.NumericLiteral:
case SyntaxKind.StringLiteral:
var parent = node.parent;
switch (parent.kind) {
case SyntaxKind.VariableDeclaration:
case SyntaxKind.Parameter:
case SyntaxKind.Property:
case SyntaxKind.EnumMember:
case SyntaxKind.PropertyAssignment:
return (<VariableDeclaration>parent).initializer === node;
case SyntaxKind.ExpressionStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.ReturnStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.CaseClause:
case SyntaxKind.ThrowStatement:
case SyntaxKind.SwitchStatement:
return (<ExpressionStatement>parent).expression === node;
case SyntaxKind.ForStatement:
return (<ForStatement>parent).initializer === node ||
(<ForStatement>parent).condition === node ||
(<ForStatement>parent).iterator === node;
case SyntaxKind.ForInStatement:
return (<ForInStatement>parent).variable === node ||
(<ForInStatement>parent).expression === node;
case SyntaxKind.TypeAssertion:
return node === (<TypeAssertion>parent).operand;
default:
if (isExpression(parent)) {
return true;
}
}
}
return false;
export function declarationNameToString(name: DeclarationName) {
return name.kind === SyntaxKind.Missing ? "(Missing)" : getTextOfNode(name);
}
export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): Diagnostic {
@@ -186,6 +116,10 @@ module ts {
return (file.flags & NodeFlags.DeclarationFile) !== 0;
}
export function isConstEnumDeclaration(node: EnumDeclaration): boolean {
return (node.flags & NodeFlags.Const) !== 0;
}
export function isPrologueDirective(node: Node): boolean {
return node.kind === SyntaxKind.ExpressionStatement && (<ExpressionStatement>node).expression.kind === SyntaxKind.StringLiteral;
}
@@ -280,11 +214,11 @@ module ts {
case SyntaxKind.FunctionExpression:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.ArrowFunction:
return child((<FunctionDeclaration>node).name) ||
children((<FunctionDeclaration>node).typeParameters) ||
children((<FunctionDeclaration>node).parameters) ||
child((<FunctionDeclaration>node).type) ||
child((<FunctionDeclaration>node).body);
return child((<FunctionLikeDeclaration>node).name) ||
children((<FunctionLikeDeclaration>node).typeParameters) ||
children((<FunctionLikeDeclaration>node).parameters) ||
child((<FunctionLikeDeclaration>node).type) ||
child((<FunctionLikeDeclaration>node).body);
case SyntaxKind.TypeReference:
return child((<TypeReferenceNode>node).typeName) ||
children((<TypeReferenceNode>node).typeArguments);
@@ -315,6 +249,9 @@ module ts {
return child((<CallExpression>node).func) ||
children((<CallExpression>node).typeArguments) ||
children((<CallExpression>node).arguments);
case SyntaxKind.TaggedTemplateExpression:
return child((<TaggedTemplateExpression>node).tag) ||
child((<TaggedTemplateExpression>node).template);
case SyntaxKind.TypeAssertion:
return child((<TypeAssertion>node).type) ||
child((<TypeAssertion>node).operand);
@@ -422,6 +359,10 @@ module ts {
child((<ImportDeclaration>node).externalModuleName);
case SyntaxKind.ExportAssignment:
return child((<ExportAssignment>node).exportName);
case SyntaxKind.TemplateExpression:
return child((<TemplateExpression>node).head) || children((<TemplateExpression>node).templateSpans);
case SyntaxKind.TemplateSpan:
return child((<TemplateSpan>node).expression) || child((<TemplateSpan>node).literal);
}
}
@@ -526,10 +467,98 @@ module ts {
}
}
export function isExpression(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.ThisKeyword:
case SyntaxKind.SuperKeyword:
case SyntaxKind.NullKeyword:
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
case SyntaxKind.RegularExpressionLiteral:
case SyntaxKind.ArrayLiteral:
case SyntaxKind.ObjectLiteral:
case SyntaxKind.PropertyAccess:
case SyntaxKind.IndexedAccess:
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.TypeAssertion:
case SyntaxKind.ParenExpression:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.PrefixOperator:
case SyntaxKind.PostfixOperator:
case SyntaxKind.BinaryExpression:
case SyntaxKind.ConditionalExpression:
case SyntaxKind.TemplateExpression:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.OmittedExpression:
return true;
case SyntaxKind.QualifiedName:
while (node.parent.kind === SyntaxKind.QualifiedName) node = node.parent;
return node.parent.kind === SyntaxKind.TypeQuery;
case SyntaxKind.Identifier:
if (node.parent.kind === SyntaxKind.TypeQuery) {
return true;
}
// fall through
case SyntaxKind.NumericLiteral:
case SyntaxKind.StringLiteral:
var parent = node.parent;
switch (parent.kind) {
case SyntaxKind.VariableDeclaration:
case SyntaxKind.Parameter:
case SyntaxKind.Property:
case SyntaxKind.EnumMember:
case SyntaxKind.PropertyAssignment:
return (<VariableDeclaration>parent).initializer === node;
case SyntaxKind.ExpressionStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.ReturnStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.CaseClause:
case SyntaxKind.ThrowStatement:
case SyntaxKind.SwitchStatement:
return (<ExpressionStatement>parent).expression === node;
case SyntaxKind.ForStatement:
return (<ForStatement>parent).initializer === node ||
(<ForStatement>parent).condition === node ||
(<ForStatement>parent).iterator === node;
case SyntaxKind.ForInStatement:
return (<ForInStatement>parent).variable === node ||
(<ForInStatement>parent).expression === node;
case SyntaxKind.TypeAssertion:
return node === (<TypeAssertion>parent).operand;
case SyntaxKind.TemplateSpan:
return node === (<TemplateSpan>parent).expression;
default:
if (isExpression(parent)) {
return true;
}
}
}
return false;
}
export function hasRestParameters(s: SignatureDeclaration): boolean {
return s.parameters.length > 0 && (s.parameters[s.parameters.length - 1].flags & NodeFlags.Rest) !== 0;
}
export function isLiteralKind(kind: SyntaxKind): boolean {
return SyntaxKind.FirstLiteralToken <= kind && kind <= SyntaxKind.LastLiteralToken;
}
export function isTextualLiteralKind(kind: SyntaxKind): boolean {
return kind === SyntaxKind.StringLiteral || kind === SyntaxKind.NoSubstitutionTemplateLiteral;
}
export function isTemplateLiteralKind(kind: SyntaxKind): boolean {
return SyntaxKind.FirstTemplateToken <= kind && kind <= SyntaxKind.LastTemplateToken;
}
export function isInAmbientContext(node: Node): boolean {
while (node) {
if (node.flags & (NodeFlags.Ambient | NodeFlags.DeclarationFile)) return true;
@@ -538,6 +567,7 @@ module ts {
return false;
}
export function isDeclaration(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.TypeParameter:
@@ -639,7 +669,7 @@ module ts {
return undefined;
}
enum ParsingContext {
const enum ParsingContext {
SourceElements, // Elements in source file
ModuleElements, // Elements in module declaration
BlockStatements, // Statements in block
@@ -660,7 +690,7 @@ module ts {
Count // Number of parsing contexts
}
enum Tristate {
const enum Tristate {
False,
True,
Unknown
@@ -688,13 +718,13 @@ module ts {
}
};
enum LookAheadMode {
const enum LookAheadMode {
NotLookingAhead,
NoErrorYet,
Error
}
enum ModifierContext {
const enum ModifierContext {
SourceElements, // Top level elements in a source file
ModuleElements, // Elements in module declaration
ClassMembers, // Members in class declaration
@@ -703,7 +733,7 @@ module ts {
// Tracks whether we nested (directly or indirectly) in a certain control block.
// Used for validating break and continue statements.
enum ControlBlockContext {
const enum ControlBlockContext {
NotNested,
Nested,
CrossingFunctionBoundary
@@ -717,6 +747,47 @@ module ts {
nodeIsNestedInLabel(label: Identifier, requireIterationStatement: boolean, stopAtFunctionBoundary: boolean): ControlBlockContext;
}
interface ReferencePathMatchResult {
fileReference?: FileReference
diagnostic?: DiagnosticMessage
isNoDefaultLib?: boolean
}
export function getFileReferenceFromReferencePath(comment: string, commentRange: CommentRange): ReferencePathMatchResult {
var simpleReferenceRegEx = /^\/\/\/\s*<reference\s+/gim;
var isNoDefaultLibRegEx = /^(\/\/\/\s*<reference\s+no-default-lib\s*=\s*)('|")(.+?)\2\s*\/>/gim;
if (simpleReferenceRegEx.exec(comment)) {
if (isNoDefaultLibRegEx.exec(comment)) {
return {
isNoDefaultLib: true
}
}
else {
var matchResult = fullTripleSlashReferencePathRegEx.exec(comment);
if (matchResult) {
var start = commentRange.pos;
var end = commentRange.end;
var fileRef = {
pos: start,
end: end,
filename: matchResult[3]
};
return {
fileReference: fileRef,
isNoDefaultLib: false
};
}
else {
return {
diagnostic: Diagnostics.Invalid_reference_directive_syntax,
isNoDefaultLib: false
};
}
}
}
return undefined;
}
export function isKeyword(token: SyntaxKind): boolean {
return SyntaxKind.FirstKeyword <= token && token <= SyntaxKind.LastKeyword;
}
@@ -899,7 +970,7 @@ module ts {
}
function reportInvalidUseInStrictMode(node: Identifier): void {
// identifierToString cannot be used here since it uses a backreference to 'parent' that is not yet set
// declarationNameToString cannot be used here since it uses a backreference to 'parent' that is not yet set
var name = sourceText.substring(skipTrivia(sourceText, node.pos), node.end);
grammarErrorOnNode(node, Diagnostics.Invalid_use_of_0_in_strict_mode, name);
}
@@ -955,6 +1026,10 @@ module ts {
return token = scanner.reScanSlashToken();
}
function reScanTemplateToken(): SyntaxKind {
return token = scanner.reScanTemplateToken();
}
function lookAheadHelper<T>(callback: () => T, alwaysResetState: boolean): T {
// Keep track of the state we'll need to rollback to if lookahead fails (or if the
// caller asked us to always reset our state).
@@ -1100,7 +1175,9 @@ module ts {
}
function isPropertyName(): boolean {
return token >= SyntaxKind.Identifier || token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral;
return token >= SyntaxKind.Identifier ||
token === SyntaxKind.StringLiteral ||
token === SyntaxKind.NumericLiteral;
}
function parsePropertyName(): Identifier {
@@ -1136,7 +1213,7 @@ module ts {
case ParsingContext.SwitchClauses:
return token === SyntaxKind.CaseKeyword || token === SyntaxKind.DefaultKeyword;
case ParsingContext.TypeMembers:
return isTypeMember();
return isStartOfTypeMember();
case ParsingContext.ClassMembers:
return lookAhead(isClassMemberStart);
case ParsingContext.EnumMembers:
@@ -1148,14 +1225,14 @@ module ts {
case ParsingContext.TypeParameters:
return isIdentifier();
case ParsingContext.ArgumentExpressions:
return token === SyntaxKind.CommaToken || isExpression();
return token === SyntaxKind.CommaToken || isStartOfExpression();
case ParsingContext.ArrayLiteralMembers:
return token === SyntaxKind.CommaToken || isExpression();
return token === SyntaxKind.CommaToken || isStartOfExpression();
case ParsingContext.Parameters:
return isParameter();
return isStartOfParameter();
case ParsingContext.TypeArguments:
case ParsingContext.TupleElementTypes:
return token === SyntaxKind.CommaToken || isType();
return token === SyntaxKind.CommaToken || isStartOfType();
}
Debug.fail("Non-exhaustive case in 'isListElement'.");
@@ -1375,7 +1452,48 @@ module ts {
return finishNode(node);
}
function parseLiteralNode(internName?:boolean): LiteralExpression {
function parseTemplateExpression() {
var template = <TemplateExpression>createNode(SyntaxKind.TemplateExpression);
template.head = parseLiteralNode();
Debug.assert(template.head.kind === SyntaxKind.TemplateHead, "Template head has wrong token kind");
var templateSpans = <NodeArray<TemplateSpan>>[];
templateSpans.pos = getNodePos();
do {
templateSpans.push(parseTemplateSpan());
}
while (templateSpans[templateSpans.length - 1].literal.kind === SyntaxKind.TemplateMiddle)
templateSpans.end = getNodeEnd();
template.templateSpans = templateSpans;
return finishNode(template);
}
function parseTemplateSpan(): TemplateSpan {
var span = <TemplateSpan>createNode(SyntaxKind.TemplateSpan);
span.expression = parseExpression(/*noIn*/ false);
var literal: LiteralExpression;
if (token === SyntaxKind.CloseBraceToken) {
reScanTemplateToken()
literal = parseLiteralNode();
}
else {
error(Diagnostics.Invalid_template_literal_expected);
literal = <LiteralExpression>createMissingNode();
literal.text = "";
}
span.literal = literal;
return finishNode(span);
}
function parseLiteralNode(internName?: boolean): LiteralExpression {
var node = <LiteralExpression>createNode(token);
var text = scanner.getTokenValue();
node.text = internName ? internIdentifier(text) : text;
@@ -1387,7 +1505,7 @@ module ts {
// Octal literals are not allowed in strict mode or ES5
// Note that theoretically the following condition would hold true literals like 009,
// which is not octal.But because of how the scanner separates the tokens, we would
// never get a token like this.Instead, we would get 00 and 9 as two separate tokens.
// never get a token like this. Instead, we would get 00 and 9 as two separate tokens.
// We also do not need to check for negatives because any prefix operator would be part of a
// parent unary expression.
if (node.kind === SyntaxKind.NumericLiteral
@@ -1406,7 +1524,9 @@ module ts {
}
function parseStringLiteral(): LiteralExpression {
if (token === SyntaxKind.StringLiteral) return parseLiteralNode(/*internName:*/ true);
if (token === SyntaxKind.StringLiteral) {
return parseLiteralNode(/*internName:*/ true);
}
error(Diagnostics.String_literal_expected);
return <LiteralExpression>createMissingNode();
}
@@ -1437,7 +1557,7 @@ module ts {
// user writes a constraint that is an expression and not an actual type, then parse
// it out as an expression (so we can recover well), but report that a type is needed
// instead.
if (isType() || !isExpression()) {
if (isStartOfType() || !isStartOfExpression()) {
node.constraint = parseType();
}
else {
@@ -1473,7 +1593,7 @@ module ts {
return parseOptional(SyntaxKind.ColonToken) ? token === SyntaxKind.StringLiteral ? parseStringLiteral() : parseType() : undefined;
}
function isParameter(): boolean {
function isStartOfParameter(): boolean {
return token === SyntaxKind.DotDotDotToken || isIdentifier() || isModifier(token);
}
@@ -1555,7 +1675,7 @@ module ts {
// Identifier in a PropertySetParameterList of a PropertyAssignment that is contained in strict code
// or if its FunctionBody is strict code(11.1.5).
// It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a
// strict mode FunctionDeclaration or FunctionExpression(13.1)
// strict mode FunctionLikeDeclaration or FunctionExpression(13.1)
if (isInStrictMode && isEvalOrArgumentsIdentifier(parameter.name)) {
reportInvalidUseInStrictMode(parameter.name);
return;
@@ -1681,7 +1801,7 @@ module ts {
return finishNode(node);
}
function isTypeMember(): boolean {
function isStartOfTypeMember(): boolean {
switch (token) {
case SyntaxKind.OpenParenToken:
case SyntaxKind.LessThanToken:
@@ -1788,7 +1908,7 @@ module ts {
return <TypeNode>createMissingNode();
}
function isType(): boolean {
function isStartOfType(): boolean {
switch (token) {
case SyntaxKind.AnyKeyword:
case SyntaxKind.StringKeyword:
@@ -1806,7 +1926,7 @@ module ts {
// or something that starts a type. We don't want to consider things like '(1)' a type.
return lookAhead(() => {
nextToken();
return token === SyntaxKind.CloseParenToken || isParameter() || isType();
return token === SyntaxKind.CloseParenToken || isStartOfParameter() || isStartOfType();
});
default:
return isIdentifier();
@@ -1840,7 +1960,7 @@ module ts {
return type;
}
function isFunctionType(): boolean {
function isStartOfFunctionType(): boolean {
return token === SyntaxKind.LessThanToken || token === SyntaxKind.OpenParenToken && lookAhead(() => {
nextToken();
if (token === SyntaxKind.CloseParenToken || token === SyntaxKind.DotDotDotToken) {
@@ -1873,7 +1993,7 @@ module ts {
}
function parseType(): TypeNode {
if (isFunctionType()) {
if (isStartOfFunctionType()) {
return parseFunctionType(SyntaxKind.CallSignature);
}
if (token === SyntaxKind.NewKeyword) {
@@ -1888,7 +2008,7 @@ module ts {
// EXPRESSIONS
function isExpression(): boolean {
function isStartOfExpression(): boolean {
switch (token) {
case SyntaxKind.ThisKeyword:
case SyntaxKind.SuperKeyword:
@@ -1897,6 +2017,8 @@ module ts {
case SyntaxKind.FalseKeyword:
case SyntaxKind.NumericLiteral:
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.TemplateHead:
case SyntaxKind.OpenParenToken:
case SyntaxKind.OpenBracketToken:
case SyntaxKind.OpenBraceToken:
@@ -1921,9 +2043,9 @@ module ts {
}
}
function isExpressionStatement(): boolean {
function isStartOfExpressionStatement(): boolean {
// As per the grammar, neither '{' nor 'function' can start an expression statement.
return token !== SyntaxKind.OpenBraceToken && token !== SyntaxKind.FunctionKeyword && isExpression();
return token !== SyntaxKind.OpenBraceToken && token !== SyntaxKind.FunctionKeyword && isStartOfExpression();
}
function parseExpression(noIn?: boolean): Expression {
@@ -1944,7 +2066,7 @@ module ts {
// it's more likely that a { would be a allowed (as an object literal). While this
// is also allowed for parameters, the risk is that we consume the { as an object
// literal when it really will be for the block following the parameter.
if (scanner.hasPrecedingLineBreak() || (inParameter && token === SyntaxKind.OpenBraceToken) || !isExpression()) {
if (scanner.hasPrecedingLineBreak() || (inParameter && token === SyntaxKind.OpenBraceToken) || !isStartOfExpression()) {
// preceding line break, open brace in a parameter (likely a function body) or current token is not an expression -
// do not try to parse initializer
return undefined;
@@ -1988,8 +2110,8 @@ module ts {
}
// Now see if we might be in cases '2' or '3'.
// If the expression was a LHS expression, and we have an assignment operator, then
// we're in '2' or '3'. Consume the assignment and return.
// If the expression was a LHS expression, and we have an assignment operator, then
// we're in '2' or '3'. Consume the assignment and return.
if (isLeftHandSideExpression(expr) && isAssignmentOperator()) {
if (isInStrictMode && isEvalOrArgumentsIdentifier(expr)) {
// ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an
@@ -2012,6 +2134,7 @@ module ts {
case SyntaxKind.IndexedAccess:
case SyntaxKind.NewExpression:
case SyntaxKind.CallExpression:
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.ArrayLiteral:
case SyntaxKind.ParenExpression:
case SyntaxKind.ObjectLiteral:
@@ -2021,6 +2144,8 @@ module ts {
case SyntaxKind.RegularExpressionLiteral:
case SyntaxKind.NumericLiteral:
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.TemplateExpression:
case SyntaxKind.FalseKeyword:
case SyntaxKind.NullKeyword:
case SyntaxKind.ThisKeyword:
@@ -2189,7 +2314,7 @@ module ts {
if (token === SyntaxKind.OpenBraceToken) {
body = parseBody(/* ignoreMissingOpenBrace */ false);
}
else if (isStatement(/* inErrorRecovery */ true) && !isExpressionStatement() && token !== SyntaxKind.FunctionKeyword) {
else if (isStatement(/* inErrorRecovery */ true) && !isStartOfExpressionStatement() && token !== SyntaxKind.FunctionKeyword) {
// Check if we got a plain statement (i.e. no expression-statements, no functions expressions/declarations)
//
// Here we try to recover from a potential error situation in the case where the
@@ -2376,7 +2501,7 @@ module ts {
function parseCallAndAccess(expr: Expression, inNewExpression: boolean): Expression {
while (true) {
var dotStart = scanner.getTokenPos();
var dotOrBracketStart = scanner.getTokenPos();
if (parseOptional(SyntaxKind.DotToken)) {
var propertyAccess = <PropertyAccess>createNode(SyntaxKind.PropertyAccess, expr.pos);
// Technically a keyword is valid here as all keywords are identifier names.
@@ -2399,7 +2524,7 @@ module ts {
// 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() && lookAhead(() => scanner.isReservedWord())) {
grammarErrorAtPos(dotStart, scanner.getStartPos() - dotStart, Diagnostics.Identifier_expected);
grammarErrorAtPos(dotOrBracketStart, scanner.getStartPos() - dotOrBracketStart, Diagnostics.Identifier_expected);
var id = <Identifier>createMissingNode();
}
else {
@@ -2412,7 +2537,6 @@ module ts {
continue;
}
var bracketStart = scanner.getTokenPos();
if (parseOptional(SyntaxKind.OpenBracketToken)) {
var indexedAccess = <IndexedAccess>createNode(SyntaxKind.IndexedAccess, expr.pos);
@@ -2422,7 +2546,7 @@ module ts {
// Check for that common pattern and report a better error message.
if (inNewExpression && parseOptional(SyntaxKind.CloseBracketToken)) {
indexedAccess.index = createMissingNode();
grammarErrorAtPos(bracketStart, scanner.getStartPos() - bracketStart, Diagnostics.new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead);
grammarErrorAtPos(dotOrBracketStart, scanner.getStartPos() - dotOrBracketStart, Diagnostics.new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead);
}
else {
indexedAccess.index = parseExpression();
@@ -2455,6 +2579,22 @@ module ts {
expr = finishNode(callExpr);
continue;
}
if (token === SyntaxKind.NoSubstitutionTemplateLiteral || token === SyntaxKind.TemplateHead) {
var tagExpression = <TaggedTemplateExpression>createNode(SyntaxKind.TaggedTemplateExpression, expr.pos);
tagExpression.tag = expr;
tagExpression.template = token === SyntaxKind.NoSubstitutionTemplateLiteral
? parseLiteralNode()
: parseTemplateExpression();
expr = finishNode(tagExpression);
if (languageVersion < ScriptTarget.ES6) {
grammarErrorOnNode(expr, Diagnostics.Tagged_templates_are_only_available_when_targeting_ECMAScript_6_and_higher);
}
continue;
}
return expr;
}
}
@@ -2501,6 +2641,7 @@ module ts {
return parseTokenNode();
case SyntaxKind.NumericLiteral:
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
return parseLiteralNode();
case SyntaxKind.OpenParenToken:
return parseParenExpression();
@@ -2518,6 +2659,9 @@ module ts {
return parseLiteralNode();
}
break;
case SyntaxKind.TemplateHead:
return parseTemplateExpression();
default:
if (isIdentifier()) {
return parseIdentifier();
@@ -2612,9 +2756,13 @@ module ts {
var SetAccesor = 4;
var GetOrSetAccessor = GetAccessor | SetAccesor;
forEach(node.properties, (p: Declaration) => {
// TODO(jfreeman): continue if we have a computed property
if (p.kind === SyntaxKind.OmittedExpression) {
return;
}
var name = <Identifier>p.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
@@ -2634,29 +2782,29 @@ module ts {
currentKind = SetAccesor;
}
else {
Debug.fail("Unexpected syntax kind:" + SyntaxKind[p.kind]);
Debug.fail("Unexpected syntax kind:" + p.kind);
}
if (!hasProperty(seen, p.name.text)) {
seen[p.name.text] = currentKind;
if (!hasProperty(seen, name.text)) {
seen[name.text] = currentKind;
}
else {
var existingKind = seen[p.name.text];
var existingKind = seen[name.text];
if (currentKind === Property && existingKind === Property) {
if (isInStrictMode) {
grammarErrorOnNode(p.name, Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode);
grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode);
}
}
else if ((currentKind & GetOrSetAccessor) && (existingKind & GetOrSetAccessor)) {
if (existingKind !== GetOrSetAccessor && currentKind !== existingKind) {
seen[p.name.text] = currentKind | existingKind;
seen[name.text] = currentKind | existingKind;
}
else {
grammarErrorOnNode(p.name, Diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name);
grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name);
}
}
else {
grammarErrorOnNode(p.name, Diagnostics.An_object_literal_cannot_have_property_and_accessor_with_the_same_name);
grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_property_and_accessor_with_the_same_name);
}
}
});
@@ -2671,7 +2819,7 @@ module ts {
var body = parseBody(/* ignoreMissingOpenBrace */ false);
if (name && isInStrictMode && isEvalOrArgumentsIdentifier(name)) {
// It is a SyntaxError to use within strict mode code the identifiers eval or arguments as the
// Identifier of a FunctionDeclaration or FunctionExpression or as a formal parameter name(13.1)
// Identifier of a FunctionLikeDeclaration or FunctionExpression or as a formal parameter name(13.1)
reportInvalidUseInStrictMode(name);
}
return makeFunctionExpression(SyntaxKind.FunctionExpression, pos, name, sig, body);
@@ -3150,7 +3298,6 @@ module ts {
case SyntaxKind.OpenBraceToken:
case SyntaxKind.VarKeyword:
case SyntaxKind.LetKeyword:
case SyntaxKind.ConstKeyword:
case SyntaxKind.FunctionKeyword:
case SyntaxKind.IfKeyword:
case SyntaxKind.DoKeyword:
@@ -3169,6 +3316,12 @@ module ts {
case SyntaxKind.CatchKeyword:
case SyntaxKind.FinallyKeyword:
return true;
case SyntaxKind.ConstKeyword:
// const keyword can precede enum keyword when defining constant enums
// 'const enum' do not start statement.
// In ES 6 'enum' is a future reserved keyword, so it should not be used as identifier
var isConstEnum = lookAhead(() => nextToken() === SyntaxKind.EnumKeyword);
return !isConstEnum;
case SyntaxKind.InterfaceKeyword:
case SyntaxKind.ClassKeyword:
case SyntaxKind.ModuleKeyword:
@@ -3176,9 +3329,10 @@ module ts {
case SyntaxKind.TypeKeyword:
// When followed by an identifier, these do not start a statement but might
// instead be following declarations
if (isDeclaration()) {
if (isDeclarationStart()) {
return false;
}
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
@@ -3189,7 +3343,7 @@ module ts {
return false;
}
default:
return isExpression();
return isStartOfExpression();
}
}
@@ -3200,6 +3354,7 @@ module ts {
case SyntaxKind.VarKeyword:
case SyntaxKind.LetKeyword:
case SyntaxKind.ConstKeyword:
// const here should always be parsed as const declaration because of check in 'isStatement'
return parseVariableStatement(allowLetAndConstDeclarations);
case SyntaxKind.FunctionKeyword:
return parseFunctionDeclaration();
@@ -3330,8 +3485,8 @@ module ts {
return node;
}
function parseFunctionDeclaration(pos?: number, flags?: NodeFlags): FunctionDeclaration {
var node = <FunctionDeclaration>createNode(SyntaxKind.FunctionDeclaration, pos);
function parseFunctionDeclaration(pos?: number, flags?: NodeFlags): FunctionLikeDeclaration {
var node = <FunctionLikeDeclaration>createNode(SyntaxKind.FunctionDeclaration, pos);
if (flags) node.flags = flags;
parseExpected(SyntaxKind.FunctionKeyword);
node.name = parseIdentifier();
@@ -3340,10 +3495,10 @@ module ts {
node.parameters = sig.parameters;
node.type = sig.type;
node.body = parseAndCheckFunctionBody(/*isConstructor*/ false);
if (isInStrictMode && isEvalOrArgumentsIdentifier(node.name)) {
if (isInStrictMode && isEvalOrArgumentsIdentifier(node.name) && node.name.kind === SyntaxKind.Identifier) {
// It is a SyntaxError to use within strict mode code the identifiers eval or arguments as the
// Identifier of a FunctionDeclaration or FunctionExpression or as a formal parameter name(13.1)
reportInvalidUseInStrictMode(node.name);
// Identifier of a FunctionLikeDeclaration or FunctionExpression or as a formal parameter name(13.1)
reportInvalidUseInStrictMode(<Identifier>node.name);
}
return finishNode(node);
}
@@ -3460,7 +3615,7 @@ module ts {
// A common error is to try to declare an accessor in an ambient class.
if (inAmbientContext && canParseSemicolon()) {
parseSemicolon();
node.body = createMissingNode();
node.body = <Block>createMissingNode();
}
else {
node.body = parseBody(/* ignoreMissingOpenBrace */ false);
@@ -3760,17 +3915,11 @@ module ts {
parseExpected(SyntaxKind.EqualsToken);
node.type = parseType();
parseSemicolon();
var n = node.type;
while (n.kind === SyntaxKind.ParenType) {
n = (<ParenTypeNode>n).type;
}
if (n.kind === SyntaxKind.TypeLiteral && (n.pos !== (<TypeLiteralNode>n).members.pos || n.end !== (<TypeLiteralNode>n).members.end)) {
grammarErrorOnNode(node.type, Diagnostics.Aliased_type_cannot_be_an_object_type_literal_Use_an_interface_declaration_instead);
}
return finishNode(node);
}
function parseAndCheckEnumDeclaration(pos: number, flags: NodeFlags): EnumDeclaration {
var enumIsConst = flags & NodeFlags.Const;
function isIntegerLiteral(expression: Expression): boolean {
function isInteger(literalExpression: LiteralExpression): boolean {
// Allows for scientific notation since literalExpression.text was formed by
@@ -3805,22 +3954,29 @@ module ts {
node.name = parsePropertyName();
node.initializer = parseInitializer(/*inParameter*/ false);
if (inAmbientContext) {
if (node.initializer && !isIntegerLiteral(node.initializer) && errorCountBeforeEnumMember === file.syntacticErrors.length) {
grammarErrorOnNode(node.name, Diagnostics.Ambient_enum_elements_can_only_have_integer_literal_initializers);
// skip checks below for const enums - they allow arbitrary initializers as long as they can be evaluated to constant expressions.
// since all values are known in compile time - it is not necessary to check that constant enum section precedes computed enum members.
if (!enumIsConst) {
if (inAmbientContext) {
if (node.initializer && !isIntegerLiteral(node.initializer) && errorCountBeforeEnumMember === file.syntacticErrors.length) {
grammarErrorOnNode(node.name, Diagnostics.Ambient_enum_elements_can_only_have_integer_literal_initializers);
}
}
else if (node.initializer) {
inConstantEnumMemberSection = isIntegerLiteral(node.initializer);
}
else if (!inConstantEnumMemberSection && errorCountBeforeEnumMember === file.syntacticErrors.length) {
grammarErrorOnNode(node.name, Diagnostics.Enum_member_must_have_initializer);
}
}
else if (node.initializer) {
inConstantEnumMemberSection = isIntegerLiteral(node.initializer);
}
else if (!inConstantEnumMemberSection && errorCountBeforeEnumMember === file.syntacticErrors.length) {
grammarErrorOnNode(node.name, Diagnostics.Enum_member_must_have_initializer);
}
return finishNode(node);
}
var node = <EnumDeclaration>createNode(SyntaxKind.EnumDeclaration, pos);
node.flags = flags;
if (enumIsConst) {
parseExpected(SyntaxKind.ConstKeyword);
}
parseExpected(SyntaxKind.EnumKeyword);
node.name = parseIdentifier();
if (parseExpected(SyntaxKind.OpenBraceToken)) {
@@ -3920,7 +4076,7 @@ module ts {
return finishNode(node);
}
function isDeclaration(): boolean {
function isDeclarationStart(): boolean {
switch (token) {
case SyntaxKind.VarKeyword:
case SyntaxKind.LetKeyword:
@@ -3939,14 +4095,14 @@ module ts {
return lookAhead(() => nextToken() >= SyntaxKind.Identifier || token === SyntaxKind.StringLiteral);
case SyntaxKind.ExportKeyword:
// Check for export assignment or modifier on source element
return lookAhead(() => nextToken() === SyntaxKind.EqualsToken || isDeclaration());
return lookAhead(() => nextToken() === SyntaxKind.EqualsToken || isDeclarationStart());
case SyntaxKind.DeclareKeyword:
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.StaticKeyword:
// Check for modifier on source element
return lookAhead(() => { nextToken(); return isDeclaration(); });
return lookAhead(() => { nextToken(); return isDeclarationStart(); });
}
}
@@ -3977,9 +4133,17 @@ module ts {
switch (token) {
case SyntaxKind.VarKeyword:
case SyntaxKind.LetKeyword:
case SyntaxKind.ConstKeyword:
result = parseVariableStatement(/*allowLetAndConstDeclarations*/ true, pos, flags);
break;
case SyntaxKind.ConstKeyword:
var isConstEnum = lookAhead(() => nextToken() === SyntaxKind.EnumKeyword);
if (isConstEnum) {
result = parseAndCheckEnumDeclaration(pos, flags | NodeFlags.Const);
}
else {
result = parseVariableStatement(/*allowLetAndConstDeclarations*/ true, pos, flags);
}
break;
case SyntaxKind.FunctionKeyword:
result = parseFunctionDeclaration(pos, flags);
break;
@@ -4010,7 +4174,7 @@ module ts {
}
function isSourceElement(inErrorRecovery: boolean): boolean {
return isDeclaration() || isStatement(inErrorRecovery);
return isDeclarationStart() || isStatement(inErrorRecovery);
}
function parseSourceElement() {
@@ -4022,7 +4186,7 @@ module ts {
}
function parseSourceElementOrModuleElement(modifierContext: ModifierContext): Statement {
if (isDeclaration()) {
if (isDeclarationStart()) {
return parseDeclaration(modifierContext);
}
@@ -4047,28 +4211,16 @@ module ts {
for (var i = 0; i < commentRanges.length; i++) {
var range = commentRanges[i];
var comment = sourceText.substring(range.pos, range.end);
var simpleReferenceRegEx = /^\/\/\/\s*<reference\s+/gim;
if (simpleReferenceRegEx.exec(comment)) {
var isNoDefaultLibRegEx = /^(\/\/\/\s*<reference\s+no-default-lib=)('|")(.+?)\2\s*\/>/gim;
if (isNoDefaultLibRegEx.exec(comment)) {
file.hasNoDefaultLib = true;
var referencePathMatchResult = getFileReferenceFromReferencePath(comment, range);
if (referencePathMatchResult) {
var fileReference = referencePathMatchResult.fileReference;
file.hasNoDefaultLib = referencePathMatchResult.isNoDefaultLib;
var diagnostic = referencePathMatchResult.diagnostic;
if (fileReference) {
referencedFiles.push(fileReference);
}
else {
var matchResult = fullTripleSlashReferencePathRegEx.exec(comment);
var start = range.pos;
var end = range.end;
var length = end - start;
if (!matchResult) {
errorAtPos(start, length, Diagnostics.Invalid_reference_directive_syntax);
}
else {
referencedFiles.push({
pos: start,
end: end,
filename: matchResult[3]
});
}
if (diagnostic) {
errorAtPos(range.pos, range.end - range.pos, diagnostic);
}
}
else {
+143 -60
View File
@@ -24,6 +24,7 @@ module ts {
isReservedWord(): boolean;
reScanGreaterToken(): SyntaxKind;
reScanSlashToken(): SyntaxKind;
reScanTemplateToken(): SyntaxKind;
scan(): SyntaxKind;
setText(text: string): void;
setTextPos(textPos: number): void;
@@ -466,7 +467,7 @@ module ts {
var len: number; // Length of text
var startPos: number; // Start position of whitespace before current token
var tokenPos: number; // Start position of text of current token
var token: number;
var token: SyntaxKind;
var tokenValue: string;
var precedingLineBreak: boolean;
@@ -519,10 +520,10 @@ module ts {
return +(text.substring(start, pos));
}
function scanHexDigits(count: number, exact?: boolean): number {
function scanHexDigits(count: number, mustMatchCount?: boolean): number {
var digits = 0;
var value = 0;
while (digits < count || !exact) {
while (digits < count || !mustMatchCount) {
var ch = text.charCodeAt(pos);
if (ch >= CharacterCodes._0 && ch <= CharacterCodes._9) {
value = value * 16 + ch - CharacterCodes._0;
@@ -563,60 +564,7 @@ module ts {
}
if (ch === CharacterCodes.backslash) {
result += text.substring(start, pos);
pos++;
if (pos >= len) {
error(Diagnostics.Unexpected_end_of_text);
break;
}
ch = text.charCodeAt(pos++);
switch (ch) {
case CharacterCodes._0:
result += "\0";
break;
case CharacterCodes.b:
result += "\b";
break;
case CharacterCodes.t:
result += "\t";
break;
case CharacterCodes.n:
result += "\n";
break;
case CharacterCodes.v:
result += "\v";
break;
case CharacterCodes.f:
result += "\f";
break;
case CharacterCodes.r:
result += "\r";
break;
case CharacterCodes.singleQuote:
result += "\'";
break;
case CharacterCodes.doubleQuote:
result += "\"";
break;
case CharacterCodes.x:
case CharacterCodes.u:
var ch = scanHexDigits(ch === CharacterCodes.x ? 2 : 4, true);
if (ch >= 0) {
result += String.fromCharCode(ch);
}
else {
error(Diagnostics.Hexadecimal_digit_expected);
}
break;
case CharacterCodes.carriageReturn:
if (pos < len && text.charCodeAt(pos) === CharacterCodes.lineFeed) pos++;
break;
case CharacterCodes.lineFeed:
case CharacterCodes.lineSeparator:
case CharacterCodes.paragraphSeparator:
break;
default:
result += String.fromCharCode(ch);
}
result += scanEscapeSequence();
start = pos;
continue;
}
@@ -630,13 +578,136 @@ module ts {
return result;
}
/**
* Sets the current 'tokenValue' and returns a NoSubstitutionTemplateLiteral or
* a literal component of a TemplateExpression.
*/
function scanTemplateAndSetTokenValue(): SyntaxKind {
var startedWithBacktick = text.charCodeAt(pos) === CharacterCodes.backtick;
pos++;
var start = pos;
var contents = ""
var resultingToken: SyntaxKind;
while (true) {
if (pos >= len) {
contents += text.substring(start, pos);
error(Diagnostics.Unexpected_end_of_text);
resultingToken = startedWithBacktick ? SyntaxKind.NoSubstitutionTemplateLiteral : SyntaxKind.TemplateTail;
break;
}
var currChar = text.charCodeAt(pos);
// '`'
if (currChar === CharacterCodes.backtick) {
contents += text.substring(start, pos);
pos++;
resultingToken = startedWithBacktick ? SyntaxKind.NoSubstitutionTemplateLiteral : SyntaxKind.TemplateTail;
break;
}
// '${'
if (currChar === CharacterCodes.$ && pos + 1 < len && text.charCodeAt(pos + 1) === CharacterCodes.openBrace) {
contents += text.substring(start, pos);
pos += 2;
resultingToken = startedWithBacktick ? SyntaxKind.TemplateHead : SyntaxKind.TemplateMiddle;
break;
}
// Escape character
if (currChar === CharacterCodes.backslash) {
contents += text.substring(start, pos);
contents += scanEscapeSequence();
start = pos;
continue;
}
// Speculated ECMAScript 6 Spec 11.8.6.1:
// <CR><LF> and <CR> LineTerminatorSequences are normalized to <LF> for Template Values
// An explicit EscapeSequence is needed to include a <CR> or <CR><LF> sequence.
if (currChar === CharacterCodes.carriageReturn) {
contents += text.substring(start, pos);
if (pos + 1 < len && text.charCodeAt(pos + 1) === CharacterCodes.lineFeed) {
pos++;
}
pos++;
contents += "\n";
start = pos;
continue;
}
pos++;
}
Debug.assert(resultingToken !== undefined);
tokenValue = contents;
return resultingToken;
}
function scanEscapeSequence(): string {
pos++;
if (pos >= len) {
error(Diagnostics.Unexpected_end_of_text);
return "";
}
var ch = text.charCodeAt(pos++);
switch (ch) {
case CharacterCodes._0:
return "\0";
case CharacterCodes.b:
return "\b";
case CharacterCodes.t:
return "\t";
case CharacterCodes.n:
return "\n";
case CharacterCodes.v:
return "\v";
case CharacterCodes.f:
return "\f";
case CharacterCodes.r:
return "\r";
case CharacterCodes.singleQuote:
return "\'";
case CharacterCodes.doubleQuote:
return "\"";
case CharacterCodes.x:
case CharacterCodes.u:
var ch = scanHexDigits(ch === CharacterCodes.x ? 2 : 4, /*mustMatchCount*/ true);
if (ch >= 0) {
return String.fromCharCode(ch);
}
else {
error(Diagnostics.Hexadecimal_digit_expected);
return ""
}
// when encountering a LineContinuation (i.e. a backslash and a line terminator sequence),
// the line terminator is interpreted to be "the empty code unit sequence".
case CharacterCodes.carriageReturn:
if (pos < len && text.charCodeAt(pos) === CharacterCodes.lineFeed) {
pos++;
}
// fall through
case CharacterCodes.lineFeed:
case CharacterCodes.lineSeparator:
case CharacterCodes.paragraphSeparator:
return ""
default:
return String.fromCharCode(ch);
}
}
// Current character is known to be a backslash. Check for Unicode escape of the form '\uXXXX'
// and return code point value if valid Unicode escape is found. Otherwise return -1.
function peekUnicodeEscape(): number {
if (pos + 5 < len && text.charCodeAt(pos + 1) === CharacterCodes.u) {
var start = pos;
pos += 2;
var value = scanHexDigits(4, true);
var value = scanHexDigits(4, /*mustMatchCount*/ true);
pos = start;
return value;
}
@@ -735,6 +806,8 @@ module ts {
case CharacterCodes.singleQuote:
tokenValue = scanString();
return token = SyntaxKind.StringLiteral;
case CharacterCodes.backtick:
return token = scanTemplateAndSetTokenValue()
case CharacterCodes.percent:
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
return pos += 2, token = SyntaxKind.PercentEqualsToken;
@@ -852,7 +925,7 @@ module ts {
case CharacterCodes._0:
if (pos + 2 < len && (text.charCodeAt(pos + 1) === CharacterCodes.X || text.charCodeAt(pos + 1) === CharacterCodes.x)) {
pos += 2;
var value = scanHexDigits(1, false);
var value = scanHexDigits(1, /*mustMatchCount*/ false);
if (value < 0) {
error(Diagnostics.Hexadecimal_digit_expected);
value = 0;
@@ -1038,6 +1111,15 @@ module ts {
return token;
}
/**
* Unconditionally back up and scan a template expression portion.
*/
function reScanTemplateToken(): SyntaxKind {
Debug.assert(token === SyntaxKind.CloseBraceToken, "'reScanTemplateToken' should only be called on a '}'");
pos = tokenPos;
return token = scanTemplateAndSetTokenValue();
}
function tryScan<T>(callback: () => T): T {
var savePos = pos;
var saveStartPos = startPos;
@@ -1086,10 +1168,11 @@ module ts {
isReservedWord: () => token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord,
reScanGreaterToken: reScanGreaterToken,
reScanSlashToken: reScanSlashToken,
reScanTemplateToken: reScanTemplateToken,
scan: scan,
setText: setText,
setTextPos: setTextPos,
tryScan: tryScan
tryScan: tryScan,
};
}
}
+142 -65
View File
@@ -1,5 +1,4 @@
/// <reference path="core.ts"/>
/// <reference path="scanner.ts"/>
module ts {
@@ -9,7 +8,7 @@ module ts {
}
// token > SyntaxKind.Identifer => token is a keyword
export enum SyntaxKind {
export const enum SyntaxKind {
Unknown,
EndOfFileToken,
SingleLineCommentTrivia,
@@ -20,6 +19,11 @@ module ts {
NumericLiteral,
StringLiteral,
RegularExpressionLiteral,
NoSubstitutionTemplateLiteral,
// Pseudo-literals
TemplateHead,
TemplateMiddle,
TemplateTail,
// Punctuation
OpenBraceToken,
CloseBraceToken,
@@ -165,6 +169,7 @@ module ts {
IndexedAccess,
CallExpression,
NewExpression,
TaggedTemplateExpression,
TypeAssertion,
ParenExpression,
FunctionExpression,
@@ -173,6 +178,8 @@ module ts {
PostfixOperator,
BinaryExpression,
ConditionalExpression,
TemplateExpression,
TemplateSpan,
OmittedExpression,
// Element
Block,
@@ -234,10 +241,14 @@ module ts {
FirstToken = EndOfFileToken,
LastToken = TypeKeyword,
FirstTriviaToken = SingleLineCommentTrivia,
LastTriviaToken = WhitespaceTrivia
LastTriviaToken = WhitespaceTrivia,
FirstLiteralToken = NumericLiteral,
LastLiteralToken = NoSubstitutionTemplateLiteral,
FirstTemplateToken = NoSubstitutionTemplateLiteral,
LastTemplateToken = TemplateTail
}
export enum NodeFlags {
export const enum NodeFlags {
Export = 0x00000001, // Declarations
Ambient = 0x00000002, // Declarations
QuestionMark = 0x00000004, // Parameter/Property/Method
@@ -290,34 +301,66 @@ module ts {
type?: TypeNode;
}
export type DeclarationName = Identifier | LiteralExpression | ComputedPropertyName;
export interface Declaration extends Node {
name?: Identifier;
name?: DeclarationName;
}
export interface ComputedPropertyName extends Node {
expression: Expression;
}
export interface TypeParameterDeclaration extends Declaration {
name: Identifier;
constraint?: TypeNode;
}
export interface SignatureDeclaration extends Declaration, ParsedSignature { }
export interface VariableDeclaration extends Declaration {
name: Identifier;
type?: TypeNode;
initializer?: Expression;
}
export interface PropertyDeclaration extends VariableDeclaration { }
export interface PropertyDeclaration extends Declaration {
type?: TypeNode;
initializer?: Expression;
}
export interface ParameterDeclaration extends VariableDeclaration { }
export interface FunctionDeclaration extends Declaration, ParsedSignature {
/**
* Several node kinds share function-like features such as a signature,
* a name, and a body. These nodes should extend FunctionLikeDeclaration.
* Examples:
* FunctionDeclaration
* MethodDeclaration
* ConstructorDeclaration
* AccessorDeclaration
* FunctionExpression
*/
export interface FunctionLikeDeclaration extends Declaration, ParsedSignature {
body?: Block | Expression;
}
export interface MethodDeclaration extends FunctionDeclaration { }
export interface FunctionDeclaration extends FunctionLikeDeclaration {
name: Identifier;
body?: Block;
}
export interface ConstructorDeclaration extends FunctionDeclaration { }
export interface MethodDeclaration extends FunctionLikeDeclaration {
body?: Block;
}
export interface AccessorDeclaration extends FunctionDeclaration { }
export interface ConstructorDeclaration extends FunctionLikeDeclaration {
body?: Block;
}
export interface AccessorDeclaration extends FunctionLikeDeclaration {
body?: Block;
}
export interface TypeNode extends Node { }
@@ -375,17 +418,30 @@ module ts {
whenFalse: Expression;
}
export interface FunctionExpression extends Expression, FunctionDeclaration {
export interface FunctionExpression extends Expression, FunctionLikeDeclaration {
name?: Identifier;
body: Block | Expression; // Required, whereas the member inherited from FunctionDeclaration is optional
}
// The text property of a LiteralExpression stores the interpreted value of the literal in text form. For a StringLiteral
// this means quotes have been removed and escapes have been converted to actual characters. For a NumericLiteral, the
// stored value is the toString() representation of the number. For example 1, 1.00, and 1e0 are all stored as just "1".
// The text property of a LiteralExpression stores the interpreted value of the literal in text form. For a StringLiteral,
// or any literal of a template, this means quotes have been removed and escapes have been converted to actual characters.
// For a NumericLiteral, the stored value is the toString() representation of the number. For example 1, 1.00, and 1e0 are all stored as just "1".
export interface LiteralExpression extends Expression {
text: string;
}
export interface TemplateExpression extends Expression {
head: LiteralExpression;
templateSpans: NodeArray<TemplateSpan>;
}
// Each of these corresponds to a substitution expression and a template literal, in that order.
// The template literal must have kind TemplateMiddleLiteral or TemplateTailLiteral.
export interface TemplateSpan extends Node {
expression: Expression;
literal: LiteralExpression;
}
export interface ParenExpression extends Expression {
expression: Expression;
}
@@ -416,6 +472,11 @@ module ts {
export interface NewExpression extends CallExpression { }
export interface TaggedTemplateExpression extends Expression {
tag: Expression;
template: LiteralExpression | TemplateExpression;
}
export interface TypeAssertion extends Expression {
type: TypeNode;
operand: Expression;
@@ -509,6 +570,7 @@ module ts {
}
export interface ClassDeclaration extends Declaration {
name: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
baseType?: TypeReferenceNode;
implementedTypes?: NodeArray<TypeReferenceNode>;
@@ -516,28 +578,34 @@ module ts {
}
export interface InterfaceDeclaration extends Declaration {
name: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
baseTypes?: NodeArray<TypeReferenceNode>;
members: NodeArray<Node>;
}
export interface TypeAliasDeclaration extends Declaration {
name: Identifier;
type: TypeNode;
}
export interface EnumMember extends Declaration {
name: Identifier | LiteralExpression;
initializer?: Expression;
}
export interface EnumDeclaration extends Declaration {
name: Identifier;
members: NodeArray<EnumMember>;
}
export interface ModuleDeclaration extends Declaration {
name: Identifier | LiteralExpression;
body: Block | ModuleDeclaration;
}
export interface ImportDeclaration extends Declaration {
name: Identifier;
entityName?: EntityName;
externalModuleName?: LiteralExpression;
}
@@ -633,7 +701,7 @@ module ts {
checkProgram(): void;
emitFiles(targetSourceFile?: SourceFile): EmitResult;
getParentOfSymbol(symbol: Symbol): Symbol;
getTypeOfSymbol(symbol: Symbol): Type;
getNarrowedTypeOfSymbol(symbol: Symbol, node: Node): Type;
getDeclaredTypeOfSymbol(symbol: Symbol): Type;
getPropertiesOfType(type: Type): Symbol[];
getPropertyOfType(type: Type, propertyName: string): Symbol;
@@ -652,7 +720,7 @@ module ts {
getContextualType(node: Node): Type;
getResolvedSignature(node: CallExpression, candidatesOutArray?: Signature[]): Signature;
getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature;
isImplementationOfOverload(node: FunctionDeclaration): boolean;
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
isUndefinedSymbol(symbol: Symbol): boolean;
isArgumentsSymbol(symbol: Symbol): boolean;
hasEarlyErrors(sourceFile?: SourceFile): boolean;
@@ -693,7 +761,7 @@ module ts {
trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void;
}
export enum TypeFormatFlags {
export const enum TypeFormatFlags {
None = 0x00000000,
WriteArrayAsGenericType = 0x00000001, // Write Array<T> instead T[]
UseTypeOfFunction = 0x00000002, // Write typeof instead of function type literal
@@ -704,7 +772,7 @@ module ts {
InElementType = 0x00000040, // Writing an array or union element type
}
export enum SymbolFormatFlags {
export const enum SymbolFormatFlags {
None = 0x00000000,
WriteTypeParametersOrArguments = 0x00000001, // Write symbols's type argument if it is instantiated symbol
// eg. class C<T> { p: T } <-- Show p as C<T>.p here
@@ -715,7 +783,7 @@ module ts {
// When this flag is specified m.c will be used to refer to the class instead of alias symbol x
}
export enum SymbolAccessibility {
export const enum SymbolAccessibility {
Accessible,
NotAccessible,
CannotBeNamed
@@ -730,26 +798,26 @@ module ts {
export interface EmitResolver {
getProgram(): Program;
getLocalNameOfContainer(container: Declaration): string;
getLocalNameOfContainer(container: ModuleDeclaration | EnumDeclaration): string;
getExpressionNamePrefix(node: Identifier): string;
getExportAssignmentName(node: SourceFile): string;
isReferencedImportDeclaration(node: ImportDeclaration): boolean;
isTopLevelValueImportedViaEntityName(node: ImportDeclaration): boolean;
isTopLevelValueImportWithEntityName(node: ImportDeclaration): boolean;
getNodeCheckFlags(node: Node): NodeCheckFlags;
getEnumMemberValue(node: EnumMember): number;
hasSemanticErrors(): boolean;
isDeclarationVisible(node: Declaration): boolean;
isImplementationOfOverload(node: FunctionDeclaration): boolean;
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
writeTypeAtLocation(location: Node, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessiblityResult;
isImportDeclarationEntityNameReferenceDeclarationVisibile(entityName: EntityName): SymbolAccessiblityResult;
// Returns the constant value this property access resolves to, or 'undefined' for a non-constant
getConstantValue(node: PropertyAccess): number;
getConstantValue(node: PropertyAccess | IndexedAccess): number;
hasEarlyErrors(sourceFile?: SourceFile): boolean;
}
export enum SymbolFlags {
export const enum SymbolFlags {
FunctionScopedVariable = 0x00000001, // Variable (var) or parameter
BlockScopedVariable = 0x00000002, // A block-scoped variable (let or const)
Property = 0x00000004, // Property or enum member
@@ -757,33 +825,34 @@ module ts {
Function = 0x00000010, // Function
Class = 0x00000020, // Class
Interface = 0x00000040, // Interface
Enum = 0x00000080, // Enum
ValueModule = 0x00000100, // Instantiated module
NamespaceModule = 0x00000200, // Uninstantiated module
TypeLiteral = 0x00000400, // Type Literal
ObjectLiteral = 0x00000800, // Object Literal
Method = 0x00001000, // Method
Constructor = 0x00002000, // Constructor
GetAccessor = 0x00004000, // Get accessor
SetAccessor = 0x00008000, // Set accessor
CallSignature = 0x00010000, // Call signature
ConstructSignature = 0x00020000, // Construct signature
IndexSignature = 0x00040000, // Index signature
TypeParameter = 0x00080000, // Type parameter
TypeAlias = 0x00100000, // Type alias
ConstEnum = 0x00000080, // Const enum
RegularEnum = 0x00000100, // Enum
ValueModule = 0x00000200, // Instantiated module
NamespaceModule = 0x00000400, // Uninstantiated module
TypeLiteral = 0x00000800, // Type Literal
ObjectLiteral = 0x00001000, // Object Literal
Method = 0x00002000, // Method
Constructor = 0x00004000, // Constructor
GetAccessor = 0x00008000, // Get accessor
SetAccessor = 0x00010000, // Set accessor
CallSignature = 0x00020000, // Call signature
ConstructSignature = 0x00040000, // Construct signature
IndexSignature = 0x00080000, // Index signature
TypeParameter = 0x00100000, // Type parameter
TypeAlias = 0x00200000, // Type alias
// Export markers (see comment in declareModuleMember in binder)
ExportValue = 0x00200000, // Exported value marker
ExportType = 0x00400000, // Exported type marker
ExportNamespace = 0x00800000, // Exported namespace marker
Import = 0x01000000, // Import
Instantiated = 0x02000000, // Instantiated symbol
Merged = 0x04000000, // Merged symbol (created during program binding)
Transient = 0x08000000, // Transient symbol (created during type check)
Prototype = 0x10000000, // Prototype property (no source representation)
UnionProperty = 0x20000000, // Property in union type
ExportValue = 0x00400000, // Exported value marker
ExportType = 0x00800000, // Exported type marker
ExportNamespace = 0x01000000, // Exported namespace marker
Import = 0x02000000, // Import
Instantiated = 0x04000000, // Instantiated symbol
Merged = 0x08000000, // Merged symbol (created during program binding)
Transient = 0x10000000, // Transient symbol (created during type check)
Prototype = 0x20000000, // Prototype property (no source representation)
UnionProperty = 0x40000000, // Property in union type
Enum = RegularEnum | ConstEnum,
Variable = FunctionScopedVariable | BlockScopedVariable,
Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor,
Type = Class | Interface | Enum | TypeLiteral | ObjectLiteral | TypeParameter | TypeAlias,
@@ -806,8 +875,9 @@ module ts {
FunctionExcludes = Value & ~(Function | ValueModule),
ClassExcludes = (Value | Type) & ~ValueModule,
InterfaceExcludes = Type & ~Interface,
EnumExcludes = (Value | Type) & ~(Enum | ValueModule),
ValueModuleExcludes = Value & ~(Function | Class | Enum | ValueModule),
RegularEnumExcludes = (Value | Type) & ~(RegularEnum | ValueModule), // regular enums merge only with regular enums and modules
ConstEnumExcludes = (Value | Type) & ~ConstEnum, // const enums merge only with const enums
ValueModuleExcludes = Value & ~(Function | Class | RegularEnum | ValueModule),
NamespaceModuleExcludes = 0,
MethodExcludes = Value & ~Method,
GetAccessorExcludes = Value & ~SetAccessor,
@@ -839,7 +909,8 @@ module ts {
members?: SymbolTable; // Class, interface or literal instance members
exports?: SymbolTable; // Module exports
exportSymbol?: Symbol; // Exported symbol associated with this symbol
valueDeclaration?: Declaration // First value declaration of the symbol
valueDeclaration?: Declaration // First value declaration of the symbol,
constEnumOnlyModule?: boolean // For modules - if true - module contains only const enums or other modules with only const enums.
}
export interface SymbolLinks {
@@ -858,7 +929,7 @@ module ts {
[index: string]: Symbol;
}
export enum NodeCheckFlags {
export const enum NodeCheckFlags {
TypeChecked = 0x00000001, // Node has been type checked
LexicalThis = 0x00000002, // Lexical 'this' reference
CaptureThis = 0x00000004, // Lexical 'this' used in body
@@ -883,7 +954,7 @@ module ts {
assignmentChecks?: Map<boolean>; // Cache of assignment checks
}
export enum TypeFlags {
export const enum TypeFlags {
Any = 0x00000001,
String = 0x00000002,
Number = 0x00000004,
@@ -980,7 +1051,7 @@ module ts {
mapper?: TypeMapper; // Instantiation mapper
}
export enum SignatureKind {
export const enum SignatureKind {
Call,
Construct,
}
@@ -1000,7 +1071,7 @@ module ts {
isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison
}
export enum IndexKind {
export const enum IndexKind {
String,
Number,
}
@@ -1009,14 +1080,18 @@ module ts {
(t: Type): Type;
}
export interface TypeInferences {
primary: Type[]; // Inferences made directly to a type parameter
secondary: Type[]; // Inferences made to a type parameter in a union type
}
export interface InferenceContext {
typeParameters: TypeParameter[]; // Type parameters for which inferences are made
inferUnionTypes: boolean; // Infer union types for disjoint candidates (otherwise undefinedType)
inferenceCount: number; // Incremented for every inference made (whether new or not)
inferences: Type[][]; // Inferences made for each type parameter
inferredTypes: Type[]; // Inferred type for each type parameter
failedTypeParameterIndex?: number; // Index of type parameter for which inference failed
// It is optional because in contextual signature instantiation, nothing fails
typeParameters: TypeParameter[]; // Type parameters for which inferences are made
inferUnionTypes: boolean; // Infer union types for disjoint candidates (otherwise undefinedType)
inferences: TypeInferences[]; // Inferences made for each type parameter
inferredTypes: Type[]; // Inferred type for each type parameter
failedTypeParameterIndex?: number; // Index of type parameter for which inference failed
// It is optional because in contextual signature instantiation, nothing fails
}
export interface DiagnosticMessage {
@@ -1076,10 +1151,11 @@ module ts {
target?: ScriptTarget;
version?: boolean;
watch?: boolean;
preserveConstEnums?: boolean;
[option: string]: string | number | boolean;
}
export enum ModuleKind {
export const enum ModuleKind {
None,
CommonJS,
AMD,
@@ -1094,7 +1170,7 @@ module ts {
}
export enum ScriptTarget {
export const enum ScriptTarget {
ES3,
ES5,
ES6,
@@ -1116,7 +1192,7 @@ module ts {
error?: DiagnosticMessage; // The error given when the argument does not fit a customized 'type'.
}
export enum CharacterCodes {
export const enum CharacterCodes {
nullCharacter = 0,
maxAsciiCharacter = 0x7F,
@@ -1218,6 +1294,7 @@ module ts {
asterisk = 0x2A, // *
at = 0x40, // @
backslash = 0x5C, // \
backtick = 0x60, // `
bar = 0x7C, // |
caret = 0x5E, // ^
closeBrace = 0x7D, // }
+1 -3
View File
@@ -3,7 +3,7 @@
/// <reference path='typeWriter.ts' />
/// <reference path='syntacticCleaner.ts' />
enum CompilerTestType {
const enum CompilerTestType {
Conformance,
Regressions,
Test262
@@ -285,12 +285,10 @@ class CompilerBaselineRunner extends RunnerBase {
typeLines.push('=== ' + file.unitName + ' ===\r\n');
for (var i = 0; i < codeLines.length; i++) {
var currentCodeLine = codeLines[i];
var lastLine = typeLines[typeLines.length];
typeLines.push(currentCodeLine + '\r\n');
if (typeMap[file.unitName]) {
var typeInfo = typeMap[file.unitName][i];
if (typeInfo) {
var leadingSpaces = '';
typeInfo.forEach(ty => {
typeLines.push('>' + ty + '\r\n');
});
+78 -60
View File
@@ -136,10 +136,11 @@ module FourSlash {
outDir: 'outDir',
sourceMap: 'sourceMap',
sourceRoot: 'sourceRoot',
resolveReference: 'ResolveReference', // This flag is used to specify entry file for resolve file references. The flag is only allow once per test file
};
// List of allowed metadata names
var fileMetadataNames = [testOptMetadataNames.filename, testOptMetadataNames.emitThisFile];
var fileMetadataNames = [testOptMetadataNames.filename, testOptMetadataNames.emitThisFile, testOptMetadataNames.resolveReference];
var globalMetadataNames = [testOptMetadataNames.baselineFile, testOptMetadataNames.declaration,
testOptMetadataNames.mapRoot, testOptMetadataNames.module, testOptMetadataNames.out,
testOptMetadataNames.outDir, testOptMetadataNames.sourceMap, testOptMetadataNames.sourceRoot]
@@ -236,6 +237,25 @@ module FourSlash {
throw new Error("Operation should be cancelled");
}
// This function creates IScriptSnapshot object for testing getPreProcessedFileInfo
// Return object may lack some functionalities for other purposes.
function createScriptSnapShot(sourceText: string): TypeScript.IScriptSnapshot {
return {
getText: (start: number, end: number) => {
return sourceText.substr(start, end - start);
},
getLength: () => {
return sourceText.length;
},
getLineStartPositions: () => {
return <number[]>[];
},
getChangeRange: (oldSnapshot: TypeScript.IScriptSnapshot) => {
return <TypeScript.TextChangeRange>undefined;
}
};
}
export class TestState {
// Language service instance
public languageServiceShimHost: Harness.LanguageService.TypeScriptLS;
@@ -264,6 +284,16 @@ module FourSlash {
private scenarioActions: string[] = [];
private taoInvalidReason: string = null;
private inputFiles: ts.Map<string> = {}; // Map between inputFile's filename and its content for easily looking up when resolving references
// Add input file which has matched file name with the given reference-file path.
// This is necessary when resolveReference flag is specified
private addMatchedInputFile(referenceFilePath: string) {
var inputFile = this.inputFiles[referenceFilePath];
if (inputFile && !Harness.isLibraryFile(referenceFilePath)) {
this.languageServiceShimHost.addScript(referenceFilePath, inputFile);
}
}
constructor(public testData: FourSlashData) {
// Initialize the language service with all the scripts
@@ -273,57 +303,57 @@ module FourSlash {
var compilationSettings = convertGlobalOptionsToCompilationSettings(this.testData.globalOptions);
this.languageServiceShimHost.setCompilationSettings(compilationSettings);
var inputFiles: { unitName: string; content: string }[] = [];
var startResolveFileRef: FourSlashFile = undefined;
testData.files.forEach(file => {
var fixedPath = file.fileName.substr(file.fileName.indexOf('tests/'));
});
// NEWTODO: disable resolution for now.
// If the last unit contains require( or /// reference then consider it the only input file
// and the rest will be added via resolution. If not, then assume we have multiple files
// with 0 references in any of them. We could be smarter here to allow scenarios like
// 2 files without references and 1 file with a reference but we have 0 tests like that
// at the moment and an exhaustive search of the test files for that content could be quite slow.
var lastFile = testData.files[testData.files.length - 1];
//if (/require\(/.test(lastFile.content) || /reference\spath/.test(lastFile.content)) {
// inputFiles.push({ unitName: lastFile.fileName, content: lastFile.content });
//} else {
inputFiles = testData.files.map(file => {
return { unitName: file.fileName, content: file.content };
});
//}
// NEWTODO: Re-implement commented-out section
//harnessCompiler.addInputFiles(inputFiles);
//try {
// var resolvedFiles = harnessCompiler.resolve();
// resolvedFiles.forEach(file => {
// if (!Harness.isLibraryFile(file.path)) {
// var fixedPath = file.path.substr(file.path.indexOf('tests/'));
// var content = harnessCompiler.getContentForFile(fixedPath);
// this.languageServiceShimHost.addScript(fixedPath, content);
// }
// });
// this.languageServiceShimHost.addScript('lib.d.ts', Harness.Compiler.libTextMinimal);
//}
//finally {
// // harness no longer needs the results of the above work, make sure the next test operations are in a clean state
// harnessCompiler.reset();
//}
/// NEWTODO: For now do not resolve, just use the input files
inputFiles.forEach(file => {
if (!Harness.isLibraryFile(file.unitName)) {
this.languageServiceShimHost.addScript(file.unitName, file.content);
ts.forEach(testData.files, file => {
// Create map between fileName and its content for easily looking up when resolveReference flag is specified
this.inputFiles[file.fileName] = file.content;
if (!startResolveFileRef && file.fileOptions[testOptMetadataNames.resolveReference]) {
startResolveFileRef = file;
} else if (startResolveFileRef) {
// If entry point for resolving file references is already specified, report duplication error
throw new Error("There exists a Fourslash file which has resolveReference flag specified; remove duplicated resolveReference flag");
}
});
this.languageServiceShimHost.addDefaultLibrary();
if (startResolveFileRef) {
// Add the entry-point file itself into the languageServiceShimHost
this.languageServiceShimHost.addScript(startResolveFileRef.fileName, startResolveFileRef.content);
var jsonResolvedResult = JSON.parse(this.languageServiceShimHost.getCoreService().getPreProcessedFileInfo(startResolveFileRef.fileName,
createScriptSnapShot(startResolveFileRef.content)));
var resolvedResult = jsonResolvedResult.result;
var referencedFiles: ts.IFileReference[] = resolvedResult.referencedFiles;
var importedFiles: ts.IFileReference[] = resolvedResult.importedFiles;
// Add triple reference files into language-service host
ts.forEach(referencedFiles, referenceFile => {
// Fourslash insert tests/cases/fourslash into inputFile.unitName so we will properly append the same base directory to refFile path
var referenceFilePath = "tests/cases/fourslash/" + referenceFile.path;
this.addMatchedInputFile(referenceFilePath);
});
// Add import files into language-service host
ts.forEach(importedFiles, importedFile => {
// Fourslash insert tests/cases/fourslash into inputFile.unitName and import statement doesn't require ".ts"
// so convert them before making appropriate comparison
var importedFilePath = "tests/cases/fourslash/" + importedFile.path + ".ts";
this.addMatchedInputFile(importedFilePath);
});
// Check if no-default-lib flag is false and if so add default library
if (!resolvedResult.isLibFile) {
this.languageServiceShimHost.addDefaultLibrary();
}
} 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)) {
this.languageServiceShimHost.addScript(fileName, this.inputFiles[fileName]);
}
});
this.languageServiceShimHost.addDefaultLibrary();
}
// Sneak into the language service and get its compiler so we can examine the syntax trees
this.languageService = this.languageServiceShimHost.getLanguageService().languageService;
@@ -2044,10 +2074,6 @@ module FourSlash {
}
}
private getEOF(): number {
return this.languageServiceShimHost.getScriptSnapshot(this.activeFile.fileName).getLength();
}
// Get the text of the entire line the caret is currently at
private getCurrentLineContent() {
// The current caret position (in line/col terms)
@@ -2163,14 +2189,6 @@ module FourSlash {
return result;
}
private getCurrentLineNumberZeroBased() {
return this.getCurrentLineNumberOneBased() - 1;
}
private getCurrentLineNumberOneBased() {
return this.languageServiceShimHost.positionToZeroBasedLineCol(this.activeFile.fileName, this.currentCaretPosition).line + 1;
}
private getLineColStringAtPosition(position: number) {
var pos = this.languageServiceShimHost.positionToZeroBasedLineCol(this.activeFile.fileName, position);
return 'line ' + (pos.line + 1) + ', col ' + pos.character;
@@ -2368,7 +2386,7 @@ module FourSlash {
};
}
enum State {
const enum State {
none,
inSlashStarMarker,
inObjectMarker
+1 -1
View File
@@ -20,7 +20,7 @@ class FourslashRunner extends RunnerBase {
});
this.tests.forEach((fn: string) => {
fn = Harness.Path.switchToForwardSlashes(fn);
fn = ts.normalizeSlashes(fn);
var justName = fn.replace(/^.*[\\\/]/, '');
// Convert to relative path
+9 -15
View File
@@ -30,7 +30,7 @@ module Utils {
var global = <any>Function("return this").call(null);
// Setup some globals based on the current environment
export enum ExecutionEnvironment {
export const enum ExecutionEnvironment {
Node,
Browser,
CScript
@@ -117,15 +117,11 @@ module Harness.Path {
}
export function filePath(fullPath: string) {
fullPath = switchToForwardSlashes(fullPath);
fullPath = ts.normalizeSlashes(fullPath);
var components = fullPath.split("/");
var path: string[] = components.slice(0, components.length - 1);
return path.join("/") + "/";
}
export function switchToForwardSlashes(path: string) {
return path.replace(/\\/g, "/").replace(/\/\//g, '/');
}
}
module Harness {
@@ -564,7 +560,7 @@ module Harness {
// Register input files
function register(file: { unitName: string; content: string; }) {
if (file.content !== undefined) {
var filename = Path.switchToForwardSlashes(file.unitName);
var filename = ts.normalizeSlashes(file.unitName);
filemap[getCanonicalFileName(filename)] = ts.createSourceFile(filename, file.content, scriptTarget, /*version:*/ "0");
}
};
@@ -757,7 +753,6 @@ module Harness {
case 'codepage':
case 'createFileLog':
case 'filename':
case 'propagateenumconstants':
case 'removecomments':
case 'watch':
case 'allowautomaticsemicoloninsertion':
@@ -772,7 +767,9 @@ module Harness {
case 'errortruncation':
options.noErrorTruncation = setting.value === 'false';
break;
case 'preserveconstenums':
options.preserveConstEnums = setting.value === 'true';
break;
default:
throw new Error('Unsupported compiler setting ' + setting.flag);
}
@@ -781,7 +778,7 @@ module Harness {
var filemap: { [name: string]: ts.SourceFile; } = {};
var register = (file: { unitName: string; content: string; }) => {
if (file.content !== undefined) {
var filename = Path.switchToForwardSlashes(file.unitName);
var filename = ts.normalizeSlashes(file.unitName);
filemap[getCanonicalFileName(filename)] = ts.createSourceFile(filename, file.content, options.target, /*version:*/ "0");
}
};
@@ -1091,7 +1088,6 @@ module Harness {
/** @param fileResults an array of strings for the fileName and an ITextWriter with its code */
constructor(fileResults: GeneratedFile[], errors: HarnessDiagnostic[], public program: ts.Program,
public currentDirectoryForProgram: string, private sourceMapData: ts.SourceMapData[]) {
var lines: string[] = [];
fileResults.forEach(emittedFile => {
if (isDTS(emittedFile.fileName)) {
@@ -1147,7 +1143,7 @@ module Harness {
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", "noimplicitany", "noresolve", "newline", "newlines", "emitbom", "errortruncation", "usecasesensitivefilenames"];
var fileMetadataNames = ["filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outdir", "noimplicitany", "noresolve", "newline", "newlines", "emitbom", "errortruncation", "usecasesensitivefilenames", "preserveconstenums"];
function extractCompilerSettings(content: string): CompilerSetting[] {
@@ -1245,7 +1241,6 @@ module Harness {
/** Support class for baseline files */
export module Baseline {
var firstRun = true;
export interface BaselineOptions {
LineEndingSensitive?: boolean;
@@ -1286,8 +1281,7 @@ module Harness {
IO.createDirectory(dirName);
fileCache[dirName] = true;
}
var parentDir = IO.directoryName(actualFilename); // .../tests/baselines/local
var parentParentDir = IO.directoryName(IO.directoryName(actualFilename)) // .../tests/baselines
// Create folders if needed
createDirectoryStructure(Harness.IO.directoryName(actualFilename));
+4
View File
@@ -258,6 +258,10 @@ module Harness.LanguageService {
return new TypeScript.Services.TypeScriptServicesFactory().createClassifierShim(this);
}
public getCoreService(): ts.CoreServicesShim {
return new TypeScript.Services.TypeScriptServicesFactory().createCoreServicesShim(this);
}
/** Parse file given its source text */
public parseSourceText(fileName: string, sourceText: TypeScript.IScriptSnapshot): TypeScript.SourceUnitSyntax {
return TypeScript.Parser.parse(fileName, TypeScript.SimpleText.fromScriptSnapshot(sourceText), ts.ScriptTarget.Latest, TypeScript.isDTSFile(fileName)).sourceUnit();
+3 -3
View File
@@ -175,10 +175,10 @@ module Playback {
}
function findResultByPath<T>(wrapper: { resolvePath(s: string): string }, logArray: { path: string; result?: T }[], expectedPath: string, defaultValue?: T): T {
var normalizedName = Harness.Path.switchToForwardSlashes(expectedPath).toLowerCase();
var normalizedName = ts.normalizeSlashes(expectedPath).toLowerCase();
// Try to find the result through normal filename
for (var i = 0; i < logArray.length; i++) {
if (Harness.Path.switchToForwardSlashes(logArray[i].path).toLowerCase() === normalizedName) {
if (ts.normalizeSlashes(logArray[i].path).toLowerCase() === normalizedName) {
return logArray[i].result;
}
}
@@ -203,7 +203,7 @@ module Playback {
function pathsAreEquivalent(left: string, right: string, wrapper: { resolvePath(s: string): string }) {
var key = left + '-~~-' + right;
function areSame(a: string, b: string) {
return Harness.Path.switchToForwardSlashes(a).toLowerCase() === Harness.Path.switchToForwardSlashes(b).toLowerCase();
return ts.normalizeSlashes(a).toLowerCase() === ts.normalizeSlashes(b).toLowerCase();
}
function check() {
if (Harness.Path.getFileName(left).toLowerCase() === Harness.Path.getFileName(right).toLowerCase()) {
+4 -4
View File
@@ -23,7 +23,7 @@ module RWC {
function collateOutputs(outputFiles: Harness.Compiler.GeneratedFile[], clean?: (s: string) => string) {
// Collect, test, and sort the filenames
function cleanName(fn: string) {
var lastSlash = Harness.Path.switchToForwardSlashes(fn).lastIndexOf('/');
var lastSlash = ts.normalizeSlashes(fn).lastIndexOf('/');
return fn.substr(lastSlash + 1).toLowerCase();
}
outputFiles.sort((a, b) => cleanName(a.fileName).localeCompare(cleanName(b.fileName)));
@@ -52,7 +52,7 @@ module RWC {
var compilerResult: Harness.Compiler.CompilerResult;
var compilerOptions: ts.CompilerOptions;
var baselineOpts: Harness.Baseline.BaselineOptions = { Subfolder: 'rwc' };
var baseName = /(.*)\/(.*).json/.exec(Harness.Path.switchToForwardSlashes(jsonPath))[2];
var baseName = /(.*)\/(.*).json/.exec(ts.normalizeSlashes(jsonPath))[2];
// Compile .d.ts files
var declFileCompilationResult: {
declInputFiles: { unitName: string; content: string }[];
@@ -99,7 +99,7 @@ module RWC {
}
ts.forEach(ioLog.filesRead, fileRead => {
var resolvedPath = Harness.Path.switchToForwardSlashes(sys.resolvePath(fileRead.path));
var resolvedPath = ts.normalizeSlashes(sys.resolvePath(fileRead.path));
var inInputList = ts.forEach(inputFiles, inputFile=> inputFile.unitName === resolvedPath);
if (!inInputList) {
// Add the file to other files
@@ -117,7 +117,7 @@ module RWC {
});
function getHarnessCompilerInputUnit(fileName: string) {
var resolvedPath = Harness.Path.switchToForwardSlashes(sys.resolvePath(fileName));
var resolvedPath = ts.normalizeSlashes(sys.resolvePath(fileName));
try {
var content = sys.readFile(resolvedPath);
}
+3 -3
View File
@@ -1,7 +1,7 @@
interface TypeWriterResult {
line: number;
column: number;
syntaxKind: string;
syntaxKind: number;
sourceText: string;
type: string;
}
@@ -84,7 +84,7 @@ class TypeWriterWalker {
this.results.push({
line: lineAndCharacter.line - 1,
column: lineAndCharacter.character,
syntaxKind: ts.SyntaxKind[node.kind],
syntaxKind: node.kind,
sourceText: sourceText,
type: this.checker.typeToString(type, node.parent, ts.TypeFormatFlags.NoTruncation | ts.TypeFormatFlags.WriteOwnNameForAnyLike)
});
@@ -92,7 +92,7 @@ class TypeWriterWalker {
private getTypeOfNode(node: ts.Node): ts.Type {
var type = this.checker.getTypeOfNode(node);
ts.Debug.assert(type, "type doesn't exist");
ts.Debug.assert(type !== undefined, "type doesn't exist");
return type;
}
}
+12 -11
View File
@@ -74,7 +74,7 @@ module ts.BreakpointResolver {
return textSpan(node);
}
if (node.parent.kind == SyntaxKind.ArrowFunction && (<FunctionDeclaration>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);
}
@@ -99,7 +99,7 @@ module ts.BreakpointResolver {
case SyntaxKind.Constructor:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
return spanInFunctionDeclaration(<FunctionDeclaration>node);
return spanInFunctionDeclaration(<FunctionLikeDeclaration>node);
case SyntaxKind.FunctionBlock:
return spanInFunctionBlock(<Block>node);
@@ -178,7 +178,7 @@ module ts.BreakpointResolver {
case SyntaxKind.ModuleDeclaration:
// span on complete module if it is instantiated
if (!isInstantiated(node)) {
if (getModuleInstanceState(node) !== ModuleInstanceState.Instantiated) {
return undefined;
}
@@ -194,8 +194,9 @@ module ts.BreakpointResolver {
// span in statement
return spanInNode((<WithStatement>node).statement);
// No breakpoint in interface
// No breakpoint in interface, type alias
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
return undefined;
// Tokens:
@@ -246,7 +247,7 @@ module ts.BreakpointResolver {
}
// return type of function go to previous token
if (isAnyFunction(node.parent) && (<FunctionDeclaration>node.parent).type === node) {
if (isAnyFunction(node.parent) && (<FunctionLikeDeclaration>node.parent).type === node) {
return spanInPreviousNode(node);
}
@@ -305,7 +306,7 @@ module ts.BreakpointResolver {
return textSpan(parameter);
}
else {
var functionDeclaration = <FunctionDeclaration>parameter.parent;
var functionDeclaration = <FunctionLikeDeclaration>parameter.parent;
var indexOfParameter = indexOf(functionDeclaration.parameters, parameter);
if (indexOfParameter) {
// Not a first parameter, go to previous parameter
@@ -318,12 +319,12 @@ module ts.BreakpointResolver {
}
}
function canFunctionHaveSpanInWholeDeclaration(functionDeclaration: FunctionDeclaration) {
function canFunctionHaveSpanInWholeDeclaration(functionDeclaration: FunctionLikeDeclaration) {
return !!(functionDeclaration.flags & NodeFlags.Export) ||
(functionDeclaration.parent.kind === SyntaxKind.ClassDeclaration && functionDeclaration.kind !== SyntaxKind.Constructor);
}
function spanInFunctionDeclaration(functionDeclaration: FunctionDeclaration): TypeScript.TextSpan {
function spanInFunctionDeclaration(functionDeclaration: FunctionLikeDeclaration): TypeScript.TextSpan {
// No breakpoints in the function signature
if (!functionDeclaration.body) {
return undefined;
@@ -340,7 +341,7 @@ module ts.BreakpointResolver {
function spanInFunctionBlock(block: Block): TypeScript.TextSpan {
var nodeForSpanInBlock = block.statements.length ? block.statements[0] : block.getLastToken();
if (canFunctionHaveSpanInWholeDeclaration(<FunctionDeclaration>block.parent)) {
if (canFunctionHaveSpanInWholeDeclaration(<FunctionLikeDeclaration>block.parent)) {
return spanInNodeIfStartsOnSameLine(block.parent, nodeForSpanInBlock);
}
@@ -350,7 +351,7 @@ module ts.BreakpointResolver {
function spanInBlock(block: Block): TypeScript.TextSpan {
switch (block.parent.kind) {
case SyntaxKind.ModuleDeclaration:
if (!isInstantiated(block.parent)) {
if (getModuleInstanceState(block.parent) !== ModuleInstanceState.Instantiated) {
return undefined;
}
@@ -407,7 +408,7 @@ module ts.BreakpointResolver {
switch (node.parent.kind) {
case SyntaxKind.ModuleBlock:
// If this is not instantiated module block no bp span
if (!isInstantiated(node.parent.parent)) {
if (getModuleInstanceState(node.parent.parent) !== ModuleInstanceState.Instantiated) {
return undefined;
}
-53
View File
@@ -1,53 +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='references.ts' />
module TypeScript {
export class Comment {
constructor(private _trivia: ISyntaxTrivia,
public endsLine: boolean,
public _start: number,
public _end: number) {
}
public start(): number {
return this._start;
}
public end(): number {
return this._end;
}
public fullText(): string {
return this._trivia.fullText();
}
public kind(): SyntaxKind {
return this._trivia.kind();
}
public structuralEquals(ast: Comment, includingPosition: boolean): boolean {
if (includingPosition) {
if (this.start() !== ast.start() || this.end() !== ast.end()) {
return false;
}
}
return this._trivia.fullText() === ast._trivia.fullText() &&
this.endsLine === ast.endsLine;
}
}
}
-759
View File
@@ -1,759 +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='references.ts' />
module TypeScript.ASTHelpers {
var sentinelEmptyArray: any[] = [];
//export function scriptIsElided(sourceUnit: SourceUnitSyntax): boolean {
// return isDTSFile(sourceUnit.syntaxTree.fileName()) || moduleMembersAreElided(sourceUnit.moduleElements);
//}
//export function moduleIsElided(declaration: ModuleDeclarationSyntax): boolean {
// return hasModifier(declaration.modifiers, PullElementFlags.Ambient) || moduleMembersAreElided(declaration.moduleElements);
//}
//function moduleMembersAreElided(members: IModuleElementSyntax[]): boolean {
// for (var i = 0, n = members.length; i < n; i++) {
// var member = members[i];
// // We should emit *this* module if it contains any non-interface types.
// // Caveat: if we have contain a module, then we should be emitted *if we want to
// // emit that inner module as well.
// if (member.kind() === SyntaxKind.ModuleDeclaration) {
// if (!moduleIsElided(<ModuleDeclarationSyntax>member)) {
// return false;
// }
// }
// else if (member.kind() !== SyntaxKind.InterfaceDeclaration) {
// return false;
// }
// }
// return true;
//}
//export function enumIsElided(declaration: EnumDeclarationSyntax): boolean {
// if (hasModifier(declaration.modifiers, PullElementFlags.Ambient)) {
// return true;
// }
// return false;
//}
export function isValidAstNode(ast: ISyntaxElement): boolean {
return ast && !isShared(ast) && start(ast) !== -1 && end(ast) !== -1;
}
export function isValidSpan(ast: ISpan): boolean {
if (!ast)
return false;
if (ast.start() === -1 || ast.end() === -1)
return false;
return true;
}
///
/// Return the ISyntaxElement containing "position"
///
export function getAstAtPosition(script: ISyntaxElement, pos: number, useTrailingTriviaAsLimChar: boolean = true, forceInclusive: boolean = false): ISyntaxElement {
var top: ISyntaxElement = null;
var pre = function (cur: ISyntaxElement, walker: IAstWalker) {
if (!isShared(cur) && isValidAstNode(cur)) {
var isInvalid1 = cur.kind() === SyntaxKind.ExpressionStatement && width(cur) === 0;
if (isInvalid1) {
walker.options.goChildren = false;
}
else {
// Add "cur" to the stack if it contains our position
// For "identifier" nodes, we need a special case: A position equal to "limChar" is
// valid, since the position corresponds to a caret position (in between characters)
// For example:
// bar
// 0123
// If "position === 3", the caret is at the "right" of the "r" character, which should be considered valid
var inclusive =
forceInclusive ||
cur.kind() === SyntaxKind.IdentifierName ||
cur.kind() === SyntaxKind.MemberAccessExpression ||
cur.kind() === SyntaxKind.QualifiedName ||
//cur.kind() === SyntaxKind.TypeRef ||
cur.kind() === SyntaxKind.VariableDeclaration ||
cur.kind() === SyntaxKind.VariableDeclarator ||
cur.kind() === SyntaxKind.InvocationExpression ||
pos === end(script) + lastToken(script).trailingTriviaWidth(); // Special "EOF" case
var minChar = start(cur);
var limChar = end(cur) + (useTrailingTriviaAsLimChar ? trailingTriviaWidth(cur) : 0) + (inclusive ? 1 : 0);
if (pos >= minChar && pos < limChar) {
// Ignore empty lists
if ((cur.kind() !== SyntaxKind.List && cur.kind() !== SyntaxKind.SeparatedList) || end(cur) > start(cur)) {
// TODO: Since ISyntaxElement is sometimes not correct wrt to position, only add "cur" if it's better
// than top of the stack.
if (top === null) {
top = cur;
}
else if (start(cur) >= start(top) &&
(end(cur) + (useTrailingTriviaAsLimChar ? trailingTriviaWidth(cur) : 0)) <= (end(top) + (useTrailingTriviaAsLimChar ? trailingTriviaWidth(top) : 0))) {
// this new node appears to be better than the one we're
// storing. Make this the new node.
// However, If the current top is a missing identifier, we
// don't want to replace it with another missing identifier.
// We want to return the first missing identifier found in a
// depth first walk of the tree.
if (width(top) !== 0 || width(cur) !== 0) {
top = cur;
}
}
}
}
// Don't go further down the tree if pos is outside of [minChar, limChar]
walker.options.goChildren = (minChar <= pos && pos <= limChar);
}
}
};
getAstWalkerFactory().walk(script, pre);
return top;
}
export function getExtendsHeritageClause(clauses: HeritageClauseSyntax[]): HeritageClauseSyntax {
return getHeritageClause(clauses, SyntaxKind.ExtendsHeritageClause);
}
export function getImplementsHeritageClause(clauses: HeritageClauseSyntax[]): HeritageClauseSyntax {
return getHeritageClause(clauses, SyntaxKind.ImplementsHeritageClause);
}
function getHeritageClause(clauses: HeritageClauseSyntax[], kind: SyntaxKind): HeritageClauseSyntax {
if (clauses) {
for (var i = 0, n = clauses.length; i < n; i++) {
var child = clauses[i];
if (child.typeNames.length > 0 && child.kind() === kind) {
return child;
}
}
}
return null;
}
export function isCallExpression(ast: ISyntaxElement): boolean {
return (ast && ast.kind() === SyntaxKind.InvocationExpression) ||
(ast && ast.kind() === SyntaxKind.ObjectCreationExpression);
}
export function isCallExpressionTarget(ast: ISyntaxElement): boolean {
return !!getCallExpressionTarget(ast);
}
export function getCallExpressionTarget(ast: ISyntaxElement): ISyntaxElement {
if (!ast) {
return null;
}
var current = ast;
while (current && current.parent) {
if (current.parent.kind() === SyntaxKind.MemberAccessExpression &&
(<MemberAccessExpressionSyntax>current.parent).name === current) {
current = current.parent;
continue;
}
break;
}
if (current && current.parent) {
if (current.parent.kind() === SyntaxKind.InvocationExpression || current.parent.kind() === SyntaxKind.ObjectCreationExpression) {
return current === (<InvocationExpressionSyntax>current.parent).expression ? current : null;
}
}
return null;
}
function isNameOfSomeDeclaration(ast: ISyntaxElement) {
if (ast === null || ast.parent === null) {
return false;
}
if (ast.kind() !== SyntaxKind.IdentifierName) {
return false;
}
switch (ast.parent.kind()) {
case SyntaxKind.ClassDeclaration:
return (<ClassDeclarationSyntax>ast.parent).identifier === ast;
case SyntaxKind.InterfaceDeclaration:
return (<InterfaceDeclarationSyntax>ast.parent).identifier === ast;
case SyntaxKind.EnumDeclaration:
return (<EnumDeclarationSyntax>ast.parent).identifier === ast;
case SyntaxKind.ModuleDeclaration:
return (<ModuleDeclarationSyntax>ast.parent).name === ast || (<ModuleDeclarationSyntax>ast.parent).stringLiteral === ast;
case SyntaxKind.VariableDeclarator:
return (<VariableDeclaratorSyntax>ast.parent).propertyName === ast;
case SyntaxKind.FunctionDeclaration:
return (<FunctionDeclarationSyntax>ast.parent).identifier === ast;
case SyntaxKind.MemberFunctionDeclaration:
return (<MemberFunctionDeclarationSyntax>ast.parent).propertyName === ast;
case SyntaxKind.Parameter:
return (<ParameterSyntax>ast.parent).identifier === ast;
case SyntaxKind.TypeParameter:
return (<TypeParameterSyntax>ast.parent).identifier === ast;
case SyntaxKind.SimplePropertyAssignment:
return (<SimplePropertyAssignmentSyntax>ast.parent).propertyName === ast;
case SyntaxKind.FunctionPropertyAssignment:
return (<FunctionPropertyAssignmentSyntax>ast.parent).propertyName === ast;
case SyntaxKind.EnumElement:
return (<EnumElementSyntax>ast.parent).propertyName === ast;
case SyntaxKind.ImportDeclaration:
return (<ImportDeclarationSyntax>ast.parent).identifier === ast;
case SyntaxKind.MethodSignature:
return (<MethodSignatureSyntax>ast.parent).propertyName === ast;
case SyntaxKind.PropertySignature:
return (<MethodSignatureSyntax>ast.parent).propertyName === ast;
}
return false;
}
export function isDeclarationASTOrDeclarationNameAST(ast: ISyntaxElement) {
return isNameOfSomeDeclaration(ast) || ASTHelpers.isDeclarationAST(ast);
}
export function getEnclosingParameterForInitializer(ast: ISyntaxElement): ParameterSyntax {
var current = ast;
while (current) {
switch (current.kind()) {
case SyntaxKind.EqualsValueClause:
if (current.parent && current.parent.kind() === SyntaxKind.Parameter) {
return <ParameterSyntax>current.parent;
}
break;
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.ModuleDeclaration:
// exit early
return null;
}
current = current.parent;
}
return null;
}
export function getEnclosingMemberDeclaration(ast: ISyntaxElement): ISyntaxElement {
var current = ast;
while (current) {
switch (current.kind()) {
case SyntaxKind.MemberVariableDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.MemberFunctionDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
return current;
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.ModuleDeclaration:
// exit early
return null;
}
current = current.parent;
}
return null;
}
export function isNameOfFunction(ast: ISyntaxElement) {
return ast
&& ast.parent
&& ast.kind() === SyntaxKind.IdentifierName
&& ast.parent.kind() === SyntaxKind.FunctionDeclaration
&& (<FunctionDeclarationSyntax>ast.parent).identifier === ast;
}
export function isNameOfMemberFunction(ast: ISyntaxElement) {
return ast
&& ast.parent
&& ast.kind() === SyntaxKind.IdentifierName
&& ast.parent.kind() === SyntaxKind.MemberFunctionDeclaration
&& (<MemberFunctionDeclarationSyntax>ast.parent).propertyName === ast;
}
export function isNameOfMemberAccessExpression(ast: ISyntaxElement) {
if (ast &&
ast.parent &&
ast.parent.kind() === SyntaxKind.MemberAccessExpression &&
(<MemberAccessExpressionSyntax>ast.parent).name === ast) {
return true;
}
return false;
}
export function isRightSideOfQualifiedName(ast: ISyntaxElement) {
if (ast &&
ast.parent &&
ast.parent.kind() === SyntaxKind.QualifiedName &&
(<QualifiedNameSyntax>ast.parent).right === ast) {
return true;
}
return false;
}
export function parentIsModuleDeclaration(ast: ISyntaxElement) {
return ast.parent && ast.parent.kind() === SyntaxKind.ModuleDeclaration;
}
export function isDeclarationAST(ast: ISyntaxElement): boolean {
switch (ast.kind()) {
case SyntaxKind.VariableDeclarator:
return getVariableStatement(<VariableDeclaratorSyntax>ast) !== null;
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.Parameter:
case SyntaxKind.SimpleArrowFunctionExpression:
case SyntaxKind.ParenthesizedArrowFunctionExpression:
case SyntaxKind.IndexSignature:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ArrayType:
case SyntaxKind.ObjectType:
case SyntaxKind.TypeParameter:
case SyntaxKind.ConstructorDeclaration:
case SyntaxKind.MemberFunctionDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.MemberVariableDeclaration:
case SyntaxKind.IndexMemberDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.EnumElement:
case SyntaxKind.SimplePropertyAssignment:
case SyntaxKind.FunctionPropertyAssignment:
case SyntaxKind.FunctionExpression:
case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
case SyntaxKind.MethodSignature:
case SyntaxKind.PropertySignature:
return true;
default:
return false;
}
}
export function preComments(element: ISyntaxElement, text: ISimpleText): Comment[]{
if (element) {
switch (element.kind()) {
case SyntaxKind.VariableStatement:
case SyntaxKind.ExpressionStatement:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ImportDeclaration:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.IfStatement:
case SyntaxKind.SimplePropertyAssignment:
case SyntaxKind.MemberFunctionDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.ReturnStatement:
case SyntaxKind.ConstructorDeclaration:
case SyntaxKind.MemberVariableDeclaration:
case SyntaxKind.EnumElement:
case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
case SyntaxKind.IndexSignature:
case SyntaxKind.PropertySignature:
case SyntaxKind.MethodSignature:
case SyntaxKind.FunctionPropertyAssignment:
case SyntaxKind.Parameter:
return convertNodeLeadingComments(element, text);
}
}
return null;
}
export function postComments(element: ISyntaxElement, text: ISimpleText): Comment[] {
if (element) {
switch (element.kind()) {
case SyntaxKind.ExpressionStatement:
return convertNodeTrailingComments(element, text, /*allowWithNewLine:*/ true);
case SyntaxKind.VariableStatement:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ImportDeclaration:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.IfStatement:
case SyntaxKind.SimplePropertyAssignment:
case SyntaxKind.MemberFunctionDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.ReturnStatement:
case SyntaxKind.ConstructorDeclaration:
case SyntaxKind.MemberVariableDeclaration:
case SyntaxKind.EnumElement:
case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
case SyntaxKind.IndexSignature:
case SyntaxKind.PropertySignature:
case SyntaxKind.MethodSignature:
case SyntaxKind.FunctionPropertyAssignment:
case SyntaxKind.Parameter:
return convertNodeTrailingComments(element, text);
}
}
return null;
}
function convertNodeTrailingComments(node: ISyntaxElement, text: ISimpleText, allowWithNewLine = false): Comment[]{
// Bail out quickly before doing any expensive math computation.
var _lastToken = lastToken(node);
if (_lastToken === null || !_lastToken.hasTrailingTrivia()) {
return null;
}
if (!allowWithNewLine && SyntaxUtilities.isLastTokenOnLine(_lastToken, text)) {
return null;
}
return convertComments(_lastToken.trailingTrivia(text), fullStart(node) + fullWidth(node) - _lastToken.trailingTriviaWidth(text));
}
function convertNodeLeadingComments(element: ISyntaxElement, text: ISimpleText): Comment[]{
if (element) {
return convertTokenLeadingComments(firstToken(element), text);
}
return null;
}
export function convertTokenLeadingComments(token: ISyntaxToken, text: ISimpleText): Comment[]{
if (token === null) {
return null;
}
return token.hasLeadingTrivia()
? convertComments(token.leadingTrivia(text), token.fullStart())
: null;
}
export function convertTokenTrailingComments(token: ISyntaxToken, text: ISimpleText): Comment[] {
if (token === null) {
return null;
}
return token.hasTrailingTrivia()
? convertComments(token.trailingTrivia(text), fullEnd(token) - token.trailingTriviaWidth(text))
: null;
}
function convertComments(triviaList: ISyntaxTriviaList, commentStartPosition: number): Comment[]{
var result: Comment[] = null;
for (var i = 0, n = triviaList.count(); i < n; i++) {
var trivia = triviaList.syntaxTriviaAt(i);
if (trivia.isComment()) {
var hasTrailingNewLine = ((i + 1) < n) && triviaList.syntaxTriviaAt(i + 1).isNewLine();
result = result || [];
result.push(convertComment(trivia, commentStartPosition, hasTrailingNewLine));
}
commentStartPosition += trivia.fullWidth();
}
return result;
}
function convertComment(trivia: ISyntaxTrivia, commentStartPosition: number, hasTrailingNewLine: boolean): Comment {
var comment = new Comment(trivia, hasTrailingNewLine, commentStartPosition, commentStartPosition + trivia.fullWidth());
return comment;
}
export function docComments(ast: ISyntaxElement, text: ISimpleText): Comment[] {
if (isDeclarationAST(ast)) {
var comments: Comment[] = null;
if (ast.kind() === SyntaxKind.VariableDeclarator) {
// Get the doc comments for a variable off of the variable statement. That's what
// they'll be attached to in the tree.
comments = TypeScript.ASTHelpers.preComments(getVariableStatement(<VariableDeclaratorSyntax>ast), text);
}
else if (ast.kind() === SyntaxKind.Parameter) {
// First check if the parameter was written like so:
// (
// /** blah */ a,
// /** blah */ b);
comments = TypeScript.ASTHelpers.preComments(ast, text);
if (!comments) {
// Now check if it was written like so:
// (/** blah */ a, /** blah */ b);
// In this case, the comment will belong to the preceding token.
var previousToken = findToken(syntaxTree(ast).sourceUnit(), firstToken(ast).fullStart() - 1);
if (previousToken && (previousToken.kind() === SyntaxKind.OpenParenToken || previousToken.kind() === SyntaxKind.CommaToken)) {
comments = convertTokenTrailingComments(previousToken, text);
}
}
}
else {
comments = TypeScript.ASTHelpers.preComments(ast, text);
}
if (comments && comments.length > 0) {
return comments.filter(c => isDocComment(c));
}
}
return sentinelEmptyArray;
}
export function isDocComment(comment: Comment) {
if (comment.kind() === SyntaxKind.MultiLineCommentTrivia) {
var fullText = comment.fullText();
return fullText.charAt(2) === "*" && fullText.charAt(3) !== "/";
}
return false;
}
export function getParameterList(ast: ISyntaxElement): ParameterListSyntax {
if (ast) {
switch (ast.kind()) {
case SyntaxKind.ConstructorDeclaration:
return getParameterList((<ConstructorDeclarationSyntax>ast).callSignature);
case SyntaxKind.FunctionDeclaration:
return getParameterList((<FunctionDeclarationSyntax>ast).callSignature);
case SyntaxKind.ParenthesizedArrowFunctionExpression:
return getParameterList((<ParenthesizedArrowFunctionExpressionSyntax>ast).callSignature);
case SyntaxKind.ConstructSignature:
return getParameterList((<ConstructSignatureSyntax>ast).callSignature);
case SyntaxKind.MemberFunctionDeclaration:
return getParameterList((<MemberFunctionDeclarationSyntax>ast).callSignature);
case SyntaxKind.FunctionPropertyAssignment:
return getParameterList((<FunctionPropertyAssignmentSyntax>ast).callSignature);
case SyntaxKind.FunctionExpression:
return getParameterList((<FunctionExpressionSyntax>ast).callSignature);
case SyntaxKind.MethodSignature:
return getParameterList((<MethodSignatureSyntax>ast).callSignature);
case SyntaxKind.ConstructorType:
return (<ConstructorTypeSyntax>ast).parameterList;
case SyntaxKind.FunctionType:
return (<FunctionTypeSyntax>ast).parameterList;
case SyntaxKind.CallSignature:
return (<CallSignatureSyntax>ast).parameterList;
case SyntaxKind.GetAccessor:
return getParameterList((<GetAccessorSyntax>ast).callSignature);
case SyntaxKind.SetAccessor:
return getParameterList((<SetAccessorSyntax>ast).callSignature);
}
}
return null;
}
export function getType(ast: ISyntaxElement): ITypeSyntax {
if (ast) {
switch (ast.kind()) {
case SyntaxKind.FunctionDeclaration:
return getType((<FunctionDeclarationSyntax>ast).callSignature);
case SyntaxKind.ParenthesizedArrowFunctionExpression:
return getType((<ParenthesizedArrowFunctionExpressionSyntax>ast).callSignature);
case SyntaxKind.ConstructSignature:
return getType((<ConstructSignatureSyntax>ast).callSignature);
case SyntaxKind.MemberFunctionDeclaration:
return getType((<MemberFunctionDeclarationSyntax>ast).callSignature);
case SyntaxKind.FunctionPropertyAssignment:
return getType((<FunctionPropertyAssignmentSyntax>ast).callSignature);
case SyntaxKind.FunctionExpression:
return getType((<FunctionExpressionSyntax>ast).callSignature);
case SyntaxKind.MethodSignature:
return getType((<MethodSignatureSyntax>ast).callSignature);
case SyntaxKind.CallSignature:
return getType((<CallSignatureSyntax>ast).typeAnnotation);
case SyntaxKind.IndexSignature:
return getType((<IndexSignatureSyntax>ast).typeAnnotation);
case SyntaxKind.PropertySignature:
return getType((<PropertySignatureSyntax>ast).typeAnnotation);
case SyntaxKind.GetAccessor:
return getType((<GetAccessorSyntax>ast).callSignature);
case SyntaxKind.Parameter:
return getType((<ParameterSyntax>ast).typeAnnotation);
case SyntaxKind.MemberVariableDeclaration:
return getType((<MemberVariableDeclarationSyntax>ast).variableDeclarator);
case SyntaxKind.VariableDeclarator:
return getType((<VariableDeclaratorSyntax>ast).typeAnnotation);
case SyntaxKind.CatchClause:
return getType((<CatchClauseSyntax>ast).typeAnnotation);
case SyntaxKind.ConstructorType:
return (<ConstructorTypeSyntax>ast).type;
case SyntaxKind.FunctionType:
return (<FunctionTypeSyntax>ast).type;
case SyntaxKind.TypeAnnotation:
return (<TypeAnnotationSyntax>ast).type;
}
}
return null;
}
function getVariableStatement(variableDeclarator: VariableDeclaratorSyntax): VariableStatementSyntax {
if (variableDeclarator && variableDeclarator.parent && variableDeclarator.parent.parent && variableDeclarator.parent.parent.parent &&
variableDeclarator.parent.kind() === SyntaxKind.SeparatedList &&
variableDeclarator.parent.parent.kind() === SyntaxKind.VariableDeclaration &&
variableDeclarator.parent.parent.parent.kind() === SyntaxKind.VariableStatement) {
return <VariableStatementSyntax>variableDeclarator.parent.parent.parent;
}
return null;
}
export function getVariableDeclaratorModifiers(variableDeclarator: VariableDeclaratorSyntax): ISyntaxToken[] {
var variableStatement = getVariableStatement(variableDeclarator);
return variableStatement ? variableStatement.modifiers : Syntax.emptyList<ISyntaxToken>();
}
export function isIntegerLiteralAST(expression: ISyntaxElement): boolean {
if (expression) {
switch (expression.kind()) {
case SyntaxKind.PlusExpression:
case SyntaxKind.NegateExpression:
// Note: if there is a + or - sign, we can only allow a normal integer following
// (and not a hex integer). i.e. -0xA is a legal expression, but it is not a
// *literal*.
expression = (<PrefixUnaryExpressionSyntax>expression).operand;
return expression.kind() === SyntaxKind.NumericLiteral && IntegerUtilities.isInteger((<ISyntaxToken>expression).text());
case SyntaxKind.NumericLiteral:
// If it doesn't have a + or -, then either an integer literal or a hex literal
// is acceptable.
var text = (<ISyntaxToken>expression).text();
return IntegerUtilities.isInteger(text) || IntegerUtilities.isHexInteger(text);
}
}
return false;
}
export function getEnclosingModuleDeclaration(ast: ISyntaxElement): ModuleDeclarationSyntax {
while (ast) {
if (ast.kind() === SyntaxKind.ModuleDeclaration) {
return <ModuleDeclarationSyntax>ast;
}
ast = ast.parent;
}
return null;
}
function isEntireNameOfModuleDeclaration(nameAST: ISyntaxElement) {
return parentIsModuleDeclaration(nameAST) && (<ModuleDeclarationSyntax>nameAST.parent).name === nameAST;
}
export function getModuleDeclarationFromNameAST(ast: ISyntaxElement): ModuleDeclarationSyntax {
if (ast) {
switch (ast.kind()) {
case SyntaxKind.StringLiteral:
if (parentIsModuleDeclaration(ast) && (<ModuleDeclarationSyntax>ast.parent).stringLiteral === ast) {
return <ModuleDeclarationSyntax>ast.parent;
}
return null;
case SyntaxKind.IdentifierName:
case SyntaxKind.QualifiedName:
if (isEntireNameOfModuleDeclaration(ast)) {
return <ModuleDeclarationSyntax>ast.parent;
}
break;
default:
return null;
}
// Only qualified names can be name of module declaration if they didnt satisfy above conditions
for (ast = ast.parent; ast && ast.kind() === SyntaxKind.QualifiedName; ast = ast.parent) {
if (isEntireNameOfModuleDeclaration(ast)) {
return <ModuleDeclarationSyntax>ast.parent;
}
}
}
return null;
}
export function isLastNameOfModule(ast: ModuleDeclarationSyntax, astName: ISyntaxElement): boolean {
if (ast) {
if (ast.stringLiteral) {
return astName === ast.stringLiteral;
}
else if (ast.name.kind() === SyntaxKind.QualifiedName) {
return astName === (<QualifiedNameSyntax>ast.name).right;
}
else {
return astName === ast.name;
}
}
return false;
}
export function getNameOfIdentifierOrQualifiedName(name: ISyntaxElement): string {
if (name.kind() === SyntaxKind.IdentifierName) {
return (<ISyntaxToken>name).text();
}
else {
Debug.assert(name.kind() == SyntaxKind.QualifiedName);
var dotExpr = <QualifiedNameSyntax>name;
return getNameOfIdentifierOrQualifiedName(dotExpr.left) + "." + getNameOfIdentifierOrQualifiedName(dotExpr.right);
}
}
export function getModuleNames(name: ISyntaxElement, result?: ISyntaxToken[]): ISyntaxToken[] {
result = result || [];
if (name.kind() === SyntaxKind.QualifiedName) {
getModuleNames((<QualifiedNameSyntax>name).left, result);
result.push((<QualifiedNameSyntax>name).right);
}
else {
result.push(<ISyntaxToken>name);
}
return result;
}
}
-721
View File
@@ -1,721 +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='references.ts' />
module TypeScript {
function walkListChildren(preAst: ISyntaxNodeOrToken[], walker: AstWalker): void {
for (var i = 0, n = preAst.length; i < n; i++) {
walker.walk(preAst[i]);
}
}
function walkThrowStatementChildren(preAst: ThrowStatementSyntax, walker: AstWalker): void {
walker.walk(preAst.expression);
}
function walkPrefixUnaryExpressionChildren(preAst: PrefixUnaryExpressionSyntax, walker: AstWalker): void {
walker.walk(preAst.operand);
}
function walkPostfixUnaryExpressionChildren(preAst: PostfixUnaryExpressionSyntax, walker: AstWalker): void {
walker.walk(preAst.operand);
}
function walkDeleteExpressionChildren(preAst: DeleteExpressionSyntax, walker: AstWalker): void {
walker.walk(preAst.expression);
}
function walkTypeArgumentListChildren(preAst: TypeArgumentListSyntax, walker: AstWalker): void {
walker.walk(preAst.typeArguments);
}
function walkTupleTypeChildren(preAst: TupleTypeSyntax, walker: AstWalker): void {
walker.walk(preAst.types);
}
function walkTypeOfExpressionChildren(preAst: TypeOfExpressionSyntax, walker: AstWalker): void {
walker.walk(preAst.expression);
}
function walkVoidExpressionChildren(preAst: VoidExpressionSyntax, walker: AstWalker): void {
walker.walk(preAst.expression);
}
function walkArgumentListChildren(preAst: ArgumentListSyntax, walker: AstWalker): void {
walker.walk(preAst.typeArgumentList);
walker.walk(preAst.arguments);
}
function walkArrayLiteralExpressionChildren(preAst: ArrayLiteralExpressionSyntax, walker: AstWalker): void {
walker.walk(preAst.expressions);
}
function walkSimplePropertyAssignmentChildren(preAst: SimplePropertyAssignmentSyntax, walker: AstWalker): void {
walker.walk(preAst.propertyName);
walker.walk(preAst.expression);
}
function walkFunctionPropertyAssignmentChildren(preAst: FunctionPropertyAssignmentSyntax, walker: AstWalker): void {
walker.walk(preAst.propertyName);
walker.walk(preAst.callSignature);
walker.walk(preAst.block);
}
function walkGetAccessorChildren(preAst: GetAccessorSyntax, walker: AstWalker): void {
walker.walk(preAst.propertyName);
walker.walk(preAst.callSignature);
walker.walk(preAst.block);
}
function walkSeparatedListChildren(preAst: ISyntaxNodeOrToken[], walker: AstWalker): void {
for (var i = 0, n = preAst.length; i < n; i++) {
walker.walk(preAst[i]);
}
}
function walkSetAccessorChildren(preAst: SetAccessorSyntax, walker: AstWalker): void {
walker.walk(preAst.propertyName);
walker.walk(preAst.callSignature);
walker.walk(preAst.block);
}
function walkObjectLiteralExpressionChildren(preAst: ObjectLiteralExpressionSyntax, walker: AstWalker): void {
walker.walk(preAst.propertyAssignments);
}
function walkCastExpressionChildren(preAst: CastExpressionSyntax, walker: AstWalker): void {
walker.walk(preAst.type);
walker.walk(preAst.expression);
}
function walkParenthesizedExpressionChildren(preAst: ParenthesizedExpressionSyntax, walker: AstWalker): void {
walker.walk(preAst.expression);
}
function walkElementAccessExpressionChildren(preAst: ElementAccessExpressionSyntax, walker: AstWalker): void {
walker.walk(preAst.expression);
walker.walk(preAst.argumentExpression);
}
function walkMemberAccessExpressionChildren(preAst: MemberAccessExpressionSyntax, walker: AstWalker): void {
walker.walk(preAst.expression);
walker.walk(preAst.name);
}
function walkQualifiedNameChildren(preAst: QualifiedNameSyntax, walker: AstWalker): void {
walker.walk(preAst.left);
walker.walk(preAst.right);
}
function walkBinaryExpressionChildren(preAst: BinaryExpressionSyntax, walker: AstWalker): void {
walker.walk(preAst.left);
walker.walk(preAst.right);
}
function walkEqualsValueClauseChildren(preAst: EqualsValueClauseSyntax, walker: AstWalker): void {
walker.walk(preAst.value);
}
function walkTypeParameterChildren(preAst: TypeParameterSyntax, walker: AstWalker): void {
walker.walk(preAst.identifier);
walker.walk(preAst.constraint);
}
function walkTypeParameterListChildren(preAst: TypeParameterListSyntax, walker: AstWalker): void {
walker.walk(preAst.typeParameters);
}
function walkGenericTypeChildren(preAst: GenericTypeSyntax, walker: AstWalker): void {
walker.walk(preAst.name);
walker.walk(preAst.typeArgumentList);
}
function walkTypeAnnotationChildren(preAst: TypeAnnotationSyntax, walker: AstWalker): void {
walker.walk(preAst.type);
}
function walkTypeQueryChildren(preAst: TypeQuerySyntax, walker: AstWalker): void {
walker.walk(preAst.name);
}
function walkInvocationExpressionChildren(preAst: InvocationExpressionSyntax, walker: AstWalker): void {
walker.walk(preAst.expression);
walker.walk(preAst.argumentList);
}
function walkObjectCreationExpressionChildren(preAst: ObjectCreationExpressionSyntax, walker: AstWalker): void {
walker.walk(preAst.expression);
walker.walk(preAst.argumentList);
}
function walkTrinaryExpressionChildren(preAst: ConditionalExpressionSyntax, walker: AstWalker): void {
walker.walk(preAst.condition);
walker.walk(preAst.whenTrue);
walker.walk(preAst.whenFalse);
}
function walkFunctionExpressionChildren(preAst: FunctionExpressionSyntax, walker: AstWalker): void {
walker.walk(preAst.identifier);
walker.walk(preAst.callSignature);
walker.walk(preAst.block);
}
function walkFunctionTypeChildren(preAst: FunctionTypeSyntax, walker: AstWalker): void {
walker.walk(preAst.typeParameterList);
walker.walk(preAst.parameterList);
walker.walk(preAst.type);
}
function walkParenthesizedArrowFunctionExpressionChildren(preAst: ParenthesizedArrowFunctionExpressionSyntax, walker: AstWalker): void {
walker.walk(preAst.callSignature);
walker.walk(preAst.block);
walker.walk(preAst.expression);
}
function walkSimpleArrowFunctionExpressionChildren(preAst: SimpleArrowFunctionExpressionSyntax, walker: AstWalker): void {
walker.walk(preAst.parameter);
walker.walk(preAst.block);
walker.walk(preAst.expression);
}
function walkMemberFunctionDeclarationChildren(preAst: MemberFunctionDeclarationSyntax, walker: AstWalker): void {
walker.walk(preAst.propertyName);
walker.walk(preAst.callSignature);
walker.walk(preAst.block);
}
function walkFuncDeclChildren(preAst: FunctionDeclarationSyntax, walker: AstWalker): void {
walker.walk(preAst.identifier);
walker.walk(preAst.callSignature);
walker.walk(preAst.block);
}
function walkIndexMemberDeclarationChildren(preAst: IndexMemberDeclarationSyntax, walker: AstWalker): void {
walker.walk(preAst.indexSignature);
}
function walkIndexSignatureChildren(preAst: IndexSignatureSyntax, walker: AstWalker): void {
walker.walk(preAst.parameters);
walker.walk(preAst.typeAnnotation);
}
function walkCallSignatureChildren(preAst: CallSignatureSyntax, walker: AstWalker): void {
walker.walk(preAst.typeParameterList);
walker.walk(preAst.parameterList);
walker.walk(preAst.typeAnnotation);
}
function walkConstraintChildren(preAst: ConstraintSyntax, walker: AstWalker): void {
walker.walk(preAst.typeOrExpression);
}
function walkConstructorDeclarationChildren(preAst: ConstructorDeclarationSyntax, walker: AstWalker): void {
walker.walk(preAst.callSignature);
walker.walk(preAst.block);
}
function walkConstructorTypeChildren(preAst: FunctionTypeSyntax, walker: AstWalker): void {
walker.walk(preAst.typeParameterList);
walker.walk(preAst.parameterList);
walker.walk(preAst.type);
}
function walkConstructSignatureChildren(preAst: ConstructSignatureSyntax, walker: AstWalker): void {
walker.walk(preAst.callSignature);
}
function walkParameterChildren(preAst: ParameterSyntax, walker: AstWalker): void {
walker.walk(preAst.identifier);
walker.walk(preAst.typeAnnotation);
walker.walk(preAst.equalsValueClause);
}
function walkParameterListChildren(preAst: ParameterListSyntax, walker: AstWalker): void {
walker.walk(preAst.parameters);
}
function walkPropertySignatureChildren(preAst: PropertySignatureSyntax, walker: AstWalker): void {
walker.walk(preAst.propertyName);
walker.walk(preAst.typeAnnotation);
}
function walkVariableDeclaratorChildren(preAst: VariableDeclaratorSyntax, walker: AstWalker): void {
walker.walk(preAst.propertyName);
walker.walk(preAst.typeAnnotation);
walker.walk(preAst.equalsValueClause);
}
function walkMemberVariableDeclarationChildren(preAst: MemberVariableDeclarationSyntax, walker: AstWalker): void {
walker.walk(preAst.variableDeclarator);
}
function walkMethodSignatureChildren(preAst: MethodSignatureSyntax, walker: AstWalker): void {
walker.walk(preAst.propertyName);
walker.walk(preAst.callSignature);
}
function walkReturnStatementChildren(preAst: ReturnStatementSyntax, walker: AstWalker): void {
walker.walk(preAst.expression);
}
function walkForStatementChildren(preAst: ForStatementSyntax, walker: AstWalker): void {
walker.walk(preAst.variableDeclaration);
walker.walk(preAst.initializer);
walker.walk(preAst.condition);
walker.walk(preAst.incrementor);
walker.walk(preAst.statement);
}
function walkForInStatementChildren(preAst: ForInStatementSyntax, walker: AstWalker): void {
walker.walk(preAst.variableDeclaration);
walker.walk(preAst.left);
walker.walk(preAst.expression);
walker.walk(preAst.statement);
}
function walkIfStatementChildren(preAst: IfStatementSyntax, walker: AstWalker): void {
walker.walk(preAst.condition);
walker.walk(preAst.statement);
walker.walk(preAst.elseClause);
}
function walkElseClauseChildren(preAst: ElseClauseSyntax, walker: AstWalker): void {
walker.walk(preAst.statement);
}
function walkWhileStatementChildren(preAst: WhileStatementSyntax, walker: AstWalker): void {
walker.walk(preAst.condition);
walker.walk(preAst.statement);
}
function walkDoStatementChildren(preAst: DoStatementSyntax, walker: AstWalker): void {
walker.walk(preAst.condition);
walker.walk(preAst.statement);
}
function walkBlockChildren(preAst: BlockSyntax, walker: AstWalker): void {
walker.walk(preAst.statements);
}
function walkVariableDeclarationChildren(preAst: VariableDeclarationSyntax, walker: AstWalker): void {
walker.walk(preAst.variableDeclarators);
}
function walkCaseSwitchClauseChildren(preAst: CaseSwitchClauseSyntax, walker: AstWalker): void {
walker.walk(preAst.expression);
walker.walk(preAst.statements);
}
function walkDefaultSwitchClauseChildren(preAst: DefaultSwitchClauseSyntax, walker: AstWalker): void {
walker.walk(preAst.statements);
}
function walkSwitchStatementChildren(preAst: SwitchStatementSyntax, walker: AstWalker): void {
walker.walk(preAst.expression);
walker.walk(preAst.switchClauses);
}
function walkTryStatementChildren(preAst: TryStatementSyntax, walker: AstWalker): void {
walker.walk(preAst.block);
walker.walk(preAst.catchClause);
walker.walk(preAst.finallyClause);
}
function walkCatchClauseChildren(preAst: CatchClauseSyntax, walker: AstWalker): void {
walker.walk(preAst.identifier);
walker.walk(preAst.typeAnnotation);
walker.walk(preAst.block);
}
function walkExternalModuleReferenceChildren(preAst: ExternalModuleReferenceSyntax, walker: AstWalker): void {
walker.walk(preAst.stringLiteral);
}
function walkFinallyClauseChildren(preAst: FinallyClauseSyntax, walker: AstWalker): void {
walker.walk(preAst.block);
}
function walkClassDeclChildren(preAst: ClassDeclarationSyntax, walker: AstWalker): void {
walker.walk(preAst.identifier);
walker.walk(preAst.typeParameterList);
walker.walk(preAst.heritageClauses);
walker.walk(preAst.classElements);
}
function walkScriptChildren(preAst: SourceUnitSyntax, walker: AstWalker): void {
walker.walk(preAst.moduleElements);
}
function walkHeritageClauseChildren(preAst: HeritageClauseSyntax, walker: AstWalker): void {
walker.walk(preAst.typeNames);
}
function walkInterfaceDeclerationChildren(preAst: InterfaceDeclarationSyntax, walker: AstWalker): void {
walker.walk(preAst.identifier);
walker.walk(preAst.typeParameterList);
walker.walk(preAst.heritageClauses);
walker.walk(preAst.body);
}
function walkObjectTypeChildren(preAst: ObjectTypeSyntax, walker: AstWalker): void {
walker.walk(preAst.typeMembers);
}
function walkArrayTypeChildren(preAst: ArrayTypeSyntax, walker: AstWalker): void {
walker.walk(preAst.type);
}
function walkModuleDeclarationChildren(preAst: ModuleDeclarationSyntax, walker: AstWalker): void {
walker.walk(preAst.name);
walker.walk(preAst.stringLiteral);
walker.walk(preAst.moduleElements);
}
function walkModuleNameModuleReferenceChildren(preAst: ModuleNameModuleReferenceSyntax, walker: AstWalker): void {
walker.walk(preAst.moduleName);
}
function walkEnumDeclarationChildren(preAst: EnumDeclarationSyntax, walker: AstWalker): void {
walker.walk(preAst.identifier);
walker.walk(preAst.enumElements);
}
function walkEnumElementChildren(preAst: EnumElementSyntax, walker: AstWalker): void {
walker.walk(preAst.propertyName);
walker.walk(preAst.equalsValueClause);
}
function walkImportDeclarationChildren(preAst: ImportDeclarationSyntax, walker: AstWalker): void {
walker.walk(preAst.identifier);
walker.walk(preAst.moduleReference);
}
function walkExportAssignmentChildren(preAst: ExportAssignmentSyntax, walker: AstWalker): void {
walker.walk(preAst.identifier);
}
function walkWithStatementChildren(preAst: WithStatementSyntax, walker: AstWalker): void {
walker.walk(preAst.condition);
walker.walk(preAst.statement);
}
function walkExpressionStatementChildren(preAst: ExpressionStatementSyntax, walker: AstWalker): void {
walker.walk(preAst.expression);
}
function walkLabeledStatementChildren(preAst: LabeledStatementSyntax, walker: AstWalker): void {
walker.walk(preAst.identifier);
walker.walk(preAst.statement);
}
function walkVariableStatementChildren(preAst: VariableStatementSyntax, walker: AstWalker): void {
walker.walk(preAst.variableDeclaration);
}
var childrenWalkers: IAstWalkChildren[] = new Array<IAstWalkChildren>(SyntaxKind.LastNode + 1);
// Tokens/trivia can't ever be walked into.
for (var i = SyntaxKind.FirstToken, n = SyntaxKind.LastToken; i <= n; i++) {
childrenWalkers[i] = null;
}
for (var i = SyntaxKind.FirstTrivia, n = SyntaxKind.LastTrivia; i <= n; i++) {
childrenWalkers[i] = null;
}
childrenWalkers[SyntaxKind.AddAssignmentExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.AddExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.AndAssignmentExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.AnyKeyword] = null;
childrenWalkers[SyntaxKind.ArgumentList] = walkArgumentListChildren;
childrenWalkers[SyntaxKind.ArrayLiteralExpression] = walkArrayLiteralExpressionChildren;
childrenWalkers[SyntaxKind.ArrayType] = walkArrayTypeChildren;
childrenWalkers[SyntaxKind.SimpleArrowFunctionExpression] = walkSimpleArrowFunctionExpressionChildren;
childrenWalkers[SyntaxKind.ParenthesizedArrowFunctionExpression] = walkParenthesizedArrowFunctionExpressionChildren;
childrenWalkers[SyntaxKind.AssignmentExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.BitwiseAndExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.BitwiseExclusiveOrExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.BitwiseNotExpression] = walkPrefixUnaryExpressionChildren;
childrenWalkers[SyntaxKind.BitwiseOrExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.Block] = walkBlockChildren;
childrenWalkers[SyntaxKind.BooleanKeyword] = null;
childrenWalkers[SyntaxKind.BreakStatement] = null;
childrenWalkers[SyntaxKind.CallSignature] = walkCallSignatureChildren;
childrenWalkers[SyntaxKind.CaseSwitchClause] = walkCaseSwitchClauseChildren;
childrenWalkers[SyntaxKind.CastExpression] = walkCastExpressionChildren;
childrenWalkers[SyntaxKind.CatchClause] = walkCatchClauseChildren;
childrenWalkers[SyntaxKind.ClassDeclaration] = walkClassDeclChildren;
childrenWalkers[SyntaxKind.CommaExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.ConditionalExpression] = walkTrinaryExpressionChildren;
childrenWalkers[SyntaxKind.Constraint] = walkConstraintChildren;
childrenWalkers[SyntaxKind.ConstructorDeclaration] = walkConstructorDeclarationChildren;
childrenWalkers[SyntaxKind.ConstructSignature] = walkConstructSignatureChildren;
childrenWalkers[SyntaxKind.ContinueStatement] = null;
childrenWalkers[SyntaxKind.ConstructorType] = walkConstructorTypeChildren;
childrenWalkers[SyntaxKind.DebuggerStatement] = null;
childrenWalkers[SyntaxKind.DefaultSwitchClause] = walkDefaultSwitchClauseChildren;
childrenWalkers[SyntaxKind.DeleteExpression] = walkDeleteExpressionChildren;
childrenWalkers[SyntaxKind.DivideAssignmentExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.DivideExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.DoStatement] = walkDoStatementChildren;
childrenWalkers[SyntaxKind.ElementAccessExpression] = walkElementAccessExpressionChildren;
childrenWalkers[SyntaxKind.ElseClause] = walkElseClauseChildren;
childrenWalkers[SyntaxKind.EmptyStatement] = null;
childrenWalkers[SyntaxKind.EnumDeclaration] = walkEnumDeclarationChildren;
childrenWalkers[SyntaxKind.EnumElement] = walkEnumElementChildren;
childrenWalkers[SyntaxKind.EqualsExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.EqualsValueClause] = walkEqualsValueClauseChildren;
childrenWalkers[SyntaxKind.EqualsWithTypeConversionExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.ExclusiveOrAssignmentExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.ExportAssignment] = walkExportAssignmentChildren;
childrenWalkers[SyntaxKind.ExpressionStatement] = walkExpressionStatementChildren;
childrenWalkers[SyntaxKind.ExtendsHeritageClause] = walkHeritageClauseChildren;
childrenWalkers[SyntaxKind.ExternalModuleReference] = walkExternalModuleReferenceChildren;
childrenWalkers[SyntaxKind.FalseKeyword] = null;
childrenWalkers[SyntaxKind.FinallyClause] = walkFinallyClauseChildren;
childrenWalkers[SyntaxKind.ForInStatement] = walkForInStatementChildren;
childrenWalkers[SyntaxKind.ForStatement] = walkForStatementChildren;
childrenWalkers[SyntaxKind.FunctionDeclaration] = walkFuncDeclChildren;
childrenWalkers[SyntaxKind.FunctionExpression] = walkFunctionExpressionChildren;
childrenWalkers[SyntaxKind.FunctionPropertyAssignment] = walkFunctionPropertyAssignmentChildren;
childrenWalkers[SyntaxKind.FunctionType] = walkFunctionTypeChildren;
childrenWalkers[SyntaxKind.GenericType] = walkGenericTypeChildren;
childrenWalkers[SyntaxKind.GetAccessor] = walkGetAccessorChildren;
childrenWalkers[SyntaxKind.GreaterThanExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.GreaterThanOrEqualExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.IfStatement] = walkIfStatementChildren;
childrenWalkers[SyntaxKind.ImplementsHeritageClause] = walkHeritageClauseChildren;
childrenWalkers[SyntaxKind.ImportDeclaration] = walkImportDeclarationChildren;
childrenWalkers[SyntaxKind.IndexMemberDeclaration] = walkIndexMemberDeclarationChildren;
childrenWalkers[SyntaxKind.IndexSignature] = walkIndexSignatureChildren;
childrenWalkers[SyntaxKind.InExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.InstanceOfExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.InterfaceDeclaration] = walkInterfaceDeclerationChildren;
childrenWalkers[SyntaxKind.InvocationExpression] = walkInvocationExpressionChildren;
childrenWalkers[SyntaxKind.LabeledStatement] = walkLabeledStatementChildren;
childrenWalkers[SyntaxKind.LeftShiftAssignmentExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.LeftShiftExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.LessThanExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.LessThanOrEqualExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.List] = walkListChildren;
childrenWalkers[SyntaxKind.LogicalAndExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.LogicalNotExpression] = walkPrefixUnaryExpressionChildren;
childrenWalkers[SyntaxKind.LogicalOrExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.MemberAccessExpression] = walkMemberAccessExpressionChildren;
childrenWalkers[SyntaxKind.MemberFunctionDeclaration] = walkMemberFunctionDeclarationChildren;
childrenWalkers[SyntaxKind.MemberVariableDeclaration] = walkMemberVariableDeclarationChildren;
childrenWalkers[SyntaxKind.MethodSignature] = walkMethodSignatureChildren;
childrenWalkers[SyntaxKind.ModuleDeclaration] = walkModuleDeclarationChildren;
childrenWalkers[SyntaxKind.ModuleNameModuleReference] = walkModuleNameModuleReferenceChildren;
childrenWalkers[SyntaxKind.ModuloAssignmentExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.ModuloExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.MultiplyAssignmentExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.MultiplyExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.IdentifierName] = null;
childrenWalkers[SyntaxKind.NegateExpression] = walkPrefixUnaryExpressionChildren;
childrenWalkers[SyntaxKind.None] = null;
childrenWalkers[SyntaxKind.NotEqualsExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.NotEqualsWithTypeConversionExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.NullKeyword] = null;
childrenWalkers[SyntaxKind.NumberKeyword] = null;
childrenWalkers[SyntaxKind.NumericLiteral] = null;
childrenWalkers[SyntaxKind.ObjectCreationExpression] = walkObjectCreationExpressionChildren;
childrenWalkers[SyntaxKind.ObjectLiteralExpression] = walkObjectLiteralExpressionChildren;
childrenWalkers[SyntaxKind.ObjectType] = walkObjectTypeChildren;
childrenWalkers[SyntaxKind.OmittedExpression] = null;
childrenWalkers[SyntaxKind.OrAssignmentExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.Parameter] = walkParameterChildren;
childrenWalkers[SyntaxKind.ParameterList] = walkParameterListChildren;
childrenWalkers[SyntaxKind.ParenthesizedExpression] = walkParenthesizedExpressionChildren;
childrenWalkers[SyntaxKind.PlusExpression] = walkPrefixUnaryExpressionChildren;
childrenWalkers[SyntaxKind.PostDecrementExpression] = walkPostfixUnaryExpressionChildren;
childrenWalkers[SyntaxKind.PostIncrementExpression] = walkPostfixUnaryExpressionChildren;
childrenWalkers[SyntaxKind.PreDecrementExpression] = walkPrefixUnaryExpressionChildren;
childrenWalkers[SyntaxKind.PreIncrementExpression] = walkPrefixUnaryExpressionChildren;
childrenWalkers[SyntaxKind.PropertySignature] = walkPropertySignatureChildren;
childrenWalkers[SyntaxKind.QualifiedName] = walkQualifiedNameChildren;
childrenWalkers[SyntaxKind.RegularExpressionLiteral] = null;
childrenWalkers[SyntaxKind.ReturnStatement] = walkReturnStatementChildren;
childrenWalkers[SyntaxKind.SourceUnit] = walkScriptChildren;
childrenWalkers[SyntaxKind.SeparatedList] = walkSeparatedListChildren;
childrenWalkers[SyntaxKind.SetAccessor] = walkSetAccessorChildren;
childrenWalkers[SyntaxKind.SignedRightShiftAssignmentExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.SignedRightShiftExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.SimplePropertyAssignment] = walkSimplePropertyAssignmentChildren;
childrenWalkers[SyntaxKind.StringLiteral] = null;
childrenWalkers[SyntaxKind.StringKeyword] = null;
childrenWalkers[SyntaxKind.SubtractAssignmentExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.SubtractExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.SuperKeyword] = null;
childrenWalkers[SyntaxKind.SwitchStatement] = walkSwitchStatementChildren;
childrenWalkers[SyntaxKind.ThisKeyword] = null;
childrenWalkers[SyntaxKind.ThrowStatement] = walkThrowStatementChildren;
childrenWalkers[SyntaxKind.TriviaList] = null;
childrenWalkers[SyntaxKind.TrueKeyword] = null;
childrenWalkers[SyntaxKind.TryStatement] = walkTryStatementChildren;
childrenWalkers[SyntaxKind.TupleType] = walkTupleTypeChildren;
childrenWalkers[SyntaxKind.TypeAnnotation] = walkTypeAnnotationChildren;
childrenWalkers[SyntaxKind.TypeArgumentList] = walkTypeArgumentListChildren;
childrenWalkers[SyntaxKind.TypeOfExpression] = walkTypeOfExpressionChildren;
childrenWalkers[SyntaxKind.TypeParameter] = walkTypeParameterChildren;
childrenWalkers[SyntaxKind.TypeParameterList] = walkTypeParameterListChildren;
childrenWalkers[SyntaxKind.TypeQuery] = walkTypeQueryChildren;
childrenWalkers[SyntaxKind.UnsignedRightShiftAssignmentExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.UnsignedRightShiftExpression] = walkBinaryExpressionChildren;
childrenWalkers[SyntaxKind.VariableDeclaration] = walkVariableDeclarationChildren;
childrenWalkers[SyntaxKind.VariableDeclarator] = walkVariableDeclaratorChildren;
childrenWalkers[SyntaxKind.VariableStatement] = walkVariableStatementChildren;
childrenWalkers[SyntaxKind.VoidExpression] = walkVoidExpressionChildren;
childrenWalkers[SyntaxKind.VoidKeyword] = null;
childrenWalkers[SyntaxKind.WhileStatement] = walkWhileStatementChildren;
childrenWalkers[SyntaxKind.WithStatement] = walkWithStatementChildren;
// Verify the code is up to date with the enum
for (var e in SyntaxKind) {
if (SyntaxKind.hasOwnProperty(e) && StringUtilities.isString(SyntaxKind[e])) {
TypeScript.Debug.assert(childrenWalkers[e] !== undefined, "Fix initWalkers: " + SyntaxKind[e]);
}
}
export class AstWalkOptions {
public goChildren = true;
public stopWalking = false;
}
interface IAstWalkChildren {
(preAst: ISyntaxElement, walker: AstWalker): void;
}
export interface IAstWalker {
options: AstWalkOptions;
state: any
}
interface AstWalker {
walk(ast: ISyntaxElement): void;
}
class SimplePreAstWalker implements AstWalker {
public options: AstWalkOptions = new AstWalkOptions();
constructor(
private pre: (ast: ISyntaxElement, state: any) => void,
public state: any) {
}
public walk(ast: ISyntaxElement): void {
if (!ast) {
return;
}
this.pre(ast, this.state);
var walker = childrenWalkers[ast.kind()];
if (walker) {
walker(ast, this);
}
}
}
class SimplePrePostAstWalker implements AstWalker {
public options: AstWalkOptions = new AstWalkOptions();
constructor(
private pre: (ast: ISyntaxElement, state: any) => void,
private post: (ast: ISyntaxElement, state: any) => void,
public state: any) {
}
public walk(ast: ISyntaxElement): void {
if (!ast) {
return;
}
this.pre(ast, this.state);
var walker = childrenWalkers[ast.kind()];
if (walker) {
walker(ast, this);
}
this.post(ast, this.state);
}
}
class NormalAstWalker implements AstWalker {
public options: AstWalkOptions = new AstWalkOptions();
constructor(
private pre: (ast: ISyntaxElement, walker: IAstWalker) => void,
private post: (ast: ISyntaxElement, walker: IAstWalker) => void,
public state: any) {
}
public walk(ast: ISyntaxElement): void {
if (!ast) {
return;
}
// If we're stopping, then bail out immediately.
if (this.options.stopWalking) {
return;
}
this.pre(ast, this);
// If we were asked to stop, then stop.
if (this.options.stopWalking) {
return;
}
if (this.options.goChildren) {
// Call the "walkChildren" function corresponding to "nodeType".
var walker = childrenWalkers[ast.kind()];
if (walker) {
walker(ast, this);
}
}
else {
// no go only applies to children of node issuing it
this.options.goChildren = true;
}
if (this.post) {
this.post(ast, this);
}
}
}
export class AstWalkerFactory {
public walk(ast: ISyntaxElement, pre: (ast: ISyntaxElement, walker: IAstWalker) => void, post?: (ast: ISyntaxElement, walker: IAstWalker) => void, state?: any): void {
new NormalAstWalker(pre, post, state).walk(ast);
}
public simpleWalk(ast: ISyntaxElement, pre: (ast: ISyntaxElement, state: any) => void, post?: (ast: ISyntaxElement, state: any) => void, state?: any): void {
if (post) {
new SimplePrePostAstWalker(pre, post, state).walk(ast);
}
else {
new SimplePreAstWalker(pre, state).walk(ast);
}
}
}
var globalAstWalkerFactory = new AstWalkerFactory();
export function getAstWalkerFactory(): AstWalkerFactory {
return globalAstWalkerFactory;
}
}
-164
View File
@@ -16,56 +16,6 @@
///<reference path='references.ts' />
module TypeScript {
export function stripStartAndEndQuotes(str: string) {
var firstCharCode = str && str.charCodeAt(0);
if (str && str.length >= 2 && firstCharCode === str.charCodeAt(str.length - 1) && (firstCharCode === CharacterCodes.singleQuote || firstCharCode === CharacterCodes.doubleQuote)) {
return str.substring(1, str.length - 1);
}
return str;
}
export function isSingleQuoted(str: string) {
return str && str.length >= 2 && str.charCodeAt(0) === str.charCodeAt(str.length - 1) && str.charCodeAt(0) === CharacterCodes.singleQuote;
}
export function isDoubleQuoted(str: string) {
return str && str.length >= 2 && str.charCodeAt(0) === str.charCodeAt(str.length - 1) && str.charCodeAt(0) === CharacterCodes.doubleQuote;
}
export function isQuoted(str: string) {
return isDoubleQuoted(str) || isSingleQuoted(str);
}
export function quoteStr(str: string) {
return "\"" + str + "\"";
}
var switchToForwardSlashesRegEx = /\\/g;
export function switchToForwardSlashes(path: string) {
return path.replace(switchToForwardSlashesRegEx, "/");
}
export function trimModName(modName: string) {
// in case's it's a declare file...
if (modName.length > 5 && modName.substring(modName.length - 5, modName.length) === ".d.ts") {
return modName.substring(0, modName.length - 5);
}
if (modName.length > 3 && modName.substring(modName.length - 3, modName.length) === ".ts") {
return modName.substring(0, modName.length - 3);
}
// in case's it's a .js file
if (modName.length > 3 && modName.substring(modName.length - 3, modName.length) === ".js") {
return modName.substring(0, modName.length - 3);
}
return modName;
}
export function getDeclareFilePath(fname: string) {
return isTSFile(fname) ? changePathToDTS(fname) : changePathToDTS(fname);
}
function isFileOfExtension(fname: string, ext: string) {
var invariantFname = fname.toLocaleUpperCase();
var invariantExt = ext.toLocaleUpperCase();
@@ -73,121 +23,7 @@ module TypeScript {
return invariantFname.length > extLength && invariantFname.substring(invariantFname.length - extLength, invariantFname.length) === invariantExt;
}
export function isTSFile(fname: string) {
return isFileOfExtension(fname, ".ts");
}
export function isDTSFile(fname: string) {
return isFileOfExtension(fname, ".d.ts");
}
export function getPrettyName(modPath: string, quote=true, treatAsFileName=false): any {
var modName = treatAsFileName ? switchToForwardSlashes(modPath) : trimModName(stripStartAndEndQuotes(modPath));
var components = this.getPathComponents(modName);
return components.length ? (quote ? quoteStr(components[components.length - 1]) : components[components.length - 1]) : modPath;
}
export function getPathComponents(path: string) {
return path.split("/");
}
export function getRelativePathToFixedPath(fixedModFilePath: string, absoluteModPath: string, isAbsoultePathURL = true) {
absoluteModPath = switchToForwardSlashes(absoluteModPath);
var modComponents = this.getPathComponents(absoluteModPath);
var fixedModComponents = this.getPathComponents(fixedModFilePath);
// Find the component that differs
var joinStartIndex = 0;
for (; joinStartIndex < modComponents.length && joinStartIndex < fixedModComponents.length ; joinStartIndex++) {
if (fixedModComponents[joinStartIndex] !== modComponents[joinStartIndex]) {
break;
}
}
// Get the relative path
if (joinStartIndex !== 0) {
var relativePath = "";
var relativePathComponents = modComponents.slice(joinStartIndex, modComponents.length);
for (; joinStartIndex < fixedModComponents.length; joinStartIndex++) {
if (fixedModComponents[joinStartIndex] !== "") {
relativePath = relativePath + "../";
}
}
return relativePath + relativePathComponents.join("/");
}
if (isAbsoultePathURL && absoluteModPath.indexOf("://") === -1) {
absoluteModPath = "file:///" + absoluteModPath;
}
return absoluteModPath;
}
export function changePathToDTS(modPath: string) {
return trimModName(stripStartAndEndQuotes(modPath)) + ".d.ts";
}
export function isRelative(path: string) {
return path.length > 0 && path.charAt(0) === ".";
}
export function isRooted(path: string) {
return path.length > 0 && (path.charAt(0) === "\\" || path.charAt(0) === "/" || (path.indexOf(":\\") !== -1) || (path.indexOf(":/") !== -1));
}
export function getRootFilePath(outFname: string) {
if (outFname === "") {
return outFname;
}
else {
var isPath = outFname.indexOf("/") !== -1;
return isPath ? filePath(outFname) : "";
}
}
export function filePathComponents(fullPath: string) {
fullPath = switchToForwardSlashes(fullPath);
var components = getPathComponents(fullPath);
return components.slice(0, components.length - 1);
}
export function filePath(fullPath: string) {
var path = filePathComponents(fullPath);
return path.join("/") + "/";
}
export function convertToDirectoryPath(dirPath: string) {
if (dirPath && dirPath.charAt(dirPath.length - 1) !== "/") {
dirPath += "/";
}
return dirPath;
}
var normalizePathRegEx = /^\\\\[^\\]/;
export function normalizePath(path: string): string {
// If it's a UNC style path (i.e. \\server\share), convert to a URI style (i.e. file://server/share)
if (normalizePathRegEx.test(path)) {
path = "file:" + path;
}
var parts = this.getPathComponents(switchToForwardSlashes(path));
var normalizedParts: string[] = [];
for (var i = 0; i < parts.length; i++) {
var part = parts[i];
if (part === ".") {
continue;
}
if (normalizedParts.length > 0 && ArrayUtilities.last(normalizedParts) !== ".." && part === "..") {
normalizedParts.pop();
continue;
}
normalizedParts.push(part);
}
return normalizedParts.join("/");
}
}
-208
View File
@@ -1,208 +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.
//
module TypeScript {
export interface ILineAndCharacter {
line: number;
character: number;
}
// Note: This is being using by the host (VS) and is marshaled back and forth. When changing this make sure the changes
// are reflected in the managed side as well.
export interface IFileReference extends ILineAndCharacter {
path: string;
isResident: boolean;
position: number;
length: number;
}
///
/// Preprocessing
///
export interface IPreProcessedFileInfo {
referencedFiles: IFileReference[];
importedFiles: IFileReference[];
diagnostics: Diagnostic[];
isLibFile: boolean;
}
interface ITripleSlashDirectiveProperties {
noDefaultLib: boolean;
diagnostics: Diagnostic[];
referencedFiles: IFileReference[];
}
function isNoDefaultLibMatch(comment: string): RegExpExecArray {
var isNoDefaultLibRegex = /^(\/\/\/\s*<reference\s+no-default-lib=)('|")(.+?)\2\s*\/>/gim;
return isNoDefaultLibRegex.exec(comment);
}
export var tripleSlashReferenceRegExp = /^(\/\/\/\s*<reference\s+path=)('|")(.+?)\2\s*(static=('|")(.+?)\5\s*)*\/>/;
function getFileReferenceFromReferencePath(fileName: string, text: ISimpleText, position: number, comment: string, diagnostics: Diagnostic[]): IFileReference {
// First, just see if they've written: /// <reference\s+
// If so, then we'll consider this a reference directive and we'll report errors if it's
// malformed. Otherwise, we'll completely ignore this.
var lineMap = text.lineMap();
var simpleReferenceRegEx = /^\/\/\/\s*<reference\s+/gim;
if (simpleReferenceRegEx.exec(comment)) {
var isNoDefaultLib = isNoDefaultLibMatch(comment);
if (!isNoDefaultLib) {
var fullReferenceRegEx = tripleSlashReferenceRegExp;
var fullReference = fullReferenceRegEx.exec(comment);
if (!fullReference) {
// It matched the start of a reference directive, but wasn't well formed. Report
// an appropriate error to the user.
diagnostics.push(new Diagnostic(fileName, lineMap, position, comment.length, DiagnosticCode.Invalid_reference_directive_syntax));
}
else {
var path: string = normalizePath(fullReference[3]);
var adjustedPath = normalizePath(path);
var isResident = fullReference.length >= 7 && fullReference[6] === "true";
return {
line: 0,
character: 0,
position: 0,
length: 0,
path: switchToForwardSlashes(adjustedPath),
isResident: isResident
};
}
}
}
return null;
}
var reportDiagnostic = () => { };
function processImports(text: ISimpleText, scanner: Scanner.IScanner, token: ISyntaxToken, importedFiles: IFileReference[]): void {
var lineChar = { line: -1, character: -1 };
var lineMap = text.lineMap();
var start = new Date().getTime();
// Look for:
// import foo = module("foo")
while (token.kind() !== SyntaxKind.EndOfFileToken) {
if (token.kind() === SyntaxKind.ImportKeyword) {
var importToken = token;
token = scanner.scan(/*allowRegularExpression:*/ false);
if (SyntaxFacts.isIdentifierNameOrAnyKeyword(token)) {
token = scanner.scan(/*allowRegularExpression:*/ false);
if (token.kind() === SyntaxKind.EqualsToken) {
token = scanner.scan(/*allowRegularExpression:*/ false);
if (token.kind() === SyntaxKind.ModuleKeyword || token.kind() === SyntaxKind.RequireKeyword) {
token = scanner.scan(/*allowRegularExpression:*/ false);
if (token.kind() === SyntaxKind.OpenParenToken) {
token = scanner.scan(/*allowRegularExpression:*/ false);
lineMap.fillLineAndCharacterFromPosition(TypeScript.start(importToken, text), lineChar);
if (token.kind() === SyntaxKind.StringLiteral) {
var ref = {
line: lineChar.line,
character: lineChar.character,
position: TypeScript.start(token, text),
length: width(token),
path: stripStartAndEndQuotes(switchToForwardSlashes(token.text())),
isResident: false
};
importedFiles.push(ref);
}
}
}
}
}
}
token = scanner.scan(/*allowRegularExpression:*/ false);
}
var totalTime = new Date().getTime() - start;
//TypeScript.fileResolutionScanImportsTime += totalTime;
}
function processTripleSlashDirectives(fileName: string, text: ISimpleText, firstToken: ISyntaxToken): ITripleSlashDirectiveProperties {
var leadingTrivia = firstToken.leadingTrivia(text);
var position = 0;
var lineChar = { line: -1, character: -1 };
var noDefaultLib = false;
var diagnostics: Diagnostic[] = [];
var referencedFiles: IFileReference[] = [];
var lineMap = text.lineMap();
for (var i = 0, n = leadingTrivia.count(); i < n; i++) {
var trivia = leadingTrivia.syntaxTriviaAt(i);
if (trivia.kind() === SyntaxKind.SingleLineCommentTrivia) {
var triviaText = trivia.fullText();
var referencedCode = getFileReferenceFromReferencePath(fileName, text, position, triviaText, diagnostics);
if (referencedCode) {
lineMap.fillLineAndCharacterFromPosition(position, lineChar);
referencedCode.position = position;
referencedCode.length = trivia.fullWidth();
referencedCode.line = lineChar.line;
referencedCode.character = lineChar.character;
referencedFiles.push(referencedCode);
}
// is it a lib file?
var isNoDefaultLib = isNoDefaultLibMatch(triviaText);
if (isNoDefaultLib) {
noDefaultLib = isNoDefaultLib[3] === "true";
}
}
position += trivia.fullWidth();
}
return { noDefaultLib: noDefaultLib, diagnostics: diagnostics, referencedFiles: referencedFiles };
}
export function preProcessFile(fileName: string, sourceText: IScriptSnapshot, readImportFiles = true): IPreProcessedFileInfo {
var text = SimpleText.fromScriptSnapshot(sourceText);
var scanner = Scanner.createScanner(ts.ScriptTarget.Latest, text, reportDiagnostic);
var firstToken = scanner.scan(/*allowRegularExpression:*/ false);
// only search out dynamic mods
// if you find a dynamic mod, ignore every other mod inside, until you balance rcurlies
// var position
var importedFiles: IFileReference[] = [];
if (readImportFiles) {
processImports(text, scanner, firstToken, importedFiles);
}
var properties = processTripleSlashDirectives(fileName, text, firstToken);
return { referencedFiles: properties.referencedFiles, importedFiles: importedFiles, isLibFile: properties.noDefaultLib, diagnostics: properties.diagnostics };
}
export function getReferencedFiles(fileName: string, sourceText: IScriptSnapshot): IFileReference[] {
return preProcessFile(fileName, sourceText, false).referencedFiles;
}
} // Tools
+3 -3
View File
@@ -7,7 +7,7 @@ module TypeScript {
return true;
}
if (array1 === null || array2 === null) {
if (!array1 || !array2) {
return false;
}
@@ -71,7 +71,7 @@ module TypeScript {
}
}
return null;
return undefined;
}
public static firstOrDefault<T>(array: T[], func: (v: T, index: number) => boolean): T {
@@ -82,7 +82,7 @@ module TypeScript {
}
}
return null;
return undefined;
}
public static first<T>(array: T[], func?: (v: T, index: number) => boolean): T {
+2 -1
View File
@@ -14,13 +14,14 @@ module TypeScript {
return this.currentAssertionLevel >= level;
}
public static assert(expression: any, message: string = "", verboseDebugInfo: () => string = null): void {
public static assert(expression: any, message?: string, verboseDebugInfo?: () => string): void {
if (!expression) {
var verboseDebugString = "";
if (verboseDebugInfo) {
verboseDebugString = "\r\nVerbose Debug Information:" + verboseDebugInfo();
}
message = message || "";
throw new Error("Debug Failure. False expression: " + message + verboseDebugString);
}
}
+3 -3
View File
@@ -50,11 +50,11 @@ module TypeScript {
private _arguments: any[];
private _additionalLocations: Location[];
constructor(fileName: string, lineMap: LineMap, start: number, length: number, diagnosticKey: string, _arguments: any[]= null, additionalLocations: Location[] = null) {
constructor(fileName: string, lineMap: LineMap, start: number, length: number, diagnosticKey: string, _arguments?: any[], additionalLocations?: Location[]) {
super(fileName, lineMap, start, length);
this._diagnosticKey = diagnosticKey;
this._arguments = (_arguments && _arguments.length > 0) ? _arguments : null;
this._additionalLocations = (additionalLocations && additionalLocations.length > 0) ? additionalLocations : null;
this._arguments = (_arguments && _arguments.length > 0) ? _arguments : undefined;
this._additionalLocations = (additionalLocations && additionalLocations.length > 0) ? additionalLocations : undefined;
}
public toJSON(key: any): any {
+7 -2
View File
@@ -1,9 +1,14 @@
///<reference path='references.ts' />
module TypeScript {
export interface ILineAndCharacter {
line: number;
character: number;
}
export class LineMap {
public static empty = new LineMap(() => [0], 0);
private _lineStarts: number[] = null;
private _lineStarts: number[] = undefined;
constructor(private _computeLineStarts: () => number[], private length: number) {
}
@@ -18,7 +23,7 @@ module TypeScript {
}
public lineStarts(): number[] {
if (this._lineStarts === null) {
if (!this._lineStarts) {
this._lineStarts = this._computeLineStarts();
}
+3 -8
View File
@@ -52,7 +52,7 @@ module TypeScript.Services.Formatting {
rulesProvider: RulesProvider,
formattingRequestKind: FormattingRequestKind): TextEditInfo[] {
var walker = new Formatter(textSpan, sourceUnit, indentFirstToken, options, snapshot, rulesProvider, formattingRequestKind);
visitNodeOrToken(walker, sourceUnit);
walker.walk(sourceUnit);
return walker.edits();
}
@@ -78,7 +78,7 @@ module TypeScript.Services.Formatting {
}
// Push the token
var currentTokenSpan = new TokenSpan(token.kind(), position, width(token));
var currentTokenSpan = new TokenSpan(token.kind, position, width(token));
if (!this.parent().hasSkippedOrMissingTokenChild()) {
if (this.previousTokenSpan) {
// Note that formatPair calls TrimWhitespaceInLineRange in between the 2 tokens
@@ -96,11 +96,6 @@ module TypeScript.Services.Formatting {
}
this.previousTokenParent = this.parent().clone(this.indentationNodeContextPool());
position += width(token);
// Extract any trailing comments
if (token.trailingTriviaWidth() !== 0) {
this.processTrivia(token.trailingTrivia(), position);
}
}
private processTrivia(triviaList: ISyntaxTriviaList, fullStart: number) {
@@ -110,7 +105,7 @@ module TypeScript.Services.Formatting {
var trivia = triviaList.syntaxTriviaAt(i);
// For a comment, format it like it is a token. For skipped text, eat it up as a token, but skip the formatting
if (trivia.isComment() || trivia.isSkippedToken()) {
var currentTokenSpan = new TokenSpan(trivia.kind(), position, trivia.fullWidth());
var currentTokenSpan = new TokenSpan(trivia.kind, position, trivia.fullWidth());
if (this.textSpan().containsTextSpan(currentTokenSpan)) {
if (trivia.isComment() && this.previousTokenSpan) {
// Note that formatPair calls TrimWhitespaceInLineRange in between the 2 tokens
+1 -1
View File
@@ -109,7 +109,7 @@ module TypeScript.Services.Formatting {
var block = <BlockSyntax>node.node();
// Now check if they are on the same line
return this.snapshot.getLineNumberFromPosition(end(block.openBraceToken)) ===
return this.snapshot.getLineNumberFromPosition(fullEnd(block.openBraceToken)) ===
this.snapshot.getLineNumberFromPosition(start(block.closeBraceToken));
}
}
+6 -6
View File
@@ -42,12 +42,12 @@ module TypeScript.Services.Formatting {
var sourceUnit = this.syntaxTree.sourceUnit();
var semicolonPositionedToken = findToken(sourceUnit, caretPosition - 1);
if (semicolonPositionedToken.kind() === SyntaxKind.SemicolonToken) {
if (semicolonPositionedToken.kind === SyntaxKind.SemicolonToken) {
// Find the outer most parent that this semicolon terminates
var current: ISyntaxElement = semicolonPositionedToken;
while (current.parent !== null &&
end(current.parent) === end(semicolonPositionedToken) &&
current.parent.kind() !== SyntaxKind.List) {
fullEnd(current.parent) === fullEnd(semicolonPositionedToken) &&
current.parent.kind !== SyntaxKind.List) {
current = current.parent;
}
@@ -65,12 +65,12 @@ module TypeScript.Services.Formatting {
var sourceUnit = this.syntaxTree.sourceUnit();
var closeBracePositionedToken = findToken(sourceUnit, caretPosition - 1);
if (closeBracePositionedToken.kind() === SyntaxKind.CloseBraceToken) {
if (closeBracePositionedToken.kind === SyntaxKind.CloseBraceToken) {
// Find the outer most parent that this closing brace terminates
var current: ISyntaxElement = closeBracePositionedToken;
while (current.parent !== null &&
end(current.parent) === end(closeBracePositionedToken) &&
current.parent.kind() !== SyntaxKind.List) {
fullEnd(current.parent) === fullEnd(closeBracePositionedToken) &&
current.parent.kind !== SyntaxKind.List) {
current = current.parent;
}
@@ -66,7 +66,7 @@ module TypeScript.Services.Formatting {
}
public kind(): SyntaxKind {
return this._node.kind();
return this._node.kind;
}
public hasSkippedOrMissingTokenChild(): boolean {
@@ -16,7 +16,7 @@
///<reference path='formatting.ts' />
module TypeScript.Services.Formatting {
export class IndentationTrackingWalker extends SyntaxWalker {
export class IndentationTrackingWalker {
private _position: number = 0;
private _parent: IndentationNodeContext = null;
private _textSpan: TextSpan;
@@ -26,8 +26,6 @@ module TypeScript.Services.Formatting {
private _text: ISimpleText;
constructor(textSpan: TextSpan, sourceUnit: SourceUnitSyntax, snapshot: ITextSnapshot, indentFirstToken: boolean, public options: FormattingOptions) {
super();
// Create a pool object to manage context nodes while walking the tree
this._indentationNodeContextPool = new IndentationNodeContextPool();
@@ -92,15 +90,37 @@ module TypeScript.Services.Formatting {
this.visitTokenInSpan(token);
// Only track new lines on tokens within the range. Make sure to check that the last trivia is a newline, and not just one of the trivia
var trivia = token.trailingTrivia();
this._lastTriviaWasNewLine = trivia.hasNewLine() && trivia.syntaxTriviaAt(trivia.count() - 1).kind() == SyntaxKind.NewLineTrivia;
var _nextToken = nextToken(token);
if (_nextToken && _nextToken.hasLeadingTrivia()) {
var trivia = _nextToken.leadingTrivia();
this._lastTriviaWasNewLine = trivia.hasNewLine();
}
else {
this._lastTriviaWasNewLine = false;
}
}
// Update the position
this._position += token.fullWidth();
}
public visitNode(node: ISyntaxNode): void {
public walk(element: ISyntaxElement) {
if (element) {
if (isToken(element)) {
this.visitToken(<ISyntaxToken>element);
}
else if (element.kind === SyntaxKind.List) {
for (var i = 0, n = childCount(element); i < n; i++) {
this.walk(childAt(element, i));
}
}
else {
this.visitNode(<ISyntaxNode>element);
}
}
}
private visitNode(node: ISyntaxNode): void {
var nodeSpan = new TextSpan(this._position, fullWidth(node));
if (nodeSpan.intersectsWithTextSpan(this._textSpan)) {
@@ -112,7 +132,9 @@ module TypeScript.Services.Formatting {
this._parent = this._indentationNodeContextPool.getNode(currentParent, node, this._position, indentation.indentationAmount, indentation.indentationAmountDelta);
// Visit node
visitNodeOrToken(this, node);
for (var i = 0, n = childCount(node); i < n; i++) {
this.walk(childAt(node, i));
}
// Reset state
this._indentationNodeContextPool.releaseNode(this._parent);
@@ -132,9 +154,9 @@ module TypeScript.Services.Formatting {
// }
// Also in a do-while statement, the while should be indented like the parent.
if (firstToken(this._parent.node()) === token ||
token.kind() === SyntaxKind.OpenBraceToken || token.kind() === SyntaxKind.CloseBraceToken ||
token.kind() === SyntaxKind.OpenBracketToken || token.kind() === SyntaxKind.CloseBracketToken ||
(token.kind() === SyntaxKind.WhileKeyword && this._parent.node().kind() == SyntaxKind.DoStatement)) {
token.kind === SyntaxKind.OpenBraceToken || token.kind === SyntaxKind.CloseBraceToken ||
token.kind === SyntaxKind.OpenBracketToken || token.kind === SyntaxKind.CloseBracketToken ||
(token.kind === SyntaxKind.WhileKeyword && this._parent.node().kind == SyntaxKind.DoStatement)) {
return this._parent.indentationAmount();
}
@@ -145,7 +167,7 @@ module TypeScript.Services.Formatting {
// If this is token terminating an indentation scope, leading comments should be indented to follow the children
// indentation level and not the node
if (token.kind() === SyntaxKind.CloseBraceToken || token.kind() === SyntaxKind.CloseBracketToken) {
if (token.kind === SyntaxKind.CloseBraceToken || token.kind === SyntaxKind.CloseBracketToken) {
return (this._parent.indentationAmount() + this._parent.childIndentationAmountDelta());
}
return this._parent.indentationAmount();
@@ -197,7 +219,7 @@ module TypeScript.Services.Formatting {
var indentationAmountDelta: number;
var parentNode = parent.node();
switch (node.kind()) {
switch (node.kind) {
default:
// General case
// This node should follow the child indentation set by its parent
@@ -337,7 +359,7 @@ module TypeScript.Services.Formatting {
private forceRecomputeIndentationOfParent(tokenStart: number, newLineAdded: boolean /*as opposed to removed*/): void {
var parent = this._parent;
if (parent.fullStart() === tokenStart) {
if (start(parent.node()) === tokenStart) {
// Temporarily pop the parent before recomputing
this._parent = parent.parent();
var indentation = this.getNodeIndentation(parent.node(), /* newLineInsertedByFormatting */ newLineAdded);
@@ -66,14 +66,29 @@ module TypeScript.Services.Formatting {
// Process any leading trivia if any
var triviaList = token.leadingTrivia();
if (triviaList) {
var seenNewLine = position === 0;
for (var i = 0, length = triviaList.count(); i < length; i++, position += trivia.fullWidth()) {
var trivia = triviaList.syntaxTriviaAt(i);
// Skip all trivia up to the first newline we see. We consider this trivia to
// 'belong' to the previous token.
if (!seenNewLine) {
if (trivia.kind !== SyntaxKind.NewLineTrivia) {
continue;
}
else {
seenNewLine = true;
continue;
}
}
// Skip this trivia if it is not in the span
if (!this.textSpan().containsTextSpan(new TextSpan(position, trivia.fullWidth()))) {
continue;
}
switch (trivia.kind()) {
switch (trivia.kind) {
case SyntaxKind.MultiLineCommentTrivia:
// We will only indent the first line of the multiline comment if we were planning to indent the next trivia. However,
// subsequent lines will always be indented
@@ -119,7 +134,7 @@ module TypeScript.Services.Formatting {
}
if (token.kind() !== SyntaxKind.EndOfFileToken && indentNextTokenOrTrivia) {
if (token.kind !== SyntaxKind.EndOfFileToken && indentNextTokenOrTrivia) {
// If the last trivia item was a new line, or no trivia items were encounterd record the
// indentation edit at the token position
if (indentationString.length > 0) {
+1 -35
View File
@@ -448,42 +448,8 @@ module TypeScript.Services.Formatting {
switch (context.contextNode.kind()) {
// binary expressions
case SyntaxKind.AssignmentExpression:
case SyntaxKind.AddAssignmentExpression:
case SyntaxKind.SubtractAssignmentExpression:
case SyntaxKind.MultiplyAssignmentExpression:
case SyntaxKind.DivideAssignmentExpression:
case SyntaxKind.ModuloAssignmentExpression:
case SyntaxKind.AndAssignmentExpression:
case SyntaxKind.ExclusiveOrAssignmentExpression:
case SyntaxKind.OrAssignmentExpression:
case SyntaxKind.LeftShiftAssignmentExpression:
case SyntaxKind.SignedRightShiftAssignmentExpression:
case SyntaxKind.UnsignedRightShiftAssignmentExpression:
case SyntaxKind.BinaryExpression:
case SyntaxKind.ConditionalExpression:
case SyntaxKind.LogicalOrExpression:
case SyntaxKind.LogicalAndExpression:
case SyntaxKind.BitwiseOrExpression:
case SyntaxKind.BitwiseExclusiveOrExpression:
case SyntaxKind.BitwiseAndExpression:
case SyntaxKind.EqualsWithTypeConversionExpression:
case SyntaxKind.NotEqualsWithTypeConversionExpression:
case SyntaxKind.EqualsExpression:
case SyntaxKind.NotEqualsExpression:
case SyntaxKind.LessThanExpression:
case SyntaxKind.GreaterThanExpression:
case SyntaxKind.LessThanOrEqualExpression:
case SyntaxKind.GreaterThanOrEqualExpression:
case SyntaxKind.InstanceOfExpression:
case SyntaxKind.InExpression:
case SyntaxKind.LeftShiftExpression:
case SyntaxKind.SignedRightShiftExpression:
case SyntaxKind.UnsignedRightShiftExpression:
case SyntaxKind.MultiplyExpression:
case SyntaxKind.DivideExpression:
case SyntaxKind.ModuloExpression:
case SyntaxKind.AddExpression:
case SyntaxKind.SubtractExpression:
return true;
// equal in import a = module('a');
+2 -2
View File
@@ -175,7 +175,7 @@ module ts.formatting {
function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: Node, childStartLine: number, sourceFile: SourceFile): boolean {
if (parent.kind === SyntaxKind.IfStatement && (<IfStatement>parent).elseStatement === child) {
var elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile);
Debug.assert(elseKeyword);
Debug.assert(elseKeyword !== undefined);
var elseKeywordStartLine = getStartLineAndCharacterForNode(elseKeyword, sourceFile).line;
return elseKeywordStartLine === childStartLine;
@@ -361,7 +361,7 @@ module ts.formatting {
case SyntaxKind.FunctionExpression:
case SyntaxKind.Method:
case SyntaxKind.ArrowFunction:
return !(<FunctionDeclaration>n).body || isCompletedNode((<FunctionDeclaration>n).body, sourceFile);
return !(<FunctionLikeDeclaration>n).body || isCompletedNode((<FunctionLikeDeclaration>n).body, sourceFile);
case SyntaxKind.ModuleDeclaration:
return (<ModuleDeclaration>n).body && isCompletedNode((<ModuleDeclaration>n).body, sourceFile);
case SyntaxKind.IfStatement:
-105
View File
@@ -1,110 +1,5 @@
module TypeScript.Indentation {
export function columnForEndOfTokenAtPosition(syntaxTree: SyntaxTree, position: number, options: FormattingOptions): number {
var token = findToken(syntaxTree.sourceUnit(), position);
return columnForStartOfTokenAtPosition(syntaxTree, position, options) + width(token);
}
export function columnForStartOfTokenAtPosition(syntaxTree: SyntaxTree, position: number, options: FormattingOptions): number {
var token = findToken(syntaxTree.sourceUnit(), position);
// Walk backward from this token until we find the first token in the line. For each token
// we see (that is not the first tokem in line), push the entirety of the text into the text
// array. Then, for the first token, add its text (without its leading trivia) to the text
// array. i.e. if we have:
//
// var foo = a => bar();
//
// And we want the column for the start of 'bar', then we'll add the underlinded portions to
// the text array:
//
// var foo = a => bar();
// _
// __
// __
// ____
// ____
var firstTokenInLine = Syntax.firstTokenInLineContainingPosition(syntaxTree, token.fullStart());
var leadingTextInReverse: string[] = [];
var current = token;
while (current !== firstTokenInLine) {
current = previousToken(current);
if (current === firstTokenInLine) {
// We're at the first token in teh line.
// We don't want the leading trivia for this token. That will be taken care of in
// columnForFirstNonWhitespaceCharacterInLine. So just push the trailing trivia
// and then the token text.
leadingTextInReverse.push(current.trailingTrivia().fullText());
leadingTextInReverse.push(current.text());
}
else {
// We're at an intermediate token on the line. Just push all its text into the array.
leadingTextInReverse.push(current.fullText());
}
}
// Now, add all trivia to the start of the line on the first token in the list.
collectLeadingTriviaTextToStartOfLine(firstTokenInLine, leadingTextInReverse);
return columnForLeadingTextInReverse(leadingTextInReverse, options);
}
export function columnForStartOfFirstTokenInLineContainingPosition(syntaxTree: SyntaxTree, position: number, options: FormattingOptions): number {
// Walk backward through the tokens until we find the first one on the line.
var firstTokenInLine = Syntax.firstTokenInLineContainingPosition(syntaxTree, position);
var leadingTextInReverse: string[] = [];
// Now, add all trivia to the start of the line on the first token in the list.
collectLeadingTriviaTextToStartOfLine(firstTokenInLine, leadingTextInReverse);
return columnForLeadingTextInReverse(leadingTextInReverse, options);
}
// Collect all the trivia that precedes this token. Stopping when we hit a newline trivia
// or a multiline comment that spans multiple lines. This is meant to be called on the first
// token in a line.
function collectLeadingTriviaTextToStartOfLine(firstTokenInLine: ISyntaxToken,
leadingTextInReverse: string[]) {
var leadingTrivia = firstTokenInLine.leadingTrivia();
for (var i = leadingTrivia.count() - 1; i >= 0; i--) {
var trivia = leadingTrivia.syntaxTriviaAt(i);
if (trivia.kind() === SyntaxKind.NewLineTrivia) {
break;
}
if (trivia.kind() === SyntaxKind.MultiLineCommentTrivia) {
var lineSegments = Syntax.splitMultiLineCommentTriviaIntoMultipleLines(trivia);
leadingTextInReverse.push(ArrayUtilities.last(lineSegments));
if (lineSegments.length > 0) {
// This multiline comment actually spanned multiple lines. So we're done.
break;
}
// It was only on a single line, so keep on going.
}
leadingTextInReverse.push(trivia.fullText());
}
}
function columnForLeadingTextInReverse(leadingTextInReverse: string[],
options: FormattingOptions): number {
var column = 0;
// walk backwards. This means we're actually walking forward from column 0 to the start of
// the token.
for (var i = leadingTextInReverse.length - 1; i >= 0; i--) {
var text = leadingTextInReverse[i];
column = columnForPositionInStringWorker(text, text.length, column, options);
}
return column;
}
// Returns the column that this input string ends at (assuming it starts at column 0).
export function columnForPositionInString(input: string, position: number, options: FormattingOptions): number {
return columnForPositionInStringWorker(input, position, 0, options);
+10 -6
View File
@@ -73,13 +73,14 @@ module ts.NavigationBar {
function sortNodes(nodes: Node[]): Node[] {
return nodes.slice(0).sort((n1: Declaration, n2: Declaration) => {
if (n1.name && n2.name) {
return n1.name.text.localeCompare(n2.name.text);
// TODO(jfreeman): How do we sort declarations with computed names?
return (<Identifier>n1.name).text.localeCompare((<Identifier>n2.name).text);
}
else if (n1.name) {
return 1;
}
else if (n2.name) {
-1;
return -1;
}
else {
return n1.kind - n2.kind;
@@ -106,7 +107,7 @@ module ts.NavigationBar {
break;
case SyntaxKind.FunctionDeclaration:
var functionDeclaration = <FunctionDeclaration>node;
var functionDeclaration = <FunctionLikeDeclaration>node;
if (isTopLevelFunctionDeclaration(functionDeclaration)) {
topLevelNodes.push(node);
addTopLevelNodes((<Block>functionDeclaration.body).statements, topLevelNodes);
@@ -116,11 +117,12 @@ module ts.NavigationBar {
}
}
function isTopLevelFunctionDeclaration(functionDeclaration: FunctionDeclaration) {
function isTopLevelFunctionDeclaration(functionDeclaration: FunctionLikeDeclaration) {
if (functionDeclaration.kind === SyntaxKind.FunctionDeclaration) {
// A function declaration is 'top level' if it contains any function declarations
// within it.
if (functionDeclaration.body && functionDeclaration.body.kind === SyntaxKind.FunctionBlock) {
// Proper function declarations can only have identifier names
if (forEach((<Block>functionDeclaration.body).statements,
s => s.kind === SyntaxKind.FunctionDeclaration && !isEmpty((<FunctionDeclaration>s).name.text))) {
@@ -230,7 +232,7 @@ module ts.NavigationBar {
return createItem(node, getTextOfNode((<PropertyDeclaration>node).name), ts.ScriptElementKind.memberVariableElement);
case SyntaxKind.FunctionDeclaration:
return createItem(node, getTextOfNode((<FunctionDeclaration>node).name), ts.ScriptElementKind.functionElement);
return createItem(node, getTextOfNode((<FunctionLikeDeclaration>node).name), ts.ScriptElementKind.functionElement);
case SyntaxKind.VariableDeclaration:
if (node.flags & NodeFlags.Const) {
@@ -371,8 +373,10 @@ module ts.NavigationBar {
});
// Add the constructor parameters in as children of the class (for property parameters).
// Note that *all* parameters will be added to the nodes array, but parameters that
// are not properties will be filtered out later by createChildItem.
var nodes: Node[] = constructor
? constructor.parameters.concat(node.members)
? node.members.concat(constructor.parameters)
: node.members;
var childItems = getItemsWorker(sortNodes(nodes), createChildItem);
@@ -13,7 +13,6 @@ module TypeScript {
Automatic_semicolon_insertion_not_allowed: "Automatic semicolon insertion not allowed.",
Unexpected_token_0_expected: "Unexpected token; '{0}' expected.",
Trailing_comma_not_allowed: "Trailing comma not allowed.",
AsteriskSlash_expected: "'*/' expected.",
public_or_private_modifier_must_precede_static: "'public' or 'private' modifier must precede 'static'.",
Unexpected_token: "Unexpected token.",
Catch_clause_parameter_cannot_have_a_type_annotation: "Catch clause parameter cannot have a type annotation.",
@@ -95,6 +94,8 @@ module TypeScript {
return_statement_must_be_contained_within_a_function_body: "'return' statement must be contained within a function body.",
Expression_expected: "Expression expected.",
Type_expected: "Type expected.",
Template_literal_cannot_be_used_as_an_element_name: "Template literal cannot be used as an element name.",
Computed_property_names_cannot_be_used_here: "Computed property names cannot be used here.",
Duplicate_identifier_0: "Duplicate identifier '{0}'.",
The_name_0_does_not_exist_in_the_current_scope: "The name '{0}' does not exist in the current scope.",
The_name_0_does_not_refer_to_a_value: "The name '{0}' does not refer to a value.",
@@ -96,6 +96,8 @@ module TypeScript {
"'return' statement must be contained within a function body.": { "code": 1108, "category": DiagnosticCategory.Error },
"Expression expected.": { "code": 1109, "category": DiagnosticCategory.Error },
"Type expected.": { "code": 1110, "category": DiagnosticCategory.Error },
"Template literal cannot be used as an element name.": { "code": 1111, "category": DiagnosticCategory.Error },
"Computed property names cannot be used here.": { "code": 1112, "category": DiagnosticCategory.Error },
"Duplicate identifier '{0}'.": { "code": 2000, "category": DiagnosticCategory.Error },
"The name '{0}' does not exist in the current scope.": { "code": 2001, "category": DiagnosticCategory.Error },
"The name '{0}' does not refer to a value.": { "code": 2002, "category": DiagnosticCategory.Error },
@@ -47,10 +47,6 @@
"category": "Error",
"code": 1009
},
"'*/' expected.": {
"category": "Error",
"code": 1010
},
"'public' or 'private' modifier must precede 'static'.": {
"category": "Error",
"code": 1011
@@ -375,6 +371,14 @@
"category": "Error",
"code": 1110
},
"Template literal cannot be used as an element name.": {
"category": "Error",
"code": 1111
},
"Computed property names cannot be used here.": {
"category": "Error",
"code": 1112
},
"Duplicate identifier '{0}'.": {
"category": "Error",
"code": 2000
+245 -97
View File
@@ -76,6 +76,12 @@ module ts {
update(scriptSnapshot: TypeScript.IScriptSnapshot, version: string, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): SourceFile;
}
export interface PreProcessedFileInfo {
referencedFiles: FileReference[];
importedFiles: FileReference[];
isLibFile: boolean
}
var scanner: Scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true);
var emptyArray: any[] = [];
@@ -138,7 +144,7 @@ module ts {
while (pos < end) {
var token = scanner.scan();
var textPos = scanner.getTextPos();
var node = nodes.push(createNode(token, pos, textPos, NodeFlags.Synthetic, this));
nodes.push(createNode(token, pos, textPos, NodeFlags.Synthetic, this));
pos = textPos;
}
return pos;
@@ -346,7 +352,8 @@ module ts {
function isName(pos: number, end: number, sourceFile: SourceFile, name: string) {
return pos + name.length < end &&
sourceFile.text.substr(pos, name.length) === name &&
isWhiteSpace(sourceFile.text.charCodeAt(pos + name.length));
(isWhiteSpace(sourceFile.text.charCodeAt(pos + name.length)) ||
isLineBreak(sourceFile.text.charCodeAt(pos + name.length)));
}
function isParamTag(pos: number, end: number, sourceFile: SourceFile) {
@@ -354,9 +361,16 @@ module ts {
return isName(pos, end, sourceFile, paramTag);
}
function pushDocCommentLineText(docComments: SymbolDisplayPart[], text: string, blankLineCount: number) {
// Add the empty lines in between texts
while (blankLineCount--) docComments.push(textPart(""));
docComments.push(textPart(text));
}
function getCleanedJsDocComment(pos: number, end: number, sourceFile: SourceFile) {
var spacesToRemoveAfterAsterisk: number;
var docComments: SymbolDisplayPart[] = [];
var blankLineCount = 0;
var isInParamTag = false;
while (pos < end) {
@@ -405,7 +419,12 @@ module ts {
// Continue with next line
pos = consumeLineBreaks(pos, end, sourceFile);
if (docCommentTextOfLine) {
docComments.push(textPart(docCommentTextOfLine));
pushDocCommentLineText(docComments, docCommentTextOfLine, blankLineCount);
blankLineCount = 0;
}
else if (!isInParamTag && docComments.length) {
// This is blank line when there is text already parsed
blankLineCount++;
}
}
@@ -417,6 +436,8 @@ module ts {
var paramDocComments: SymbolDisplayPart[] = [];
while (pos < end) {
if (isParamTag(pos, end, sourceFile)) {
var blankLineCount = 0;
var recordedParamTag = false;
// Consume leading spaces
pos = consumeWhiteSpaces(pos + paramTag.length);
if (pos >= end) {
@@ -478,8 +499,13 @@ module ts {
// at line break, set this comment line text and go to next line
if (isLineBreak(ch)) {
if (paramHelpString) {
paramDocComments.push(textPart(paramHelpString));
pushDocCommentLineText(paramDocComments, paramHelpString, blankLineCount);
paramHelpString = "";
blankLineCount = 0;
recordedParamTag = true;
}
else if (recordedParamTag) {
blankLineCount++;
}
// Get the pos after cleaning start of the line
@@ -500,7 +526,7 @@ module ts {
// If there is param help text, add it top the doc comments
if (paramHelpString) {
paramDocComments.push(textPart(paramHelpString));
pushDocCommentLineText(paramDocComments, paramHelpString, blankLineCount);
}
paramHelpStringMargin = undefined;
}
@@ -628,7 +654,7 @@ module ts {
if (this.documentationComment === undefined) {
this.documentationComment = this.declaration ? getJsDocCommentsFromDeclarations(
[this.declaration],
this.declaration.name ? this.declaration.name.text : "",
/*name*/ undefined,
/*canUseParsedParamTagComments*/ false) : [];
}
@@ -636,8 +662,6 @@ module ts {
}
}
var incrementalParse: IncrementalParse = TypeScript.IncrementalParser.parse;
class SourceFileObject extends NodeObject implements SourceFile {
public filename: string;
public text: string;
@@ -674,7 +698,7 @@ module ts {
switch (node.kind) {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.Method:
var functionDeclaration = <FunctionDeclaration>node;
var functionDeclaration = <FunctionLikeDeclaration>node;
if (functionDeclaration.name && functionDeclaration.name.kind !== SyntaxKind.Missing) {
var lastDeclaration = namedDeclarations.length > 0 ?
@@ -685,7 +709,7 @@ module ts {
if (lastDeclaration && functionDeclaration.symbol === lastDeclaration.symbol) {
// Overwrite the last declaration if it was an overload
// and this one is an implementation.
if (functionDeclaration.body && !(<FunctionDeclaration>lastDeclaration).body) {
if (functionDeclaration.body && !(<FunctionLikeDeclaration>lastDeclaration).body) {
namedDeclarations[namedDeclarations.length - 1] = functionDeclaration;
}
}
@@ -737,10 +761,6 @@ module ts {
return this.namedDeclarations;
}
private isDeclareFile(): boolean {
return TypeScript.isDTSFile(this.filename);
}
public update(scriptSnapshot: TypeScript.IScriptSnapshot, version: string, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): SourceFile {
if (textChangeRange && Debug.shouldAssert(AssertionLevel.Normal)) {
var oldText = this.scriptSnapshot;
@@ -1065,7 +1085,7 @@ module ts {
emitOutputStatus: EmitReturnStatus;
}
export enum OutputFileType {
export const enum OutputFileType {
JavaScript,
SourceMap,
Declaration
@@ -1077,7 +1097,7 @@ module ts {
text: string;
}
export enum EndOfLineState {
export const enum EndOfLineState {
Start,
InMultiLineCommentTrivia,
InSingleQuoteStringLiteral,
@@ -1286,7 +1306,7 @@ module ts {
return "";
}
interface DisplayPartsSymbolWriter extends SymbolWriter {
export interface DisplayPartsSymbolWriter extends SymbolWriter {
displayParts(): SymbolDisplayPart[];
}
@@ -1509,7 +1529,7 @@ module ts {
var filenames = host.getScriptFileNames();
for (var i = 0, n = filenames.length; i < n; i++) {
var filename = filenames[i];
this.filenameToEntry[TypeScript.switchToForwardSlashes(filename)] = {
this.filenameToEntry[normalizeSlashes(filename)] = {
filename: filename,
version: host.getScriptVersion(filename),
isOpen: host.getScriptIsOpen(filename)
@@ -1524,7 +1544,7 @@ module ts {
}
public getEntry(filename: string): HostFileInformation {
filename = TypeScript.switchToForwardSlashes(filename);
filename = normalizeSlashes(filename);
return lookUp(this.filenameToEntry, filename);
}
@@ -1639,7 +1659,7 @@ module ts {
}
if (syntaxTree !== null) {
Debug.assert(sourceFile);
Debug.assert(sourceFile !== undefined);
// All done, ensure state is up to date
this.currentFileVersion = version;
this.currentFilename = filename;
@@ -1780,7 +1800,7 @@ module ts {
var buckets: Map<Map<DocumentRegistryEntry>> = {};
function getKeyFromCompilationSettings(settings: CompilerOptions): string {
return "_" + ScriptTarget[settings.target]; // + "|" + settings.propagateEnumConstantoString()
return "_" + settings.target; // + "|" + settings.propagateEnumConstantoString()
}
function getBucketForCompilationSettings(settings: CompilerOptions, createIfMissing: boolean): Map<DocumentRegistryEntry> {
@@ -1847,9 +1867,9 @@ module ts {
): SourceFile {
var bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ false);
Debug.assert(bucket);
Debug.assert(bucket !== undefined);
var entry = lookUp(bucket, filename);
Debug.assert(entry);
Debug.assert(entry !== undefined);
if (entry.sourceFile.isOpen === isOpen && entry.sourceFile.version === version) {
return entry.sourceFile;
@@ -1861,7 +1881,7 @@ module ts {
function releaseDocument(filename: string, compilationSettings: CompilerOptions): void {
var bucket = getBucketForCompilationSettings(compilationSettings, false);
Debug.assert(bucket);
Debug.assert(bucket !== undefined);
var entry = lookUp(bucket, filename);
entry.refCount--;
@@ -1880,6 +1900,68 @@ module ts {
};
}
export function preProcessFile(sourceText: string, readImportFiles = true): PreProcessedFileInfo {
var referencedFiles: FileReference[] = [];
var importedFiles: FileReference[] = [];
var isNoDefaultLib = false;
function processTripleSlashDirectives(): void {
var commentRanges = getLeadingCommentRanges(sourceText, 0);
forEach(commentRanges, commentRange => {
var comment = sourceText.substring(commentRange.pos, commentRange.end);
var referencePathMatchResult = getFileReferenceFromReferencePath(comment, commentRange);
if (referencePathMatchResult) {
isNoDefaultLib = referencePathMatchResult.isNoDefaultLib;
var fileReference = referencePathMatchResult.fileReference;
if (fileReference) {
referencedFiles.push(fileReference);
}
}
});
}
function processImport(): void {
scanner.setText(sourceText);
var token = scanner.scan();
// Look for:
// import foo = module("foo");
while (token !== SyntaxKind.EndOfFileToken) {
if (token === SyntaxKind.ImportKeyword) {
token = scanner.scan();
if (token === SyntaxKind.Identifier) {
token = scanner.scan();
if (token === SyntaxKind.EqualsToken) {
token = scanner.scan();
if (token === SyntaxKind.RequireKeyword) {
token = scanner.scan();
if (token === SyntaxKind.OpenParenToken) {
token = scanner.scan();
if (token === SyntaxKind.StringLiteral) {
var importPath = scanner.getTokenValue();
var pos = scanner.getTokenPos();
importedFiles.push({
filename: importPath,
pos: pos,
end: pos + importPath.length
});
}
}
}
}
}
}
token = scanner.scan();
}
scanner.setText(undefined);
}
if (readImportFiles) {
processImport();
}
processTripleSlashDirectives();
return { referencedFiles: referencedFiles, importedFiles: importedFiles, isLibFile: isNoDefaultLib };
}
/// Helpers
export function getNodeModifiers(node: Node): string {
var flags = node.flags;
@@ -1963,7 +2045,7 @@ module ts {
function isNameOfFunctionDeclaration(node: Node): boolean {
return node.kind === SyntaxKind.Identifier &&
isAnyFunction(node.parent) && (<FunctionDeclaration>node.parent).name === node;
isAnyFunction(node.parent) && (<FunctionLikeDeclaration>node.parent).name === node;
}
/** Returns true if node is a name of an object literal property, e.g. "a" in x = { "a": 1 } */
@@ -2028,7 +2110,7 @@ module ts {
}
}
enum SemanticMeaning {
const enum SemanticMeaning {
None = 0x0,
Value = 0x1,
Type = 0x2,
@@ -2036,7 +2118,7 @@ module ts {
All = Value | Type | Namespace
}
enum BreakContinueSearchType {
const enum BreakContinueSearchType {
None = 0x0,
Unlabeled = 0x1,
Labeled = 0x2,
@@ -2240,7 +2322,7 @@ module ts {
function getSyntacticDiagnostics(filename: string) {
synchronizeHostData();
filename = TypeScript.switchToForwardSlashes(filename);
filename = normalizeSlashes(filename);
return program.getDiagnostics(getSourceFile(filename).getSourceFile());
}
@@ -2252,7 +2334,7 @@ module ts {
function getSemanticDiagnostics(filename: string) {
synchronizeHostData();
filename = TypeScript.switchToForwardSlashes(filename)
filename = normalizeSlashes(filename)
var compilerOptions = program.getCompilerOptions();
var checker = getFullTypeCheckChecker();
var targetSourceFile = getSourceFile(filename);
@@ -2310,7 +2392,7 @@ module ts {
return undefined;
}
function createCompletionEntry(symbol: Symbol, typeChecker: TypeChecker): CompletionEntry {
function createCompletionEntry(symbol: Symbol, typeChecker: TypeChecker, location: Node): CompletionEntry {
// Try to get a valid display name for this symbol, if we could not find one, then ignore it.
// We would like to only show things that can be added after a dot, so for instance numeric properties can
// not be accessed with a dot (a.1 <- invalid)
@@ -2325,7 +2407,7 @@ module ts {
// We COULD also just do what 'getSymbolModifiers' does, which is to use the first declaration.
return {
name: displayName,
kind: getSymbolKind(symbol, typeChecker),
kind: getSymbolKind(symbol, typeChecker, location),
kindModifiers: getSymbolModifiers(symbol)
};
}
@@ -2333,26 +2415,37 @@ module ts {
function getCompletionsAtPosition(filename: string, position: number, isMemberCompletion: boolean) {
synchronizeHostData();
filename = TypeScript.switchToForwardSlashes(filename);
filename = normalizeSlashes(filename);
var syntacticStart = new Date().getTime();
var sourceFile = getSourceFile(filename);
var start = new Date().getTime();
var currentToken = getTokenAtPosition(sourceFile, position);
host.log("getCompletionsAtPosition: Get current token: " + (new Date().getTime() - start));
var start = new Date().getTime();
// Completion not allowed inside comments, bail out if this is the case
if (isInsideComment(sourceFile, currentToken, position)) {
var insideComment = isInsideComment(sourceFile, currentToken, position);
host.log("getCompletionsAtPosition: Is inside comment: " + (new Date().getTime() - start));
if (insideComment) {
host.log("Returning an empty list because completion was inside a comment.");
return undefined;
}
// The decision to provide completion depends on the previous token, so find it
// Note: previousToken can be undefined if we are the beginning of the file
var start = new Date().getTime();
var previousToken = findPrecedingToken(position, sourceFile);
host.log("getCompletionsAtPosition: Get previous token 1: " + (new Date().getTime() - start));
// The caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS|
// Skip this partial identifier to the previous token
if (previousToken && position <= previousToken.end && previousToken.kind === SyntaxKind.Identifier) {
var start = new Date().getTime();
previousToken = findPrecedingToken(previousToken.pos, sourceFile);
host.log("getCompletionsAtPosition: Get previous token 2: " + (new Date().getTime() - start));
}
// Check if this is a valid completion location
@@ -2383,8 +2476,11 @@ module ts {
symbols: {},
typeChecker: typeInfoResolver
};
host.log("getCompletionsAtPosition: Syntactic work: " + (new Date().getTime() - syntacticStart));
var location = getTouchingPropertyName(sourceFile, position);
// Populate the completion list
var semanticStart = new Date().getTime();
if (isRightOfDot) {
// Right of dot member completion list
var symbols: Symbol[] = [];
@@ -2454,6 +2550,7 @@ module ts {
if (!isMemberCompletion) {
Array.prototype.push.apply(activeCompletionSession.entries, keywordCompletions);
}
host.log("getCompletionsAtPosition: Semantic work: " + (new Date().getTime() - semanticStart));
return {
isMemberCompletion: isMemberCompletion,
@@ -2461,41 +2558,69 @@ module ts {
};
function getCompletionEntriesFromSymbols(symbols: Symbol[], session: CompletionSession): void {
var start = new Date().getTime();
forEach(symbols, symbol => {
var entry = createCompletionEntry(symbol, session.typeChecker);
var entry = createCompletionEntry(symbol, session.typeChecker, location);
if (entry && !lookUp(session.symbols, entry.name)) {
session.entries.push(entry);
session.symbols[entry.name] = symbol;
}
});
host.log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (new Date().getTime() - start));
}
function isCompletionListBlocker(previousToken: Node): boolean {
return isInStringOrRegularExpressionLiteral(previousToken) ||
var start = new Date().getTime();
var result = isInStringOrRegularExpressionOrTemplateLiteral(previousToken) ||
isIdentifierDefinitionLocation(previousToken) ||
isRightOfIllegalDot(previousToken);
host.log("getCompletionsAtPosition: isCompletionListBlocker: " + (new Date().getTime() - start));
return result;
}
function isInStringOrRegularExpressionLiteral(previousToken: Node): boolean {
if (previousToken.kind === SyntaxKind.StringLiteral) {
function isInStringOrRegularExpressionOrTemplateLiteral(previousToken: Node): boolean {
if (previousToken.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(previousToken.kind)) {
// The position has to be either: 1. entirely within the token text, or
// 2. at the end position, and the string literal is not terminated
var start = previousToken.getStart();
var end = previousToken.getEnd();
if (start < position && position < end) {
return true;
}
else if (position === end) {
var width = end - start;
var text = previousToken.getSourceFile().text;
return width <= 1 ||
text.charCodeAt(start) !== text.charCodeAt(end - 1) ||
text.charCodeAt(end - 2) === CharacterCodes.backslash;
// If the token is a single character, or its second-to-last charcter indicates an escape code,
// then we can immediately say that we are in the middle of an unclosed string.
if (width <= 1 || text.charCodeAt(end - 2) === CharacterCodes.backslash) {
return true;
}
// Now check if the last character is a closing character for the token.
switch (previousToken.kind) {
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
return text.charCodeAt(start) !== text.charCodeAt(end - 1);
case SyntaxKind.TemplateHead:
case SyntaxKind.TemplateMiddle:
return text.charCodeAt(end - 1) !== CharacterCodes.openBrace
|| text.charCodeAt(end - 2) !== CharacterCodes.$;
case SyntaxKind.TemplateTail:
return text.charCodeAt(end - 1) !== CharacterCodes.backtick;
}
return false;
}
}
else if (previousToken.kind === SyntaxKind.RegularExpressionLiteral) {
return previousToken.getStart() < position && position < previousToken.getEnd();
}
return false;
}
@@ -2571,6 +2696,7 @@ module ts {
case SyntaxKind.VarKeyword:
case SyntaxKind.GetKeyword:
case SyntaxKind.SetKeyword:
case SyntaxKind.ImportKeyword:
return true;
}
@@ -2616,7 +2742,8 @@ module ts {
return;
}
existingMemberNames[m.name.text] = true;
// TODO(jfreeman): Account for computed property name
existingMemberNames[(<Identifier>m.name).text] = true;
});
var filteredMembers: Symbol[] = [];
@@ -2633,7 +2760,7 @@ module ts {
function getCompletionEntryDetails(filename: string, position: number, entryName: string): CompletionEntryDetails {
// Note: No need to call synchronizeHostData, as we have captured all the data we need
// in the getCompletionsAtPosition earlier
filename = TypeScript.switchToForwardSlashes(filename);
filename = normalizeSlashes(filename);
var sourceFile = getSourceFile(filename);
@@ -2646,14 +2773,13 @@ module ts {
var symbol = lookUp(activeCompletionSession.symbols, entryName);
if (symbol) {
var type = session.typeChecker.getTypeOfSymbol(symbol);
Debug.assert(type, "Could not find type for symbol");
var completionEntry = createCompletionEntry(symbol, session.typeChecker);
var location = getTouchingPropertyName(sourceFile, position);
var completionEntry = createCompletionEntry(symbol, session.typeChecker, location);
// TODO(drosen): Right now we just permit *all* semantic meanings when calling 'getSymbolKind'
// which is permissible given that it is backwards compatible; but really we should consider
// passing the meaning for the node so that we don't report that a suggestion for a value is an interface.
// We COULD also just do what 'getSymbolModifiers' does, which is to use the first declaration.
var location = getTouchingPropertyName(sourceFile, position);
Debug.assert(session.typeChecker.getNarrowedTypeOfSymbol(symbol, location) !== undefined, "Could not find type for symbol");
var displayPartsDocumentationsAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getSourceFile(filename), location, session.typeChecker, location, SemanticMeaning.All);
return {
name: entryName,
@@ -2698,7 +2824,7 @@ module ts {
}
// TODO(drosen): use contextual SemanticMeaning.
function getSymbolKind(symbol: Symbol, typeResolver: TypeChecker): string {
function getSymbolKind(symbol: Symbol, typeResolver: TypeChecker, location?: Node): string {
var flags = symbol.getFlags();
if (flags & SymbolFlags.Class) return ScriptElementKind.classElement;
@@ -2707,7 +2833,7 @@ module ts {
if (flags & SymbolFlags.Interface) return ScriptElementKind.interfaceElement;
if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, typeResolver);
var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, typeResolver, location);
if (result === ScriptElementKind.unknown) {
if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
if (flags & SymbolFlags.EnumMember) return ScriptElementKind.variableElement;
@@ -2717,7 +2843,7 @@ module ts {
return result;
}
function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol: Symbol, flags: SymbolFlags, typeResolver: TypeChecker) {
function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol: Symbol, flags: SymbolFlags, typeResolver: TypeChecker, location: Node) {
if (typeResolver.isUndefinedSymbol(symbol)) {
return ScriptElementKind.variableElement;
}
@@ -2741,15 +2867,24 @@ module ts {
if (flags & SymbolFlags.Property) {
if (flags & SymbolFlags.UnionProperty) {
return forEach(typeInfoResolver.getRootSymbols(symbol), rootSymbol => {
// If union property is result of union of non method (property/accessors/variables), it is labeled as property
var unionPropertyKind = forEach(typeInfoResolver.getRootSymbols(symbol), rootSymbol => {
var rootSymbolFlags = rootSymbol.getFlags();
if (rootSymbolFlags & SymbolFlags.Property) {
if (rootSymbolFlags & (SymbolFlags.PropertyOrAccessor | SymbolFlags.Variable)) {
return ScriptElementKind.memberVariableElement;
}
if (rootSymbolFlags & SymbolFlags.GetAccessor) return ScriptElementKind.memberVariableElement;
if (rootSymbolFlags & SymbolFlags.SetAccessor) return ScriptElementKind.memberVariableElement;
Debug.assert(rootSymbolFlags & SymbolFlags.Method);
}) || ScriptElementKind.memberFunctionElement;
Debug.assert(!!(rootSymbolFlags & SymbolFlags.Method));
});
if (!unionPropertyKind) {
// If this was union of all methods,
//make sure it has call signatures before we can label it as method
var typeOfUnionProperty = typeInfoResolver.getNarrowedTypeOfSymbol(symbol, location);
if (typeOfUnionProperty.getCallSignatures().length) {
return ScriptElementKind.memberFunctionElement;
}
return ScriptElementKind.memberVariableElement;
}
return unionPropertyKind;
}
return ScriptElementKind.memberVariableElement;
}
@@ -2807,7 +2942,7 @@ module ts {
var displayParts: SymbolDisplayPart[] = [];
var documentation: SymbolDisplayPart[];
var symbolFlags = symbol.flags;
var symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, typeResolver);
var symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, typeResolver, location);
var hasAddedSymbolInfo: boolean;
// Class at constructor site need to be shown as constructor apart from property,method, vars
if (symbolKind !== ScriptElementKind.unknown || symbolFlags & SymbolFlags.Class || symbolFlags & SymbolFlags.Import) {
@@ -2816,7 +2951,7 @@ module ts {
symbolKind = ScriptElementKind.memberVariableElement;
}
var type = typeResolver.getTypeOfSymbol(symbol);
var type = typeResolver.getNarrowedTypeOfSymbol(symbol, location);
if (type) {
if (location.parent && location.parent.kind === SyntaxKind.PropertyAccess) {
var right = (<PropertyAccess>location.parent).right;
@@ -2903,7 +3038,7 @@ module ts {
(location.kind === SyntaxKind.ConstructorKeyword && location.parent.kind === SyntaxKind.Constructor)) { // At constructor keyword of constructor declaration
// get the signature from the declaration and write it
var signature: Signature;
var functionDeclaration = <FunctionDeclaration>location.parent;
var functionDeclaration = <FunctionLikeDeclaration>location.parent;
var allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getConstructSignatures() : type.getCallSignatures();
if (!typeResolver.isImplementationOfOverload(functionDeclaration)) {
signature = typeResolver.getSignatureFromDeclaration(functionDeclaration);
@@ -3009,13 +3144,13 @@ module ts {
displayParts.push(keywordPart(SyntaxKind.ImportKeyword));
displayParts.push(spacePart());
addFullSymbolName(symbol);
displayParts.push(spacePart());
displayParts.push(punctuationPart(SyntaxKind.EqualsToken));
displayParts.push(spacePart());
ts.forEach(symbol.declarations, declaration => {
if (declaration.kind === SyntaxKind.ImportDeclaration) {
var importDeclaration = <ImportDeclaration>declaration;
if (importDeclaration.externalModuleName) {
displayParts.push(spacePart());
displayParts.push(punctuationPart(SyntaxKind.EqualsToken));
displayParts.push(spacePart());
displayParts.push(keywordPart(SyntaxKind.RequireKeyword));
displayParts.push(punctuationPart(SyntaxKind.OpenParenToken));
displayParts.push(displayPart(getTextOfNode(importDeclaration.externalModuleName), SymbolDisplayPartKind.stringLiteral));
@@ -3023,7 +3158,12 @@ module ts {
}
else {
var internalAliasSymbol = typeResolver.getSymbolInfo(importDeclaration.entityName);
addFullSymbolName(internalAliasSymbol, enclosingDeclaration);
if (internalAliasSymbol) {
displayParts.push(spacePart());
displayParts.push(punctuationPart(SyntaxKind.EqualsToken));
displayParts.push(spacePart());
addFullSymbolName(internalAliasSymbol, enclosingDeclaration);
}
}
return true;
}
@@ -3062,7 +3202,7 @@ module ts {
}
}
else {
symbolKind = getSymbolKind(symbol, typeResolver);
symbolKind = getSymbolKind(symbol, typeResolver, location);
}
}
@@ -3120,7 +3260,7 @@ module ts {
function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo {
synchronizeHostData();
fileName = TypeScript.switchToForwardSlashes(fileName);
fileName = normalizeSlashes(fileName);
var sourceFile = getSourceFile(fileName);
var node = getTouchingPropertyName(sourceFile, position);
if (!node) {
@@ -3183,7 +3323,7 @@ module ts {
if ((selectConstructors && d.kind === SyntaxKind.Constructor) ||
(!selectConstructors && (d.kind === SyntaxKind.FunctionDeclaration || d.kind === SyntaxKind.Method))) {
declarations.push(d);
if ((<FunctionDeclaration>d).body) definition = d;
if ((<FunctionLikeDeclaration>d).body) definition = d;
}
});
@@ -3222,7 +3362,7 @@ module ts {
synchronizeHostData();
filename = TypeScript.switchToForwardSlashes(filename);
filename = normalizeSlashes(filename);
var sourceFile = getSourceFile(filename);
var node = getTouchingPropertyName(sourceFile, position);
@@ -3286,7 +3426,7 @@ module ts {
function getOccurrencesAtPosition(filename: string, position: number): ReferenceEntry[] {
synchronizeHostData();
filename = TypeScript.switchToForwardSlashes(filename);
filename = normalizeSlashes(filename);
var sourceFile = getSourceFile(filename);
var node = getTouchingWord(sourceFile, position);
@@ -3430,7 +3570,7 @@ module ts {
}
function getReturnOccurrences(returnStatement: ReturnStatement): ReferenceEntry[] {
var func = <FunctionDeclaration>getContainingFunction(returnStatement);
var func = <FunctionLikeDeclaration>getContainingFunction(returnStatement);
// If we didn't find a containing function with a block body, bail out.
if (!(func && hasKind(func.body, SyntaxKind.FunctionBlock))) {
@@ -3589,9 +3729,6 @@ module ts {
pushKeywordIf(keywords, switchStatement.getFirstToken(), SyntaxKind.SwitchKeyword);
// Types of break statements we can grab on to.
var breakSearchType = BreakContinueSearchType.All;
// Go through each clause in the switch statement, collecting the 'case'/'default' keywords.
forEach(switchStatement.clauses, clause => {
pushKeywordIf(keywords, clause.getFirstToken(), SyntaxKind.CaseKeyword, SyntaxKind.DefaultKeyword);
@@ -3739,7 +3876,7 @@ module ts {
function findReferences(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): ReferenceEntry[] {
synchronizeHostData();
fileName = TypeScript.switchToForwardSlashes(fileName);
fileName = normalizeSlashes(fileName);
var sourceFile = getSourceFile(fileName);
var node = getTouchingPropertyName(sourceFile, position);
@@ -3829,7 +3966,7 @@ module ts {
function getNormalizedSymbolName(symbolName: string, declarations: Declaration[]): string {
// Special case for function expressions, whose names are solely local to their bodies.
var functionExpression = forEach(declarations, d => d.kind === SyntaxKind.FunctionExpression ? d : undefined);
var functionExpression = forEach(declarations, d => d.kind === SyntaxKind.FunctionExpression ? <FunctionExpression>d : undefined);
if (functionExpression && functionExpression.name) {
var name = functionExpression.name.text;
@@ -4388,7 +4525,8 @@ module ts {
var declarations = sourceFile.getNamedDeclarations();
for (var i = 0, n = declarations.length; i < n; i++) {
var declaration = declarations[i];
var name = declaration.name.text;
// TODO(jfreeman): Skip this declaration if it has a computed name
var name = (<Identifier>declaration.name).text;
var matchKind = getMatchKind(searchTerms, name);
if (matchKind !== MatchKind.none) {
var container = <Declaration>getContainerNode(declaration);
@@ -4399,7 +4537,8 @@ module ts {
matchKind: MatchKind[matchKind],
fileName: filename,
textSpan: TypeScript.TextSpan.fromBounds(declaration.getStart(), declaration.getEnd()),
containerName: container.name ? container.name.text : "",
// TODO(jfreeman): What should be the containerName when the container has a computed name?
containerName: container.name ? (<Identifier>container.name).text : "",
containerKind: container.name ? getNodeKind(container) : ""
});
}
@@ -4458,12 +4597,11 @@ module ts {
function getEmitOutput(filename: string): EmitOutput {
synchronizeHostData();
filename = TypeScript.switchToForwardSlashes(filename);
filename = normalizeSlashes(filename);
var compilerOptions = program.getCompilerOptions();
var targetSourceFile = program.getSourceFile(filename); // Current selected file to be output
// If --out flag is not specified, shouldEmitToOwnFile is true. Otherwise shouldEmitToOwnFile is false.
var shouldEmitToOwnFile = ts.shouldEmitToOwnFile(targetSourceFile, compilerOptions);
var emitDeclaration = compilerOptions.declaration;
var emitOutput: EmitOutput = {
outputFiles: [],
emitOutputStatus: undefined,
@@ -4480,7 +4618,6 @@ module ts {
// Initialize writer for CompilerHost.writeFile
writer = getEmitOutputWriter;
var syntacticDiagnostics: Diagnostic[] = [];
var containSyntacticErrors = false;
if (shouldEmitToOwnFile) {
@@ -4549,7 +4686,7 @@ module ts {
if ((<ModuleDeclaration>node).name.kind === SyntaxKind.StringLiteral) {
return SemanticMeaning.Namespace | SemanticMeaning.Value;
}
else if (isInstantiated(node)) {
else if (getModuleInstanceState(node) === ModuleInstanceState.Instantiated) {
return SemanticMeaning.Namespace | SemanticMeaning.Value;
}
else {
@@ -4634,7 +4771,7 @@ module ts {
function getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems {
synchronizeHostData();
fileName = TypeScript.switchToForwardSlashes(fileName);
fileName = normalizeSlashes(fileName);
var sourceFile = getSourceFile(fileName);
return SignatureHelp.getSignatureHelpItems(sourceFile, position, typeInfoResolver, cancellationToken);
@@ -4665,7 +4802,7 @@ module ts {
var start = signatureInfoString.length;
signatureInfoString += displayPartsToString(parameter.displayParts);
var end = signatureInfoString.length - 1;
var end = signatureInfoString.length;
// add the parameter to the list
parameters.push({
@@ -4704,12 +4841,12 @@ module ts {
/// Syntactic features
function getSyntaxTree(filename: string): TypeScript.SyntaxTree {
filename = TypeScript.switchToForwardSlashes(filename);
filename = normalizeSlashes(filename);
return syntaxTreeCache.getCurrentFileSyntaxTree(filename);
}
function getCurrentSourceFile(filename: string): SourceFile {
filename = TypeScript.switchToForwardSlashes(filename);
filename = normalizeSlashes(filename);
var currentSourceFile = syntaxTreeCache.getCurrentSourceFile(filename);
return currentSourceFile;
}
@@ -4776,14 +4913,14 @@ module ts {
}
function getNavigationBarItems(filename: string): NavigationBarItem[] {
filename = TypeScript.switchToForwardSlashes(filename);
filename = normalizeSlashes(filename);
return NavigationBar.getNavigationBarItems(getCurrentSourceFile(filename));
}
function getSemanticClassifications(fileName: string, span: TypeScript.TextSpan): ClassifiedSpan[] {
synchronizeHostData();
fileName = TypeScript.switchToForwardSlashes(fileName);
fileName = normalizeSlashes(fileName);
var sourceFile = getSourceFile(fileName);
@@ -4826,7 +4963,7 @@ module ts {
*/
function hasValueSideModule(symbol: Symbol): boolean {
return forEach(symbol.declarations, declaration => {
return declaration.kind === SyntaxKind.ModuleDeclaration && isInstantiated(declaration);
return declaration.kind === SyntaxKind.ModuleDeclaration && getModuleInstanceState(declaration) == ModuleInstanceState.Instantiated;
});
}
}
@@ -4854,7 +4991,7 @@ module ts {
function getSyntacticClassifications(fileName: string, span: TypeScript.TextSpan): ClassifiedSpan[] {
// doesn't use compiler - no need to synchronize with host
fileName = TypeScript.switchToForwardSlashes(fileName);
fileName = normalizeSlashes(fileName);
var sourceFile = getCurrentSourceFile(fileName);
var result: ClassifiedSpan[] = [];
@@ -4927,6 +5064,10 @@ module ts {
// TODO: we should get another classification type for these literals.
return ClassificationTypeNames.stringLiteral;
}
else if (isTemplateLiteralKind(tokenKind)) {
// TODO (drosen): we should *also* get another classification type for these literals.
return ClassificationTypeNames.stringLiteral;
}
else if (tokenKind === SyntaxKind.Identifier) {
switch (token.parent.kind) {
case SyntaxKind.ClassDeclaration:
@@ -4980,7 +5121,7 @@ module ts {
function getOutliningSpans(filename: string): OutliningSpan[] {
// doesn't use compiler - no need to synchronize with host
filename = TypeScript.switchToForwardSlashes(filename);
filename = normalizeSlashes(filename);
var sourceFile = getCurrentSourceFile(filename);
return OutliningElementsCollector.collectElements(sourceFile);
}
@@ -5039,7 +5180,7 @@ module ts {
}
function getIndentationAtPosition(filename: string, position: number, editorOptions: EditorOptions) {
filename = TypeScript.switchToForwardSlashes(filename);
filename = normalizeSlashes(filename);
var start = new Date().getTime();
var sourceFile = getCurrentSourceFile(filename);
@@ -5076,21 +5217,21 @@ module ts {
}
function getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[] {
fileName = TypeScript.switchToForwardSlashes(fileName);
fileName = normalizeSlashes(fileName);
var manager = getFormattingManager(fileName, options);
return manager.formatSelection(start, end);
}
function getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[] {
fileName = TypeScript.switchToForwardSlashes(fileName);
fileName = normalizeSlashes(fileName);
var manager = getFormattingManager(fileName, options);
return manager.formatDocument();
}
function getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[] {
fileName = TypeScript.switchToForwardSlashes(fileName);
fileName = normalizeSlashes(fileName);
var manager = getFormattingManager(fileName, options);
@@ -5108,9 +5249,17 @@ module ts {
}
function getTodoComments(filename: string, descriptors: TodoCommentDescriptor[]): TodoComment[] {
filename = TypeScript.switchToForwardSlashes(filename);
// Note: while getting todo comments seems like a syntactic operation, we actually
// treat it as a semantic operation here. This is because we expect our host to call
// this on every single file. If we treat this syntactically, then that will cause
// us to populate and throw away the tree in our syntax tree cache for each file. By
// treating this as a semantic operation, we can access any tree without throwing
// anything away.
synchronizeHostData();
var sourceFile = getCurrentSourceFile(filename);
filename = normalizeSlashes(filename);
var sourceFile = getSourceFile(filename);
cancellationToken.throwIfCancellationRequested();
@@ -5163,7 +5312,7 @@ module ts {
descriptor = descriptors[i];
}
}
Debug.assert(descriptor);
Debug.assert(descriptor !== undefined);
// We don't want to match something like 'TODOBY', so we make sure a non
// letter/digit follows the match.
@@ -5268,7 +5417,7 @@ module ts {
function getRenameInfo(fileName: string, position: number): RenameInfo {
synchronizeHostData();
fileName = TypeScript.switchToForwardSlashes(fileName);
fileName = normalizeSlashes(fileName);
var sourceFile = getSourceFile(fileName);
var node = getTouchingWord(sourceFile, position);
@@ -5407,7 +5556,6 @@ module ts {
function getClassificationsForLine(text: string, lexState: EndOfLineState): ClassificationResult {
var offset = 0;
var lastTokenOrCommentEnd = 0;
var token = SyntaxKind.Unknown;
var lastNonTriviaToken = SyntaxKind.Unknown;
+38 -18
View File
@@ -16,7 +16,6 @@
/// <reference path='services.ts' />
/// <reference path='compiler\pathUtils.ts' />
/// <reference path='compiler\precompile.ts' />
var debugObjectHost = (<any>this);
@@ -55,6 +54,17 @@ module ts {
getDefaultLibFilename(options: string): string;
}
///
/// Pre-processing
///
// Note: This is being using by the host (VS) and is marshaled back and forth.
// When changing this make sure the changes are reflected in the managed side as well
export interface IFileReference {
path: string;
position: number;
length: number;
}
/** Public interface of a language service instance shim. */
export interface ShimFactory {
registerShim(shim: Shim): void;
@@ -171,13 +181,13 @@ module ts {
}
/// TODO: delete this, it is only needed until the VS interface is updated
export enum LanguageVersion {
export const enum LanguageVersion {
EcmaScript3 = 0,
EcmaScript5 = 1,
EcmaScript6 = 2,
}
export enum ModuleGenTarget {
export const enum ModuleGenTarget {
Unspecified = 0,
Synchronous = 1,
Asynchronous = 2,
@@ -507,17 +517,6 @@ module ts {
};
}
private realizeDiagnosticWithFileName(diagnostic: Diagnostic): { fileName: string; message: string; start: number; length: number; category: string; } {
return {
fileName: diagnostic.file.filename,
message: diagnostic.messageText,
start: diagnostic.start,
length: diagnostic.length,
/// TODO: no need for the tolowerCase call
category: DiagnosticCategory[diagnostic.category].toLowerCase()
};
}
public getSyntacticClassifications(fileName: string, start: number, length: number): string {
return this.forwardJSONCall(
"getSyntacticClassifications('" + fileName + "', " + start + ", " + length + ")",
@@ -559,7 +558,7 @@ module ts {
"getCompilerOptionsDiagnostics()",
() => {
var errors = this.languageService.getCompilerOptionsDiagnostics();
return errors.map(d => this.realizeDiagnosticWithFileName(d))
return errors.map(LanguageServiceShimObject.realizeDiagnostic)
});
}
@@ -846,12 +845,33 @@ module ts {
return forwardJSONCall(this.logger, actionDescription, action);
}
public getPreProcessedFileInfo(fileName: string, sourceText: TypeScript.IScriptSnapshot): string {
public getPreProcessedFileInfo(fileName: string, sourceTextSnapshot: TypeScript.IScriptSnapshot): string {
return this.forwardJSONCall(
"getPreProcessedFileInfo('" + fileName + "')",
() => {
var result = TypeScript.preProcessFile(fileName, sourceText);
return result;
var result = preProcessFile(sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength()));
var convertResult = {
referencedFiles: <IFileReference[]>[],
importedFiles: <IFileReference[]>[],
isLibFile: result.isLibFile
};
forEach(result.referencedFiles, refFile => {
convertResult.referencedFiles.push({
path: normalizePath(refFile.filename),
position: refFile.pos,
length: refFile.end - refFile.pos
});
});
forEach(result.importedFiles, importedFile => {
convertResult.importedFiles.push({
path: normalizeSlashes(importedFile.filename),
position: importedFile.pos,
length: importedFile.end - importedFile.pos
});
});
return convertResult;
});
}
+2 -2
View File
@@ -219,7 +219,7 @@ module ts.SignatureHelp {
// Find the list that starts right *after* the < or ( token.
// If the user has just opened a list, consider this item 0.
var list = getChildListThatStartsWithOpenerToken(parent, node, sourceFile);
Debug.assert(list);
Debug.assert(list !== undefined);
return {
list: list,
listItemIndex: 0
@@ -244,7 +244,7 @@ module ts.SignatureHelp {
// If the node is not a subspan of its parent, this is a big problem.
// There have been crashes that might be caused by this violation.
if (n.pos < n.parent.pos || n.end > n.parent.end) {
Debug.fail("Node of kind " + SyntaxKind[n.kind] + " is not a subspan of its parent of kind " + SyntaxKind[n.parent.kind]);
Debug.fail("Node of kind " + n.kind + " is not a subspan of its parent of kind " + n.parent.kind);
}
var argumentInfo = getImmediatelyContainingArgumentInfo(n);
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
@@ -1,357 +0,0 @@
///<reference path='references.ts' />
module TypeScript {
export class SyntaxVisitor implements ISyntaxVisitor {
public defaultVisit(node: ISyntaxNodeOrToken): any {
return null;
}
public visitToken(token: ISyntaxToken): any {
return this.defaultVisit(token);
}
public visitSourceUnit(node: SourceUnitSyntax): any {
return this.defaultVisit(node);
}
public visitQualifiedName(node: QualifiedNameSyntax): any {
return this.defaultVisit(node);
}
public visitObjectType(node: ObjectTypeSyntax): any {
return this.defaultVisit(node);
}
public visitFunctionType(node: FunctionTypeSyntax): any {
return this.defaultVisit(node);
}
public visitArrayType(node: ArrayTypeSyntax): any {
return this.defaultVisit(node);
}
public visitConstructorType(node: ConstructorTypeSyntax): any {
return this.defaultVisit(node);
}
public visitGenericType(node: GenericTypeSyntax): any {
return this.defaultVisit(node);
}
public visitTypeQuery(node: TypeQuerySyntax): any {
return this.defaultVisit(node);
}
public visitTupleType(node: TupleTypeSyntax): any {
return this.defaultVisit(node);
}
public visitInterfaceDeclaration(node: InterfaceDeclarationSyntax): any {
return this.defaultVisit(node);
}
public visitFunctionDeclaration(node: FunctionDeclarationSyntax): any {
return this.defaultVisit(node);
}
public visitModuleDeclaration(node: ModuleDeclarationSyntax): any {
return this.defaultVisit(node);
}
public visitClassDeclaration(node: ClassDeclarationSyntax): any {
return this.defaultVisit(node);
}
public visitEnumDeclaration(node: EnumDeclarationSyntax): any {
return this.defaultVisit(node);
}
public visitImportDeclaration(node: ImportDeclarationSyntax): any {
return this.defaultVisit(node);
}
public visitExportAssignment(node: ExportAssignmentSyntax): any {
return this.defaultVisit(node);
}
public visitMemberFunctionDeclaration(node: MemberFunctionDeclarationSyntax): any {
return this.defaultVisit(node);
}
public visitMemberVariableDeclaration(node: MemberVariableDeclarationSyntax): any {
return this.defaultVisit(node);
}
public visitConstructorDeclaration(node: ConstructorDeclarationSyntax): any {
return this.defaultVisit(node);
}
public visitIndexMemberDeclaration(node: IndexMemberDeclarationSyntax): any {
return this.defaultVisit(node);
}
public visitGetAccessor(node: GetAccessorSyntax): any {
return this.defaultVisit(node);
}
public visitSetAccessor(node: SetAccessorSyntax): any {
return this.defaultVisit(node);
}
public visitPropertySignature(node: PropertySignatureSyntax): any {
return this.defaultVisit(node);
}
public visitCallSignature(node: CallSignatureSyntax): any {
return this.defaultVisit(node);
}
public visitConstructSignature(node: ConstructSignatureSyntax): any {
return this.defaultVisit(node);
}
public visitIndexSignature(node: IndexSignatureSyntax): any {
return this.defaultVisit(node);
}
public visitMethodSignature(node: MethodSignatureSyntax): any {
return this.defaultVisit(node);
}
public visitBlock(node: BlockSyntax): any {
return this.defaultVisit(node);
}
public visitIfStatement(node: IfStatementSyntax): any {
return this.defaultVisit(node);
}
public visitVariableStatement(node: VariableStatementSyntax): any {
return this.defaultVisit(node);
}
public visitExpressionStatement(node: ExpressionStatementSyntax): any {
return this.defaultVisit(node);
}
public visitReturnStatement(node: ReturnStatementSyntax): any {
return this.defaultVisit(node);
}
public visitSwitchStatement(node: SwitchStatementSyntax): any {
return this.defaultVisit(node);
}
public visitBreakStatement(node: BreakStatementSyntax): any {
return this.defaultVisit(node);
}
public visitContinueStatement(node: ContinueStatementSyntax): any {
return this.defaultVisit(node);
}
public visitForStatement(node: ForStatementSyntax): any {
return this.defaultVisit(node);
}
public visitForInStatement(node: ForInStatementSyntax): any {
return this.defaultVisit(node);
}
public visitEmptyStatement(node: EmptyStatementSyntax): any {
return this.defaultVisit(node);
}
public visitThrowStatement(node: ThrowStatementSyntax): any {
return this.defaultVisit(node);
}
public visitWhileStatement(node: WhileStatementSyntax): any {
return this.defaultVisit(node);
}
public visitTryStatement(node: TryStatementSyntax): any {
return this.defaultVisit(node);
}
public visitLabeledStatement(node: LabeledStatementSyntax): any {
return this.defaultVisit(node);
}
public visitDoStatement(node: DoStatementSyntax): any {
return this.defaultVisit(node);
}
public visitDebuggerStatement(node: DebuggerStatementSyntax): any {
return this.defaultVisit(node);
}
public visitWithStatement(node: WithStatementSyntax): any {
return this.defaultVisit(node);
}
public visitPrefixUnaryExpression(node: PrefixUnaryExpressionSyntax): any {
return this.defaultVisit(node);
}
public visitDeleteExpression(node: DeleteExpressionSyntax): any {
return this.defaultVisit(node);
}
public visitTypeOfExpression(node: TypeOfExpressionSyntax): any {
return this.defaultVisit(node);
}
public visitVoidExpression(node: VoidExpressionSyntax): any {
return this.defaultVisit(node);
}
public visitConditionalExpression(node: ConditionalExpressionSyntax): any {
return this.defaultVisit(node);
}
public visitBinaryExpression(node: BinaryExpressionSyntax): any {
return this.defaultVisit(node);
}
public visitPostfixUnaryExpression(node: PostfixUnaryExpressionSyntax): any {
return this.defaultVisit(node);
}
public visitMemberAccessExpression(node: MemberAccessExpressionSyntax): any {
return this.defaultVisit(node);
}
public visitInvocationExpression(node: InvocationExpressionSyntax): any {
return this.defaultVisit(node);
}
public visitArrayLiteralExpression(node: ArrayLiteralExpressionSyntax): any {
return this.defaultVisit(node);
}
public visitObjectLiteralExpression(node: ObjectLiteralExpressionSyntax): any {
return this.defaultVisit(node);
}
public visitObjectCreationExpression(node: ObjectCreationExpressionSyntax): any {
return this.defaultVisit(node);
}
public visitParenthesizedExpression(node: ParenthesizedExpressionSyntax): any {
return this.defaultVisit(node);
}
public visitParenthesizedArrowFunctionExpression(node: ParenthesizedArrowFunctionExpressionSyntax): any {
return this.defaultVisit(node);
}
public visitSimpleArrowFunctionExpression(node: SimpleArrowFunctionExpressionSyntax): any {
return this.defaultVisit(node);
}
public visitCastExpression(node: CastExpressionSyntax): any {
return this.defaultVisit(node);
}
public visitElementAccessExpression(node: ElementAccessExpressionSyntax): any {
return this.defaultVisit(node);
}
public visitFunctionExpression(node: FunctionExpressionSyntax): any {
return this.defaultVisit(node);
}
public visitOmittedExpression(node: OmittedExpressionSyntax): any {
return this.defaultVisit(node);
}
public visitVariableDeclaration(node: VariableDeclarationSyntax): any {
return this.defaultVisit(node);
}
public visitVariableDeclarator(node: VariableDeclaratorSyntax): any {
return this.defaultVisit(node);
}
public visitArgumentList(node: ArgumentListSyntax): any {
return this.defaultVisit(node);
}
public visitParameterList(node: ParameterListSyntax): any {
return this.defaultVisit(node);
}
public visitTypeArgumentList(node: TypeArgumentListSyntax): any {
return this.defaultVisit(node);
}
public visitTypeParameterList(node: TypeParameterListSyntax): any {
return this.defaultVisit(node);
}
public visitHeritageClause(node: HeritageClauseSyntax): any {
return this.defaultVisit(node);
}
public visitEqualsValueClause(node: EqualsValueClauseSyntax): any {
return this.defaultVisit(node);
}
public visitCaseSwitchClause(node: CaseSwitchClauseSyntax): any {
return this.defaultVisit(node);
}
public visitDefaultSwitchClause(node: DefaultSwitchClauseSyntax): any {
return this.defaultVisit(node);
}
public visitElseClause(node: ElseClauseSyntax): any {
return this.defaultVisit(node);
}
public visitCatchClause(node: CatchClauseSyntax): any {
return this.defaultVisit(node);
}
public visitFinallyClause(node: FinallyClauseSyntax): any {
return this.defaultVisit(node);
}
public visitTypeParameter(node: TypeParameterSyntax): any {
return this.defaultVisit(node);
}
public visitConstraint(node: ConstraintSyntax): any {
return this.defaultVisit(node);
}
public visitSimplePropertyAssignment(node: SimplePropertyAssignmentSyntax): any {
return this.defaultVisit(node);
}
public visitFunctionPropertyAssignment(node: FunctionPropertyAssignmentSyntax): any {
return this.defaultVisit(node);
}
public visitParameter(node: ParameterSyntax): any {
return this.defaultVisit(node);
}
public visitEnumElement(node: EnumElementSyntax): any {
return this.defaultVisit(node);
}
public visitTypeAnnotation(node: TypeAnnotationSyntax): any {
return this.defaultVisit(node);
}
public visitExternalModuleReference(node: ExternalModuleReferenceSyntax): any {
return this.defaultVisit(node);
}
public visitModuleNameModuleReference(node: ModuleNameModuleReferenceSyntax): any {
return this.defaultVisit(node);
}
}
}
-21
View File
@@ -1,21 +0,0 @@
///<reference path='references.ts' />
module TypeScript {
export class DepthLimitedWalker extends SyntaxWalker {
private _depth: number = 0;
private _maximumDepth: number = 0;
constructor(maximumDepth: number) {
super();
this._maximumDepth = maximumDepth;
}
public visitNode(node: ISyntaxNode): void {
if (this._depth < this._maximumDepth) {
this._depth++;
super.visitNode(node);
this._depth--;
}
}
}
}
+88 -55
View File
@@ -88,8 +88,8 @@ module TypeScript.IncrementalParser {
function release() {
_scannerParserSource.release();
_scannerParserSource = null;
_oldSourceUnitCursor = null;
_scannerParserSource = undefined;
_oldSourceUnitCursor = undefined;
_outstandingRewindPointCount = 0;
}
@@ -177,13 +177,13 @@ module TypeScript.IncrementalParser {
// Null out the cursor that the rewind point points to. This way we don't try
// to return it in 'releaseRewindPoint'.
rewindPoint.oldSourceUnitCursor = null;
rewindPoint.oldSourceUnitCursor = undefined;
_scannerParserSource.rewind(rewindPoint);
}
function releaseRewindPoint(rewindPoint: IParserRewindPoint): void {
if (rewindPoint.oldSourceUnitCursor !== null) {
if (rewindPoint.oldSourceUnitCursor) {
returnSyntaxCursor(rewindPoint.oldSourceUnitCursor);
}
@@ -220,7 +220,7 @@ module TypeScript.IncrementalParser {
// If our current absolute position is in the middle of the changed range in the new text
// then we definitely can't read from the old source unit right now.
if (_changeRange !== null && _changeRangeNewSpan.intersectsWithPosition(absolutePosition())) {
if (_changeRange && _changeRangeNewSpan.intersectsWithPosition(absolutePosition())) {
return false;
}
@@ -235,7 +235,7 @@ module TypeScript.IncrementalParser {
!_oldSourceUnitCursor.isFinished();
}
function updateTokens(nodeOrToken: ISyntaxNodeOrToken): void {
function updateTokenPosition(token: ISyntaxToken): void {
// If we got a node or token, and we're past the range of edited text, then walk its
// constituent tokens, making sure all their positions are correct. We don't need to
// do this for the tokens before the edited range (since their positions couldn't have
@@ -243,38 +243,70 @@ module TypeScript.IncrementalParser {
// edited range, as their positions will be correct when the underlying parser source
// creates them.
var position = absolutePosition();
var tokenWasMoved = isPastChangeRange() && fullStart(nodeOrToken) !== position;
if (tokenWasMoved) {
setTokenFullStartWalker.position = position;
visitNodeOrToken(setTokenFullStartWalker, nodeOrToken);
if (isPastChangeRange()) {
token.setFullStart(absolutePosition());
}
}
function updateNodePosition(node: ISyntaxNode): void {
// If we got a node or token, and we're past the range of edited text, then walk its
// constituent tokens, making sure all their positions are correct. We don't need to
// do this for the tokens before the edited range (since their positions couldn't have
// been affected by the edit), and we don't need to do this for the tokens in the
// edited range, as their positions will be correct when the underlying parser source
// creates them.
if (isPastChangeRange()) {
var position = absolutePosition();
var tokens = getTokens(node);
for (var i = 0, n = tokens.length; i < n; i++) {
var token = tokens[i];
token.setFullStart(position);
position += token.fullWidth();
}
}
}
function getTokens(node: ISyntaxNode): ISyntaxToken[] {
var tokens = node.__cachedTokens;
if (!tokens) {
tokens = [];
tokenCollectorWalker.tokens = tokens;
visitNodeOrToken(tokenCollectorWalker, node);
node.__cachedTokens = tokens;
tokenCollectorWalker.tokens = undefined;
}
return tokens;
}
function currentNode(): ISyntaxNode {
if (canReadFromOldSourceUnit()) {
// Try to read a node. If we can't then our caller will call back in and just try
// to get a token.
var node = tryGetNodeFromOldSourceUnit();
if (node !== null) {
if (node) {
// Make sure the positions for the tokens in this node are correct.
updateTokens(node);
updateNodePosition(node);
return node;
}
}
// Either we were ahead of the old text, or we were pinned. No node can be read here.
return null;
return undefined;
}
function currentToken(): ISyntaxToken {
if (canReadFromOldSourceUnit()) {
var token = tryGetTokenFromOldSourceUnit();
if (token !== null) {
if (token) {
// Make sure the token's position/text is correct.
updateTokens(token);
updateTokenPosition(token);
return token;
}
}
@@ -354,9 +386,9 @@ module TypeScript.IncrementalParser {
// e) we are still in the same strict or non-strict state that the node was originally parsed in.
while (true) {
var node = _oldSourceUnitCursor.currentNode();
if (node === null) {
if (node === undefined) {
// Couldn't even read a node, nothing to return.
return null;
return undefined;
}
if (!intersectsWithChangeRangeSpanInOriginalText(absolutePosition(), fullWidth(node))) {
@@ -395,7 +427,7 @@ module TypeScript.IncrementalParser {
// need to make sure that if that the parser asks for a *token* we don't return it.
// Converted identifiers can't ever be created by the scanner, and as such, should not
// be returned by this source.
if (token !== null) {
if (token) {
if (!intersectsWithChangeRangeSpanInOriginalText(position, token.fullWidth())) {
// Didn't intersect with the change range.
if (!token.isIncrementallyUnusable() && !Scanner.isContextualToken(token)) {
@@ -417,13 +449,13 @@ module TypeScript.IncrementalParser {
var token = _oldSourceUnitCursor.currentToken();
return canReuseTokenFromOldSourceUnit(absolutePosition(), token)
? token : null;
? token : undefined;
}
function peekToken(n: number): ISyntaxToken {
if (canReadFromOldSourceUnit()) {
var token = tryPeekTokenFromOldSourceUnit(n);
if (token !== null) {
if (token) {
return token;
}
}
@@ -462,7 +494,7 @@ module TypeScript.IncrementalParser {
var interimToken = _oldSourceUnitCursor.currentToken();
if (!canReuseTokenFromOldSourceUnit(currentPosition, interimToken)) {
return null;
return undefined;
}
currentPosition += interimToken.fullWidth();
@@ -471,7 +503,7 @@ module TypeScript.IncrementalParser {
var token = _oldSourceUnitCursor.currentToken();
return canReuseTokenFromOldSourceUnit(currentPosition, token)
? token : null;
? token : undefined;
}
function consumeNode(node: ISyntaxNode): void {
@@ -486,7 +518,7 @@ module TypeScript.IncrementalParser {
var _absolutePosition = absolutePosition() + fullWidth(node);
_scannerParserSource.resetToPosition(_absolutePosition);
// Debug.assert(previousToken !== null);
// Debug.assert(previousToken !== undefined);
// Debug.assert(previousToken.width() > 0);
//if (!isPastChangeRange()) {
@@ -497,6 +529,8 @@ module TypeScript.IncrementalParser {
}
function consumeToken(currentToken: ISyntaxToken): void {
// Debug.assert(currentToken.fullWidth() > 0 || currentToken.kind === SyntaxKind.EndOfFileToken);
// This token may have come from the old source unit, or from the new text. Handle
// both accordingly.
@@ -515,7 +549,7 @@ module TypeScript.IncrementalParser {
var _absolutePosition = absolutePosition() + currentToken.fullWidth();
_scannerParserSource.resetToPosition(_absolutePosition);
// Debug.assert(previousToken !== null);
// Debug.assert(previousToken !== undefined);
// Debug.assert(previousToken.width() > 0);
//if (!isPastChangeRange()) {
@@ -543,15 +577,15 @@ module TypeScript.IncrementalParser {
// Once we're past the change range, we no longer need it. Null it out.
// From now on we can check if we're past the change range just by seeing
// if this is null.
_changeRange = null;
// if this is undefined.
_changeRange = undefined;
}
}
}
}
function isPastChangeRange(): boolean {
return _changeRange === null;
return _changeRange === undefined;
}
return {
@@ -605,7 +639,7 @@ module TypeScript.IncrementalParser {
if (syntaxCursorPoolCount > 0) {
// If we reused an existing cursor, take it out of the pool so no one else uses it.
syntaxCursorPoolCount--;
syntaxCursorPool[syntaxCursorPoolCount] = null;
syntaxCursorPool[syntaxCursorPoolCount] = undefined;
}
return cursor;
@@ -652,11 +686,11 @@ module TypeScript.IncrementalParser {
for (var i = 0, n = pieces.length; i < n; i++) {
var piece = pieces[i];
if (piece.element === null) {
if (piece.element === undefined) {
break;
}
piece.element = null;
piece.element = undefined;
piece.indexInParent = -1;
}
@@ -669,7 +703,7 @@ module TypeScript.IncrementalParser {
for (var i = 0, n = other.pieces.length; i < n; i++) {
var piece = other.pieces[i];
if (piece.element === null) {
if (piece.element === undefined) {
break;
}
@@ -685,13 +719,13 @@ module TypeScript.IncrementalParser {
function currentNodeOrToken(): ISyntaxNodeOrToken {
if (isFinished()) {
return null;
return undefined;
}
var result = pieces[currentPieceIndex].element;
// The current element must always be a node or a token.
// Debug.assert(result !== null);
// Debug.assert(result !== undefined);
// Debug.assert(result.isNode() || result.isToken());
return <ISyntaxNodeOrToken>result;
@@ -699,12 +733,16 @@ module TypeScript.IncrementalParser {
function currentNode(): ISyntaxNode {
var element = currentNodeOrToken();
return isNode(element) ? <ISyntaxNode>element : null;
return isNode(element) ? <ISyntaxNode>element : undefined;
}
function isEmptyList(element: ISyntaxElement) {
return isList(element) && (<ISyntaxNodeOrToken[]>element).length === 0;
}
function moveToFirstChild() {
var nodeOrToken = currentNodeOrToken();
if (nodeOrToken === null) {
if (nodeOrToken === undefined) {
return;
}
@@ -721,7 +759,7 @@ module TypeScript.IncrementalParser {
// next sibling of the empty node.
for (var i = 0, n = childCount(nodeOrToken); i < n; i++) {
var child = childAt(nodeOrToken, i);
if (child !== null && !isShared(child)) {
if (child && !isEmptyList(child)) {
// Great, we found a real child. Push that.
pushElement(child, /*indexInParent:*/ i);
@@ -749,14 +787,13 @@ module TypeScript.IncrementalParser {
for (var i = currentPiece.indexInParent + 1, n = childCount(parent); i < n; i++) {
var sibling = childAt(parent, i);
if (sibling !== null && !isShared(sibling)) {
if (sibling && !isEmptyList(sibling)) {
// We found a good sibling that we can move to. Just reuse our existing piece
// so we don't have to push/pop.
currentPiece.element = sibling;
currentPiece.indexInParent = i;
// The sibling might have been a list. Move to it's first child. it must have
// one since this was a non-shared element.
// The sibling might have been a list. Move to it's first child.
moveToFirstChildIfList();
return;
}
@@ -766,7 +803,7 @@ module TypeScript.IncrementalParser {
// Clear the data from the old piece. We don't want to keep any elements around
// unintentionally.
currentPiece.element = null;
currentPiece.element = undefined;
currentPiece.indexInParent = -1;
// Point at the parent. if we move past the top of the path, then we're finished.
@@ -777,7 +814,7 @@ module TypeScript.IncrementalParser {
function moveToFirstChildIfList(): void {
var element = pieces[currentPieceIndex].element;
if (isList(element) || isSeparatedList(element)) {
if (isList(element)) {
// We cannot ever get an empty list in our piece path. Empty lists are 'shared' and
// we make sure to filter that out before pushing any children.
// Debug.assert(childCount(element) > 0);
@@ -787,7 +824,7 @@ module TypeScript.IncrementalParser {
}
function pushElement(element: ISyntaxElement, indexInParent: number): void {
// Debug.assert(element !== null);
// Debug.assert(element !== undefined);
// Debug.assert(indexInParent >= 0);
currentPieceIndex++;
@@ -819,8 +856,8 @@ module TypeScript.IncrementalParser {
moveToFirstToken();
var element = currentNodeOrToken();
// Debug.assert(element === null || element.isToken());
return element === null ? null : <ISyntaxToken>element;
// Debug.assert(element === undefined || element.isToken());
return <ISyntaxToken>element;
}
return {
@@ -841,21 +878,17 @@ module TypeScript.IncrementalParser {
// A simple walker we use to hit all the tokens of a node and update their positions when they
// are reused in a different location because of an incremental parse.
class SetTokenFullStartWalker extends SyntaxWalker {
public position: number;
class TokenCollectorWalker extends SyntaxWalker {
public tokens: ISyntaxToken[] = [];
public visitToken(token: ISyntaxToken): void {
var position = this.position;
token.setFullStart(position);
this.position = position + token.fullWidth();
this.tokens.push(token);
}
}
var setTokenFullStartWalker = new SetTokenFullStartWalker();
var tokenCollectorWalker = new TokenCollectorWalker();
export function parse(oldSyntaxTree: SyntaxTree, textChangeRange: TextChangeRange, newText: ISimpleText): SyntaxTree {
Debug.assert(oldSyntaxTree.isConcrete(), "Can only incrementally parse a concrete syntax tree.");
if (textChangeRange.isUnchanged()) {
return oldSyntaxTree;
}
+1038 -1154
View File
File diff suppressed because it is too large Load Diff
+78 -47
View File
@@ -16,11 +16,11 @@ module TypeScript.PrettyPrinter {
}
private newLineCountBetweenModuleElements(element1: IModuleElementSyntax, element2: IModuleElementSyntax): number {
if (element1 === null || element2 === null) {
if (!element1 || !element2) {
return 0;
}
if (lastToken(element1).kind() === SyntaxKind.CloseBraceToken) {
if (lastToken(element1).kind === SyntaxKind.CloseBraceToken) {
return 2;
}
@@ -28,19 +28,19 @@ module TypeScript.PrettyPrinter {
}
private newLineCountBetweenClassElements(element1: IClassElementSyntax, element2: IClassElementSyntax): number {
if (element1 === null || element2 === null) {
if (!element1 || !element2) {
return 0;
}
return 1;
}
private newLineCountBetweenStatements(element1: IClassElementSyntax, element2: IClassElementSyntax): number {
if (element1 === null || element2 === null) {
private newLineCountBetweenStatements(element1: IStatementSyntax, element2: IStatementSyntax): number {
if (!element1 || !element2) {
return 0;
}
if (lastToken(element1).kind() === SyntaxKind.CloseBraceToken) {
if (lastToken(element1).kind === SyntaxKind.CloseBraceToken) {
return 2;
}
@@ -48,7 +48,7 @@ module TypeScript.PrettyPrinter {
}
private newLineCountBetweenSwitchClauses(element1: ISwitchClauseSyntax, element2: ISwitchClauseSyntax): number {
if (element1 === null || element2 === null) {
if (!element1 || !element2) {
return 0;
}
@@ -120,7 +120,7 @@ module TypeScript.PrettyPrinter {
}
private appendToken(token: ISyntaxToken): void {
if (token !== null && token.fullWidth() > 0) {
if (token && token.fullWidth() > 0) {
this.appendIndentationIfAfterNewLine();
this.appendText(token.text());
}
@@ -150,7 +150,7 @@ module TypeScript.PrettyPrinter {
this.ensureSpace();
}
visitNodeOrToken(this, childAt(list, i));
visitNodeOrToken(this, list[i]);
}
else {
this.appendToken(<ISyntaxToken>childAt(list, i));
@@ -165,7 +165,7 @@ module TypeScript.PrettyPrinter {
this.ensureNewLine();
}
visitNodeOrToken(this, childAt(list, i));
visitNodeOrToken(this, list[i]);
}
else {
this.appendToken(<ISyntaxToken>childAt(list, i));
@@ -174,7 +174,7 @@ module TypeScript.PrettyPrinter {
}
private appendModuleElements(list: IModuleElementSyntax[]): void {
var lastModuleElement: IModuleElementSyntax = null;
var lastModuleElement: IModuleElementSyntax = undefined;
for (var i = 0, n = list.length; i < n; i++) {
var moduleElement = list[i];
var newLineCount = this.newLineCountBetweenModuleElements(lastModuleElement, moduleElement);
@@ -236,7 +236,7 @@ module TypeScript.PrettyPrinter {
this.indentation++;
var lastClassElement: IClassElementSyntax = null;
var lastClassElement: IClassElementSyntax = undefined;
for (var i = 0, n = node.classElements.length; i < n; i++) {
var classElement = node.classElements[i];
var newLineCount = this.newLineCountBetweenClassElements(lastClassElement, classElement);
@@ -278,7 +278,7 @@ module TypeScript.PrettyPrinter {
}
for (var i = 0, n = childCount(node.typeMembers); i < n; i++) {
visitNodeOrToken(this, childAt(node.typeMembers, i));
visitNodeOrToken(this, node.typeMembers[i]);
if (appendNewLines) {
this.ensureNewLine();
@@ -305,9 +305,6 @@ module TypeScript.PrettyPrinter {
this.ensureSpace();
this.appendElement(node.name);
this.ensureSpace();
this.appendToken(node.stringLiteral);
this.ensureSpace();
this.appendToken(node.openBraceToken);
this.ensureNewLine();
@@ -319,13 +316,13 @@ module TypeScript.PrettyPrinter {
this.appendToken(node.closeBraceToken);
}
private appendBlockOrSemicolon(block: BlockSyntax, semicolonToken: ISyntaxToken) {
if (block) {
private appendBlockOrSemicolon(body: BlockSyntax | ISyntaxToken) {
if (body.kind === SyntaxKind.Block) {
this.ensureSpace();
visitNodeOrToken(this, block);
visitNodeOrToken(this, body);
}
else {
this.appendToken(semicolonToken);
this.appendToken(<ISyntaxToken>body);
}
}
@@ -336,7 +333,7 @@ module TypeScript.PrettyPrinter {
this.ensureSpace();
this.appendToken(node.identifier);
this.appendNode(node.callSignature);
this.appendBlockOrSemicolon(node.block, node.semicolonToken);
this.appendBlockOrSemicolon(node.body);
}
public visitVariableStatement(node: VariableStatementSyntax): void {
@@ -353,7 +350,7 @@ module TypeScript.PrettyPrinter {
}
public visitVariableDeclarator(node: VariableDeclaratorSyntax): void {
this.appendToken(node.propertyName);
visitNodeOrToken(this, node.propertyName);
this.appendNode(node.equalsValueClause);
}
@@ -390,8 +387,7 @@ module TypeScript.PrettyPrinter {
this.ensureSpace();
this.appendToken(node.equalsGreaterThanToken);
this.ensureSpace();
this.appendNode(node.block);
this.appendElement(node.expression);
visitNodeOrToken(this, node.body);
}
public visitParenthesizedArrowFunctionExpression(node: ParenthesizedArrowFunctionExpressionSyntax): void {
@@ -399,8 +395,7 @@ module TypeScript.PrettyPrinter {
this.ensureSpace();
this.appendToken(node.equalsGreaterThanToken);
this.ensureSpace();
this.appendNode(node.block);
this.appendElement(node.expression);
visitNodeOrToken(this, node.body);
}
public visitQualifiedName(node: QualifiedNameSyntax): void {
@@ -427,6 +422,20 @@ module TypeScript.PrettyPrinter {
this.appendToken(node.closeBracketToken);
}
public visitParenthesizedType(node: ParenthesizedTypeSyntax): void {
this.appendToken(node.openParenToken);
this.appendElement(node.type);
this.appendToken(node.closeParenToken);
}
public visitUnionType(node: UnionTypeSyntax): void {
this.appendElement(node.left);
this.ensureSpace();
this.appendToken(node.barToken);
this.ensureSpace();
this.appendElement(node.right);
}
public visitConstructorType(node: ConstructorTypeSyntax): void {
this.appendToken(node.newKeyword);
this.ensureSpace();
@@ -472,7 +481,7 @@ module TypeScript.PrettyPrinter {
}
private appendStatements(statements: IStatementSyntax[]): void {
var lastStatement: IStatementSyntax = null;
var lastStatement: IStatementSyntax = undefined;
for (var i = 0, n = statements.length; i < n; i++) {
var statement = statements[i];
@@ -538,7 +547,7 @@ module TypeScript.PrettyPrinter {
public visitBinaryExpression(node: BinaryExpressionSyntax): void {
visitNodeOrToken(this, node.left);
if (node.kind() !== SyntaxKind.CommaExpression) {
if (node.operatorToken.kind !== SyntaxKind.CommaToken) {
this.ensureSpace();
}
@@ -565,7 +574,7 @@ module TypeScript.PrettyPrinter {
}
public visitMethodSignature(node: MethodSignatureSyntax): void {
this.appendToken(node.propertyName);
visitNodeOrToken(this, node.propertyName);
this.appendToken(node.questionToken);
visitNodeOrToken(this, node.callSignature);
}
@@ -578,7 +587,7 @@ module TypeScript.PrettyPrinter {
}
public visitPropertySignature(node: PropertySignatureSyntax): void {
this.appendToken(node.propertyName);
visitNodeOrToken(this, node.propertyName);
this.appendToken(node.questionToken);
this.appendNode(node.typeAnnotation);
}
@@ -614,7 +623,7 @@ module TypeScript.PrettyPrinter {
}
private appendBlockOrStatement(node: IStatementSyntax): void {
if (node.kind() === SyntaxKind.Block) {
if (node.kind === SyntaxKind.Block) {
this.ensureSpace();
visitNodeOrToken(this, node);
}
@@ -640,7 +649,7 @@ module TypeScript.PrettyPrinter {
this.ensureNewLine();
this.appendToken(node.elseKeyword);
if (node.statement.kind() === SyntaxKind.IfStatement) {
if (node.statement.kind === SyntaxKind.IfStatement) {
this.ensureSpace();
visitNodeOrToken(this, node.statement);
}
@@ -657,7 +666,7 @@ module TypeScript.PrettyPrinter {
public visitConstructorDeclaration(node: ConstructorDeclarationSyntax): void {
this.appendToken(node.constructorKeyword);
visitNodeOrToken(this, node.callSignature);
this.appendBlockOrSemicolon(node.block, node.semicolonToken);
this.appendBlockOrSemicolon(node.body);
}
public visitIndexMemberDeclaration(node: IndexMemberDeclarationSyntax): void {
@@ -670,9 +679,9 @@ module TypeScript.PrettyPrinter {
public visitMemberFunctionDeclaration(node: MemberFunctionDeclarationSyntax): void {
this.appendSpaceList(node.modifiers);
this.ensureSpace();
this.appendToken(node.propertyName);
visitNodeOrToken(this, node.propertyName);
visitNodeOrToken(this, node.callSignature);
this.appendBlockOrSemicolon(node.block, node.semicolonToken);
this.appendBlockOrSemicolon(node.body);
}
public visitGetAccessor(node: GetAccessorSyntax): void {
@@ -680,7 +689,7 @@ module TypeScript.PrettyPrinter {
this.ensureSpace();
this.appendToken(node.getKeyword);
this.ensureSpace();
this.appendToken(node.propertyName);
visitNodeOrToken(this, node.propertyName);
visitNodeOrToken(this, node.callSignature);
this.ensureSpace();
visitNodeOrToken(this, node.block);
@@ -691,7 +700,7 @@ module TypeScript.PrettyPrinter {
this.ensureSpace();
this.appendToken(node.setKeyword);
this.ensureSpace();
this.appendToken(node.propertyName);
visitNodeOrToken(this, node.propertyName);
visitNodeOrToken(this, node.callSignature)
this.ensureSpace();
visitNodeOrToken(this, node.block);
@@ -743,7 +752,7 @@ module TypeScript.PrettyPrinter {
this.appendToken(node.openBraceToken);
this.ensureNewLine();
var lastSwitchClause: ISwitchClauseSyntax = null;
var lastSwitchClause: ISwitchClauseSyntax = undefined;
for (var i = 0, n = node.switchClauses.length; i < n; i++) {
var switchClause = node.switchClauses[i];
@@ -760,9 +769,9 @@ module TypeScript.PrettyPrinter {
}
private appendSwitchClauseStatements(node: ISwitchClauseSyntax): void {
if (childCount(node.statements) === 1 && childAt(node.statements, 0).kind() === SyntaxKind.Block) {
if (childCount(node.statements) === 1 && childAt(node.statements, 0).kind === SyntaxKind.Block) {
this.ensureSpace();
visitNodeOrToken(this, childAt(node.statements, 0));
visitNodeOrToken(this, node.statements[0]);
}
else if (childCount(node.statements) > 0) {
this.ensureNewLine();
@@ -811,8 +820,7 @@ module TypeScript.PrettyPrinter {
this.appendToken(node.forKeyword);
this.ensureSpace();
this.appendToken(node.openParenToken);
this.appendNode(node.variableDeclaration);
this.appendElement(node.initializer);
visitNodeOrToken(this, node.initializer);
this.appendToken(node.firstSemicolonToken);
if (node.condition) {
@@ -835,12 +843,11 @@ module TypeScript.PrettyPrinter {
this.appendToken(node.forKeyword);
this.ensureSpace();
this.appendToken(node.openParenToken);
this.appendNode(node.variableDeclaration);
this.appendElement(node.left);
this.ensureSpace();
this.appendToken(node.inKeyword);
this.ensureSpace();
this.appendElement(node.expression);
this.appendElement(node.right);
this.appendToken(node.closeParenToken);
this.appendBlockOrStatement(node.statement);
}
@@ -881,7 +888,7 @@ module TypeScript.PrettyPrinter {
}
public visitEnumElement(node: EnumElementSyntax): void {
this.appendToken(node.propertyName);
visitNodeOrToken(this, node.propertyName);
this.ensureSpace();
this.appendNode(node.equalsValueClause);
}
@@ -912,15 +919,21 @@ module TypeScript.PrettyPrinter {
this.appendToken(node.closeBraceToken);
}
public visitComputedPropertyName(node: ComputedPropertyNameSyntax): void {
this.appendToken(node.openBracketToken);
visitNodeOrToken(this, node.expression);
this.appendToken(node.closeBracketToken);
}
public visitSimplePropertyAssignment(node: SimplePropertyAssignmentSyntax): void {
this.appendToken(node.propertyName);
visitNodeOrToken(this, node.propertyName);
this.appendToken(node.colonToken);
this.ensureSpace();
visitNodeOrToken(this, node.expression);
}
public visitFunctionPropertyAssignment(node: FunctionPropertyAssignmentSyntax): void {
this.appendToken(node.propertyName);
visitNodeOrToken(this, node.propertyName);
visitNodeOrToken(this, node.callSignature);
this.ensureSpace();
visitNodeOrToken(this, node.block);
@@ -1009,5 +1022,23 @@ module TypeScript.PrettyPrinter {
this.appendToken(node.debuggerKeyword);
this.appendToken(node.semicolonToken);
}
public visitTemplateExpression(node: TemplateExpressionSyntax): void {
this.appendToken(node.templateStartToken);
this.ensureSpace();
this.appendSpaceList(node.templateClauses);
}
public visitTemplateClause(node: TemplateClauseSyntax): void {
visitNodeOrToken(this, node.expression);
this.ensureSpace();
this.appendToken(node.templateMiddleOrEndToken);
}
public visitTemplateAccessExpression(node: TemplateAccessExpressionSyntax): void {
visitNodeOrToken(this, node.expression);
this.ensureSpace();
visitNodeOrToken(this, node.templateExpression);
}
}
}
+1 -2
View File
@@ -17,9 +17,7 @@
///<reference path='syntaxElement.ts' />
///<reference path='syntaxFacts2.ts' />
///<reference path='syntaxList.ts' />
///<reference path='syntaxNode.ts' />
///<reference path='syntaxNodeOrToken.ts' />
///<reference path='syntaxNodes.interfaces.generated.ts' />
// SyntaxDedenter depends on SyntaxRewriter
// ///<reference path='syntaxDedenter.ts' />
@@ -41,6 +39,7 @@
///<reference path='parser.ts' />
// Concrete nodes depend on the parser.
///<reference path='syntaxInterfaces.generated.ts' />
///<reference path='syntaxNodes.concrete.generated.ts' />
// SyntaxTree depends on PositionTrackingWalker
+175 -212
View File
@@ -60,84 +60,47 @@ module TypeScript.Scanner {
// This gives us 23bit for width (or 8MB of width which should be enough for any codebase).
enum ScannerConstants {
LargeTokenFullStartShift = 4,
LargeTokenFullWidthShift = 7,
LargeTokenLeadingTriviaBitMask = 0x01, // 00000001
LargeTokenLeadingCommentBitMask = 0x02, // 00000010
LargeTokenTrailingTriviaBitMask = 0x04, // 00000100
LargeTokenTrailingCommentBitMask = 0x08, // 00001000
LargeTokenTriviaBitMask = 0x0F, // 00001111
LargeTokenFullWidthShift = 3,
FixedWidthTokenFullStartShift = 7,
FixedWidthTokenMaxFullStart = 0x7FFFFF, // 23 ones.
WhitespaceTrivia = 0x01, // 00000001
NewlineTrivia = 0x02, // 00000010
CommentTrivia = 0x04, // 00000100
TriviaMask = 0x07, // 00000111
SmallTokenFullWidthShift = 7,
SmallTokenFullStartShift = 12,
SmallTokenMaxFullStart = 0x3FFFF, // 18 ones.
SmallTokenMaxFullWidth = 0x1F, // 5 ones
SmallTokenFullWidthMask = 0x1F, // 00011111
KindMask = 0x7F, // 01111111
IsVariableWidthMask = 0x80, // 10000000
KindMask = 0x7F, // 01111111
IsVariableWidthMask = 0x80, // 10000000
}
// Make sure our math works for packing/unpacking large fullStarts.
Debug.assert(largeTokenUnpackFullStart(largeTokenPackFullStartAndInfo(1 << 26, 3)) === (1 << 26));
Debug.assert(largeTokenUnpackFullStart(largeTokenPackFullStartAndInfo(3 << 25, 1)) === (3 << 25));
Debug.assert(largeTokenUnpackFullStart(largeTokenPackFullStartAndInfo(10 << 23, 2)) === (10 << 23));
function fixedWidthTokenPackData(fullStart: number, kind: SyntaxKind) {
return (fullStart << ScannerConstants.FixedWidthTokenFullStartShift) | kind;
function largeTokenPackData(fullWidth: number, leadingTriviaInfo: number) {
return (fullWidth << ScannerConstants.LargeTokenFullWidthShift) | leadingTriviaInfo;
}
function fixedWidthTokenUnpackFullStart(packedData: number) {
return packedData >> ScannerConstants.FixedWidthTokenFullStartShift;
function largeTokenUnpackFullWidth(packedFullWidthAndInfo: number): number {
return packedFullWidthAndInfo >> ScannerConstants.LargeTokenFullWidthShift;
}
function smallTokenPackData(fullStart: number, fullWidth: number, kind: SyntaxKind) {
return (fullStart << ScannerConstants.SmallTokenFullStartShift) |
(fullWidth << ScannerConstants.SmallTokenFullWidthShift) |
kind;
}
function smallTokenUnpackFullWidth(packedData: number): SyntaxKind {
return (packedData >> ScannerConstants.SmallTokenFullWidthShift) & ScannerConstants.SmallTokenFullWidthMask;
}
function smallTokenUnpackFullStart(packedData: number): number {
return packedData >> ScannerConstants.SmallTokenFullStartShift;
}
function largeTokenPackFullStartAndInfo(fullStart: number, triviaInfo: number): number {
return (fullStart << ScannerConstants.LargeTokenFullStartShift) | triviaInfo;
}
function largeTokenUnpackFullWidth(packedFullWidthAndKind: number) {
return packedFullWidthAndKind >> ScannerConstants.LargeTokenFullWidthShift;
}
function largeTokenUnpackFullStart(packedFullStartAndInfo: number): number {
return packedFullStartAndInfo >> ScannerConstants.LargeTokenFullStartShift;
function largeTokenUnpackLeadingTriviaInfo(packedFullWidthAndInfo: number): number {
return packedFullWidthAndInfo & ScannerConstants.TriviaMask;
}
function largeTokenUnpackHasLeadingTrivia(packed: number): boolean {
return (packed & ScannerConstants.LargeTokenLeadingTriviaBitMask) !== 0;
return largeTokenUnpackLeadingTriviaInfo(packed) !== 0;
}
function largeTokenUnpackHasTrailingTrivia(packed: number): boolean {
return (packed & ScannerConstants.LargeTokenTrailingTriviaBitMask) !== 0;
function hasComment(info: number) {
return (info & ScannerConstants.CommentTrivia) !== 0;
}
function hasNewLine(info: number) {
return (info & ScannerConstants.NewlineTrivia) !== 0;
}
function largeTokenUnpackHasLeadingNewLine(packed: number): boolean {
return hasNewLine(largeTokenUnpackLeadingTriviaInfo(packed));
}
function largeTokenUnpackHasLeadingComment(packed: number): boolean {
return (packed & ScannerConstants.LargeTokenLeadingCommentBitMask) !== 0;
}
function largeTokenUnpackHasTrailingComment(packed: number): boolean {
return (packed & ScannerConstants.LargeTokenTrailingCommentBitMask) !== 0;
}
function largeTokenUnpackTriviaInfo(packed: number): number {
return packed & ScannerConstants.LargeTokenTriviaBitMask;
return hasComment(largeTokenUnpackLeadingTriviaInfo(packed));
}
var isKeywordStartCharacter: number[] = ArrayUtilities.createArray<number>(CharacterCodes.maxAsciiCharacter, 0);
@@ -166,7 +129,7 @@ module TypeScript.Scanner {
// These tokens are contextually created based on parsing decisions. We can't reuse
// them in incremental scenarios as we may be in a context where the parser would not
// create them.
switch (token.kind()) {
switch (token.kind) {
// Created by the parser when it sees / or /= in a location where it needs an expression.
case SyntaxKind.RegularExpressionLiteral:
@@ -178,12 +141,17 @@ module TypeScript.Scanner {
case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
return true;
// Created by the parser when it sees } while parsing a template expression.
case SyntaxKind.TemplateMiddleToken:
case SyntaxKind.TemplateEndToken:
return true;
default:
return token.isKeywordConvertedToIdentifier();
}
}
var lastTokenInfo = { leadingTriviaWidth: -1, width: -1 };
var lastTokenInfo = { leadingTriviaWidth: -1 };
var lastTokenInfoTokenID: number = -1;
var triviaScanner = createScannerInternal(ts.ScriptTarget.Latest, SimpleText.fromString(""), () => { });
@@ -207,15 +175,7 @@ module TypeScript.Scanner {
return Syntax.emptyTriviaList;
}
return triviaScanner.scanTrivia(token, text, /*isTrailing:*/ false);
}
function trailingTrivia(token: IScannerToken, text: ISimpleText): ISyntaxTriviaList {
if (!token.hasTrailingTrivia()) {
return Syntax.emptyTriviaList;
}
return triviaScanner.scanTrivia(token, text, /*isTrailing:*/ true);
return triviaScanner.scanTrivia(token, text);
}
function leadingTriviaWidth(token: IScannerToken, text: ISimpleText): number {
@@ -227,15 +187,6 @@ module TypeScript.Scanner {
return lastTokenInfo.leadingTriviaWidth;
}
function trailingTriviaWidth(token: IScannerToken, text: ISimpleText): number {
if (!token.hasTrailingTrivia()) {
return 0;
}
fillSizeInfo(token, text);
return token.fullWidth() - lastTokenInfo.leadingTriviaWidth - lastTokenInfo.width;
}
function tokenIsIncrementallyUnusable(token: IScannerToken): boolean {
// No scanner tokens make their *containing node* incrementally unusable.
// Note: several scanner tokens may themselves be unusable. i.e. if the parser asks
@@ -246,50 +197,56 @@ module TypeScript.Scanner {
}
class FixedWidthTokenWithNoTrivia implements ISyntaxToken {
public _primaryExpressionBrand: any; public _memberExpressionBrand: any; public _leftHandSideExpressionBrand: any; public _postfixExpressionBrand: any; public _unaryExpressionBrand: any; public _expressionBrand: any; public _typeBrand: any;
public _primaryExpressionBrand: any; public _memberExpressionBrand: any; public _leftHandSideExpressionBrand: any; public _postfixExpressionBrand: any; public _unaryExpressionBrand: any; public _expressionBrand: any; public _typeBrand: any; public _nameBrand: any; public _propertyAssignmentBrand: any; public _propertyNameBrand: any;
public parent: ISyntaxElement;
public childCount: number;
constructor(private _packedData: number) {
constructor(private _fullStart: number, public kind: SyntaxKind) {
}
public setFullStart(fullStart: number): void {
this._packedData = fixedWidthTokenPackData(fullStart, this.kind());
this._fullStart = fullStart;
}
public childAt(index: number): ISyntaxElement { throw Errors.invalidOperation() }
public isIncrementallyUnusable(): boolean { return false; }
public isKeywordConvertedToIdentifier(): boolean { return false; }
public hasSkippedToken(): boolean { return false; }
public fullText(): string { return SyntaxFacts.getText(this.kind()); }
public fullText(): string { return SyntaxFacts.getText(this.kind); }
public text(): string { return this.fullText(); }
public leadingTrivia(): ISyntaxTriviaList { return Syntax.emptyTriviaList; }
public trailingTrivia(): ISyntaxTriviaList { return Syntax.emptyTriviaList; }
public leadingTriviaWidth(): number { return 0; }
public trailingTriviaWidth(): number { return 0; }
public kind(): SyntaxKind { return this._packedData & ScannerConstants.KindMask; }
public fullWidth(): number { return this.fullText().length; }
public fullStart(): number { return fixedWidthTokenUnpackFullStart(this._packedData); }
public fullWidth(): number { return fixedWidthTokenLength(this.kind); }
public fullStart(): number { return this._fullStart; }
public hasLeadingTrivia(): boolean { return false; }
public hasTrailingTrivia(): boolean { return false; }
public hasLeadingNewLine(): boolean { return false; }
public hasLeadingSkippedToken(): boolean { return false; }
public hasLeadingComment(): boolean { return false; }
public hasTrailingComment(): boolean { return false; }
public clone(): ISyntaxToken { return new FixedWidthTokenWithNoTrivia(this._packedData); }
public clone(): ISyntaxToken { return new FixedWidthTokenWithNoTrivia(this._fullStart, this.kind); }
}
FixedWidthTokenWithNoTrivia.prototype.childCount = 0;
class LargeScannerToken implements ISyntaxToken {
public _primaryExpressionBrand: any; public _memberExpressionBrand: any; public _leftHandSideExpressionBrand: any; public _postfixExpressionBrand: any; public _unaryExpressionBrand: any; public _expressionBrand: any; public _typeBrand: any;
public _primaryExpressionBrand: any; public _memberExpressionBrand: any; public _leftHandSideExpressionBrand: any; public _postfixExpressionBrand: any; public _unaryExpressionBrand: any; public _expressionBrand: any; public _typeBrand: any; public _nameBrand: any; public _propertyAssignmentBrand: any; public _propertyNameBrand: any;
public parent: ISyntaxElement;
public childCount: number;
private cachedText: string;
constructor(private _packedFullStartAndInfo: number, private _packedFullWidthAndKind: number, cachedText: string) {
constructor(private _fullStart: number, public kind: SyntaxKind, private _packedFullWidthAndInfo: number, cachedText: string) {
if (cachedText !== undefined) {
this.cachedText = cachedText;
}
}
public setFullStart(fullStart: number): void {
this._packedFullStartAndInfo = largeTokenPackFullStartAndInfo(fullStart,
largeTokenUnpackTriviaInfo(this._packedFullStartAndInfo));
this._fullStart = fullStart;
}
public childAt(index: number): ISyntaxElement { throw Errors.invalidOperation() }
private syntaxTreeText(text: ISimpleText) {
var result = text || syntaxTree(this).text;
Debug.assert(result);
@@ -298,7 +255,6 @@ module TypeScript.Scanner {
public isIncrementallyUnusable(): boolean { return tokenIsIncrementallyUnusable(this); }
public isKeywordConvertedToIdentifier(): boolean { return false; }
public hasSkippedToken(): boolean { return false; }
public fullText(text?: ISimpleText): string {
return fullText(this, this.syntaxTreeText(text));
@@ -306,29 +262,23 @@ module TypeScript.Scanner {
public text(): string {
var cachedText = this.cachedText;
return cachedText !== undefined ? cachedText : SyntaxFacts.getText(this.kind());
return cachedText !== undefined ? cachedText : SyntaxFacts.getText(this.kind);
}
public leadingTrivia(text?: ISimpleText): ISyntaxTriviaList { return leadingTrivia(this, this.syntaxTreeText(text)); }
public trailingTrivia(text?: ISimpleText): ISyntaxTriviaList { return trailingTrivia(this, this.syntaxTreeText(text)); }
public leadingTriviaWidth(text?: ISimpleText): number { return leadingTriviaWidth(this, this.syntaxTreeText(text)); }
public leadingTriviaWidth(text?: ISimpleText): number {
return leadingTriviaWidth(this, this.syntaxTreeText(text));
}
public fullWidth(): number { return largeTokenUnpackFullWidth(this._packedFullWidthAndInfo); }
public fullStart(): number { return this._fullStart; }
public trailingTriviaWidth(text?: ISimpleText): number {
return trailingTriviaWidth(this, this.syntaxTreeText(text));
}
public hasLeadingTrivia(): boolean { return largeTokenUnpackHasLeadingTrivia(this._packedFullWidthAndInfo); }
public hasLeadingNewLine(): boolean { return largeTokenUnpackHasLeadingNewLine(this._packedFullWidthAndInfo); }
public hasLeadingComment(): boolean { return largeTokenUnpackHasLeadingComment(this._packedFullWidthAndInfo); }
public hasLeadingSkippedToken(): boolean { return false; }
public kind(): SyntaxKind { return this._packedFullWidthAndKind & ScannerConstants.KindMask; }
public fullWidth(): number { return largeTokenUnpackFullWidth(this._packedFullWidthAndKind); }
public fullStart(): number { return largeTokenUnpackFullStart(this._packedFullStartAndInfo); }
public hasLeadingTrivia(): boolean { return largeTokenUnpackHasLeadingTrivia(this._packedFullStartAndInfo); }
public hasTrailingTrivia(): boolean { return largeTokenUnpackHasTrailingTrivia(this._packedFullStartAndInfo); }
public hasLeadingComment(): boolean { return largeTokenUnpackHasLeadingComment(this._packedFullStartAndInfo); }
public hasTrailingComment(): boolean { return largeTokenUnpackHasTrailingComment(this._packedFullStartAndInfo); }
public clone(): ISyntaxToken { return new LargeScannerToken(this._packedFullStartAndInfo, this._packedFullWidthAndKind, this.cachedText); }
public clone(): ISyntaxToken { return new LargeScannerToken(this._fullStart, this.kind, this._packedFullWidthAndInfo, this.cachedText); }
}
LargeScannerToken.prototype.childCount = 0;
export interface DiagnosticCallback {
(position: number, width: number, key: string, arguments: any[]): void;
@@ -336,12 +286,11 @@ module TypeScript.Scanner {
interface TokenInfo {
leadingTriviaWidth: number;
width: number;
}
interface IScannerInternal extends IScanner {
fillTokenInfo(token: IScannerToken, text: ISimpleText, tokenInfo: TokenInfo): void;
scanTrivia(token: IScannerToken, text: ISimpleText, isTrailing: boolean): ISyntaxTriviaList;
scanTrivia(token: IScannerToken, text: ISimpleText): ISyntaxTriviaList;
}
export interface IScanner {
@@ -368,12 +317,13 @@ module TypeScript.Scanner {
}
function reset(_text: ISimpleText, _start: number, _end: number) {
Debug.assert(_start <= _text.length(), "Token's start was not within the bounds of text: " + _start + " - [0, " + _text.length() + ")");
Debug.assert(_end <= _text.length(), "Token's end was not within the bounds of text: " + _end + " - [0, " + _text.length() + ")");
var textLength = _text.length();
Debug.assert(_start <= textLength, "Token's start was not within the bounds of text.");
Debug.assert(_end <= textLength, "Token's end was not within the bounds of text:");
if (!str || text !== _text) {
text = _text;
str = _text.substr(0, _text.length());
str = _text.substr(0, textLength);
}
start = _start;
@@ -383,15 +333,13 @@ module TypeScript.Scanner {
function scan(allowContextualToken: boolean): ISyntaxToken {
var fullStart = index;
var leadingTriviaInfo = scanTriviaInfo(/*isTrailing: */ false);
var leadingTriviaInfo = scanTriviaInfo();
var start = index;
var kindAndIsVariableWidth = scanSyntaxKind(allowContextualToken);
var end = index;
var trailingTriviaInfo = scanTriviaInfo(/*isTrailing: */true);
var fullWidth = index - fullStart;
var fullEnd = index;
var fullWidth = fullEnd - fullStart;
// If we have no trivia, and we are a fixed width token kind, and our size isn't too
// large, and we're a real fixed width token (and not something like "\u0076ar").
@@ -399,34 +347,21 @@ module TypeScript.Scanner {
var isFixedWidth = kind >= SyntaxKind.FirstFixedWidth && kind <= SyntaxKind.LastFixedWidth &&
((kindAndIsVariableWidth & ScannerConstants.IsVariableWidthMask) === 0);
if (isFixedWidth &&
leadingTriviaInfo === 0 && trailingTriviaInfo === 0 &&
fullStart <= ScannerConstants.FixedWidthTokenMaxFullStart &&
(kindAndIsVariableWidth & ScannerConstants.IsVariableWidthMask) === 0) {
return new FixedWidthTokenWithNoTrivia((fullStart << ScannerConstants.FixedWidthTokenFullStartShift) | kind);
if (isFixedWidth && leadingTriviaInfo === 0) {
return new FixedWidthTokenWithNoTrivia(fullStart, kind);
}
else {
// inline the packing logic for perf.
var packedFullStartAndTriviaInfo = (fullStart << ScannerConstants.LargeTokenFullStartShift) |
leadingTriviaInfo | (trailingTriviaInfo << 2);
var packedFullWidthAndKind = (fullWidth << ScannerConstants.LargeTokenFullWidthShift) | kind;
var cachedText = isFixedWidth ? undefined : text.substr(start, end - start);
return new LargeScannerToken(packedFullStartAndTriviaInfo, packedFullWidthAndKind, cachedText);
var packedFullWidthAndInfo = largeTokenPackData(fullWidth, leadingTriviaInfo);
var cachedText = isFixedWidth ? undefined : text.substr(start, fullEnd - start);
return new LargeScannerToken(fullStart, kind, packedFullWidthAndInfo, cachedText);
}
}
function scanTrivia(parent: IScannerToken, text: ISimpleText, isTrailing: boolean): ISyntaxTriviaList {
function scanTrivia(parent: IScannerToken, text: ISimpleText): ISyntaxTriviaList {
var tokenFullStart = parent.fullStart();
var tokenStart = tokenFullStart + leadingTriviaWidth(parent, text)
if (isTrailing) {
reset(text, tokenStart + parent.text().length, tokenFullStart + parent.fullWidth());
}
else {
reset(text, tokenFullStart, tokenStart);
}
reset(text, tokenFullStart, tokenStart);
// Debug.assert(length > 0);
// Keep this exactly in sync with scanTriviaInfo
@@ -483,15 +418,7 @@ module TypeScript.Scanner {
case CharacterCodes.paragraphSeparator:
case CharacterCodes.lineSeparator:
trivia.push(scanLineTerminatorSequenceTrivia(ch));
// If we're consuming leading trivia, then we will continue consuming more
// trivia (including newlines) up to the first token we see. If we're
// consuming trailing trivia, then we break after the first newline we see.
if (!isTrailing) {
continue;
}
break;
continue;
default:
throw Errors.invalidOperation();
@@ -508,7 +435,7 @@ module TypeScript.Scanner {
// Returns 0 if there was no trivia, or 1 if there was trivia. Returned as an int instead
// of a boolean because we'll need a numerical value later on to store in our tokens.
function scanTriviaInfo(isTrailing: boolean): number {
function scanTriviaInfo(): number {
// Keep this exactly in sync with scanTrivia
var result = 0;
var _end = end;
@@ -523,7 +450,7 @@ module TypeScript.Scanner {
case CharacterCodes.formFeed:
index++;
// we have trivia
result |= 1;
result |= ScannerConstants.WhitespaceTrivia;
continue;
case CharacterCodes.carriageReturn:
@@ -532,18 +459,12 @@ module TypeScript.Scanner {
}
// fall through.
case CharacterCodes.lineFeed:
case CharacterCodes.paragraphSeparator:
case CharacterCodes.lineSeparator:
index++;
// we have trivia
result |= 1;
// If we're consuming leading trivia, then we will continue consuming more
// trivia (including newlines) up to the first token we see. If we're
// consuming trailing trivia, then we break after the first newline we see.
if (isTrailing) {
return result;
}
result |= ScannerConstants.NewlineTrivia;
continue;
case CharacterCodes.slash:
@@ -551,14 +472,14 @@ module TypeScript.Scanner {
var ch2 = str.charCodeAt(index + 1);
if (ch2 === CharacterCodes.slash) {
// we have a comment, and we have trivia
result |= 3;
result |= ScannerConstants.CommentTrivia;
skipSingleLineCommentTrivia();
continue;
}
if (ch2 === CharacterCodes.asterisk) {
// we have a comment, and we have trivia
result |= 3;
result |= ScannerConstants.CommentTrivia;
skipMultiLineCommentTrivia();
continue;
}
@@ -568,8 +489,8 @@ module TypeScript.Scanner {
return result;
default:
if (ch > CharacterCodes.maxAsciiCharacter && slowScanTriviaInfo(ch)) {
result |= 1;
if (ch > CharacterCodes.maxAsciiCharacter && slowScanWhitespaceTriviaInfo(ch)) {
result |= ScannerConstants.WhitespaceTrivia;
continue;
}
@@ -580,7 +501,7 @@ module TypeScript.Scanner {
return result;
}
function slowScanTriviaInfo(ch: number): boolean {
function slowScanWhitespaceTriviaInfo(ch: number): boolean {
switch (ch) {
case CharacterCodes.nonBreakingSpace:
case CharacterCodes.enQuad:
@@ -598,8 +519,6 @@ module TypeScript.Scanner {
case CharacterCodes.narrowNoBreakSpace:
case CharacterCodes.ideographicSpace:
case CharacterCodes.byteOrderMark:
case CharacterCodes.paragraphSeparator:
case CharacterCodes.lineSeparator:
index++;
return true;
@@ -694,26 +613,31 @@ module TypeScript.Scanner {
return createTrivia(SyntaxKind.MultiLineCommentTrivia, absoluteStartIndex);
}
function skipMultiLineCommentTrivia(): number {
function skipMultiLineCommentTrivia(): void {
// The '2' is for the "/*" we consumed.
var _index = index + 2;
var _end = end;
index += 2;
while (true) {
if (index === end) {
reportDiagnostic(end, 0, DiagnosticCode.AsteriskSlash_expected, null);
return;
if (_index === _end) {
reportDiagnostic(end, 0, DiagnosticCode._0_expected, ["*/"]);
break;
}
if ((index + 1) < end &&
str.charCodeAt(index) === CharacterCodes.asterisk &&
str.charCodeAt(index + 1) === CharacterCodes.slash) {
if ((_index + 1) < _end &&
str.charCodeAt(_index) === CharacterCodes.asterisk &&
str.charCodeAt(_index + 1) === CharacterCodes.slash) {
index += 2;
return;
_index += 2;
break;
}
index++;
_index++;
}
index = _index;
}
function scanLineTerminatorSequenceTrivia(ch: number): ISyntaxTrivia {
@@ -742,10 +666,10 @@ module TypeScript.Scanner {
index++;
switch (character) {
case CharacterCodes.exclamation /*33*/: return scanExclamationToken();
case CharacterCodes.exclamation/*33*/: return scanExclamationToken();
case CharacterCodes.doubleQuote/*34*/: return scanStringLiteral(character);
case CharacterCodes.percent /*37*/: return scanPercentToken();
case CharacterCodes.ampersand /*38*/: return scanAmpersandToken();
case CharacterCodes.percent/*37*/: return scanPercentToken();
case CharacterCodes.ampersand/*38*/: return scanAmpersandToken();
case CharacterCodes.singleQuote/*39*/: return scanStringLiteral(character);
case CharacterCodes.openParen/*40*/: return SyntaxKind.OpenParenToken;
case CharacterCodes.closeParen/*41*/: return SyntaxKind.CloseParenToken;
@@ -771,10 +695,11 @@ module TypeScript.Scanner {
case CharacterCodes.openBracket/*91*/: return SyntaxKind.OpenBracketToken;
case CharacterCodes.closeBracket/*93*/: return SyntaxKind.CloseBracketToken;
case CharacterCodes.caret/*94*/: return scanCaretToken();
case CharacterCodes.backtick/*96*/: return scanTemplateToken(character);
case CharacterCodes.openBrace/*123*/: return SyntaxKind.OpenBraceToken;
case CharacterCodes.bar/*124*/: return scanBarToken();
case CharacterCodes.closeBrace/*125*/: return SyntaxKind.CloseBraceToken;
case CharacterCodes.closeBrace/*125*/: return scanCloseBraceToken(allowContextualToken, character);
case CharacterCodes.tilde/*126*/: return SyntaxKind.TildeToken;
}
@@ -916,7 +841,7 @@ module TypeScript.Scanner {
if (languageVersion >= ts.ScriptTarget.ES5) {
reportDiagnostic(
start, index - start, DiagnosticCode.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher, null);
start, index - start, DiagnosticCode.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher, undefined);
}
}
@@ -1073,6 +998,39 @@ module TypeScript.Scanner {
}
}
function scanCloseBraceToken(allowContextualToken: boolean, startChar: number): SyntaxKind {
return allowContextualToken ? scanTemplateToken(startChar) : SyntaxKind.CloseBraceToken;
}
function scanTemplateToken(startChar: number): SyntaxKind {
var startedWithBacktick = startChar === CharacterCodes.backtick;
while (true) {
if (index === end) {
// Hit the end of the file.
reportDiagnostic(end, 0, DiagnosticCode._0_expected, ["`"]);
break;
}
var ch = str.charCodeAt(index);
index++;
if (ch === CharacterCodes.backtick) {
break;
}
if (ch === CharacterCodes.$ &&
index < end &&
str.charCodeAt(index) === CharacterCodes.openBrace) {
index++;
return startedWithBacktick ? SyntaxKind.TemplateStartToken : SyntaxKind.TemplateMiddleToken;
}
}
return startedWithBacktick ? SyntaxKind.NoSubstitutionTemplateToken : SyntaxKind.TemplateEndToken;
}
function scanAmpersandToken(): SyntaxKind {
var character = str.charCodeAt(index);
if (character === CharacterCodes.equals) {
@@ -1223,7 +1181,7 @@ module TypeScript.Scanner {
switch (ch) {
case CharacterCodes.backslash:
// We're now in an escape. Consume the next character we see (unless it's
// a newline or null.
// a newline or undefined.
inEscape = true;
continue;
@@ -1364,7 +1322,7 @@ module TypeScript.Scanner {
break;
}
else if (isNaN(ch) || isNewLineCharacter(ch)) {
reportDiagnostic(Math.min(index, end), 1, DiagnosticCode.Missing_close_quote_character, null);
reportDiagnostic(Math.min(index, end), 1, DiagnosticCode.Missing_close_quote_character, undefined);
break;
}
else {
@@ -1431,7 +1389,7 @@ module TypeScript.Scanner {
var ch2 = str.charCodeAt(index);
if (!CharacterInfo.isHexDigit(ch2)) {
if (report) {
reportDiagnostic(start, index - start, DiagnosticCode.Unrecognized_escape_sequence, null)
reportDiagnostic(start, index - start, DiagnosticCode.Unrecognized_escape_sequence, undefined)
}
break;
@@ -1449,14 +1407,10 @@ module TypeScript.Scanner {
var fullEnd = fullStart + token.fullWidth();
reset(text, fullStart, fullEnd);
scanTriviaInfo(/*isTrailing: */ false);
scanTriviaInfo();
var start = index;
scanSyntaxKind(isContextualToken(token));
var end = index;
tokenInfo.leadingTriviaWidth = start - fullStart;
tokenInfo.width = end - start;
}
reset(text, 0, text.length());
@@ -1511,30 +1465,30 @@ module TypeScript.Scanner {
var rewindPointPool: IScannerRewindPoint[] = [];
var rewindPointPoolCount = 0;
var lastDiagnostic: Diagnostic = null;
var lastDiagnostic: Diagnostic = undefined;
var reportDiagnostic = (position: number, fullWidth: number, diagnosticKey: string, args: any[]) => {
lastDiagnostic = new Diagnostic(fileName, text.lineMap(), position, fullWidth, diagnosticKey, args);
};
// The sliding window that we store tokens in.
var slidingWindow = new SlidingWindow(fetchNextItem, ArrayUtilities.createArray(/*defaultWindowSize:*/ 1024, null), null);
var slidingWindow = new SlidingWindow(fetchNextItem, ArrayUtilities.createArray(/*defaultWindowSize:*/ 1024, undefined), undefined);
// The scanner we're pulling tokens from.
var scanner = createScanner(languageVersion, text, reportDiagnostic);
function release() {
slidingWindow = null;
scanner = null;
slidingWindow = undefined;
scanner = undefined;
_tokenDiagnostics = [];
rewindPointPool = [];
lastDiagnostic = null;
reportDiagnostic = null;
lastDiagnostic = undefined;
reportDiagnostic = undefined;
}
function currentNode(): ISyntaxNode {
// The normal parser source never returns nodes. They're only returned by the
// incremental parser source.
return null;
return undefined;
}
function consumeNode(node: ISyntaxNode): void {
@@ -1557,7 +1511,7 @@ module TypeScript.Scanner {
rewindPointPoolCount--;
var result = rewindPointPool[rewindPointPoolCount];
rewindPointPool[rewindPointPoolCount] = null;
rewindPointPool[rewindPointPoolCount] = undefined;
return result;
}
@@ -1593,7 +1547,7 @@ module TypeScript.Scanner {
// Debug.assert(spaceAvailable > 0);
var token = scanner.scan(allowContextualToken);
if (lastDiagnostic === null) {
if (lastDiagnostic === undefined) {
return token;
}
@@ -1601,7 +1555,7 @@ module TypeScript.Scanner {
// it won't be reused in incremental scenarios.
_tokenDiagnostics.push(lastDiagnostic);
lastDiagnostic = null;
lastDiagnostic = undefined;
return Syntax.realizeToken(token, text);
}
@@ -1610,6 +1564,8 @@ module TypeScript.Scanner {
}
function consumeToken(token: ISyntaxToken): void {
// Debug.assert(token.fullWidth() > 0 || token.kind === SyntaxKind.EndOfFileToken);
// Debug.assert(currentToken() === token);
_absolutePosition += token.fullWidth();
@@ -1628,22 +1584,24 @@ module TypeScript.Scanner {
var diagnostic = _tokenDiagnostics[tokenDiagnosticsLength - 1];
if (diagnostic.start() >= position) {
tokenDiagnosticsLength--;
_tokenDiagnostics.pop();
}
else {
break;
}
}
_tokenDiagnostics.length = tokenDiagnosticsLength;
}
function resetToPosition(absolutePosition: number): void {
Debug.assert(absolutePosition <= text.length(), "Trying to set the position outside the bounds of the text!");
var resetBackward = absolutePosition <= _absolutePosition;
_absolutePosition = absolutePosition;
// First, remove any diagnostics that came after this position.
removeDiagnosticsOnOrAfterPosition(absolutePosition);
if (resetBackward) {
// First, remove any diagnostics that came after this position.
removeDiagnosticsOnOrAfterPosition(absolutePosition);
}
// Now, tell our sliding window to throw away all tokens after this position as well.
slidingWindow.disgardAllItemsFromCurrentIndexOnwards();
@@ -1655,7 +1613,7 @@ module TypeScript.Scanner {
function currentContextualToken(): ISyntaxToken {
// We better be on a / or > token right now.
// Debug.assert(SyntaxFacts.isAnyDivideToken(currentToken().kind()));
// Debug.assert(SyntaxFacts.isAnyDivideToken(currentToken().kind));
// First, we're going to rewind all our data to the point where this / or /= token started.
// That's because if it does turn out to be a regular expression, then any tokens or token
@@ -1675,7 +1633,7 @@ module TypeScript.Scanner {
// We have better gotten some sort of regex token. Otherwise, something *very* wrong has
// occurred.
// Debug.assert(SyntaxFacts.isAnyDivideOrRegularExpressionToken(token.kind()));
// Debug.assert(SyntaxFacts.isAnyDivideOrRegularExpressionToken(token.kind));
return token;
}
@@ -1699,4 +1657,9 @@ module TypeScript.Scanner {
resetToPosition: resetToPosition,
};
}
var fixedWidthArray = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 4, 5, 8, 8, 7, 6, 2, 4, 5, 7, 3, 8, 2, 2, 10, 3, 4, 6, 6, 4, 5, 4, 3, 6, 3, 4, 5, 4, 5, 5, 4, 6, 7, 6, 5, 10, 9, 3, 7, 7, 9, 6, 6, 5, 3, 7, 11, 7, 3, 6, 7, 6, 3, 6, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 1, 1, 1, 1, 2, 2, 2, 2, 3, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 2, 2, 2, 1, 2];
function fixedWidthTokenLength(kind: SyntaxKind) {
return fixedWidthArray[kind];
}
}
@@ -1,8 +1,8 @@
///<reference path='references.ts' />
module TypeScript {
export class ScannerUtilities {
public static identifierKind(str: string, start: number, length: number): SyntaxKind {
export module ScannerUtilities {
export function identifierKind(str: string, start: number, length: number): SyntaxKind {
switch (length) {
case 2: // do, if, in
switch(str.charCodeAt(start)) {
+1 -1
View File
@@ -167,7 +167,7 @@ module TypeScript {
// Assert disabled because it is actually expensive enugh to affect perf.
// Debug.assert(n >= 0);
while (this.currentRelativeItemIndex + n >= this.windowCount) {
if (!this.addMoreItemsToWindow(/*argument:*/ null)) {
if (!this.addMoreItemsToWindow(/*argument:*/ undefined)) {
return this.defaultValue;
}
}
+28 -171
View File
@@ -3,24 +3,13 @@
module TypeScript.Syntax {
export var _nextSyntaxID: number = 1;
export function childIndex(parent: ISyntaxElement, child: ISyntaxElement) {
for (var i = 0, n = childCount(parent); i < n; i++) {
var current = childAt(parent, i);
if (current === child) {
return i;
}
}
throw Errors.invalidOperation();
}
export function nodeHasSkippedOrMissingTokens(node: ISyntaxNode): boolean {
for (var i = 0; i < childCount(node); i++) {
var child = childAt(node, i);
if (isToken(child)) {
var token = <ISyntaxToken>child;
// If a token is skipped, return true. Or if it is a missing token. The only empty token that is not missing is EOF
if (token.hasSkippedToken() || (width(token) === 0 && token.kind() !== SyntaxKind.EndOfFileToken)) {
if (token.hasLeadingSkippedToken() || (fullWidth(token) === 0 && token.kind !== SyntaxKind.EndOfFileToken)) {
return true;
}
}
@@ -30,7 +19,7 @@ module TypeScript.Syntax {
}
export function isUnterminatedStringLiteral(token: ISyntaxToken): boolean {
if (token && token.kind() === SyntaxKind.StringLiteral) {
if (token && token.kind === SyntaxKind.StringLiteral) {
var text = token.text();
return text.length < 2 || text.charCodeAt(text.length - 1) !== text.charCodeAt(0);
}
@@ -39,7 +28,7 @@ module TypeScript.Syntax {
}
export function isUnterminatedMultilineCommentTrivia(trivia: ISyntaxTrivia): boolean {
if (trivia && trivia.kind() === SyntaxKind.MultiLineCommentTrivia) {
if (trivia && trivia.kind === SyntaxKind.MultiLineCommentTrivia) {
var text = trivia.fullText();
return text.length < 4 || text.substring(text.length - 2) !== "*/";
}
@@ -53,145 +42,43 @@ module TypeScript.Syntax {
return true;
}
else if (position === end) {
return trivia.kind() === SyntaxKind.SingleLineCommentTrivia || isUnterminatedMultilineCommentTrivia(trivia);
return trivia.kind === SyntaxKind.SingleLineCommentTrivia || isUnterminatedMultilineCommentTrivia(trivia);
}
}
return false;
}
export function isEntirelyInsideComment(sourceUnit: SourceUnitSyntax, position: number): boolean {
var positionedToken = findToken(sourceUnit, position);
var fullStart = positionedToken.fullStart();
var triviaList: ISyntaxTriviaList = null;
var lastTriviaBeforeToken: ISyntaxTrivia = null;
if (positionedToken.kind() === SyntaxKind.EndOfFileToken) {
// Check if the trivia is leading on the EndOfFile token
if (positionedToken.hasLeadingTrivia()) {
triviaList = positionedToken.leadingTrivia();
}
// Or trailing on the previous token
else {
positionedToken = previousToken(positionedToken);
if (positionedToken) {
if (positionedToken && positionedToken.hasTrailingTrivia()) {
triviaList = positionedToken.trailingTrivia();
fullStart = end(positionedToken);
}
}
}
}
else {
if (position <= (fullStart + positionedToken.leadingTriviaWidth())) {
triviaList = positionedToken.leadingTrivia();
}
else if (position >= (fullStart + width(positionedToken))) {
triviaList = positionedToken.trailingTrivia();
fullStart = end(positionedToken);
}
}
if (triviaList) {
// Try to find the trivia matching the position
for (var i = 0, n = triviaList.count(); i < n; i++) {
var trivia = triviaList.syntaxTriviaAt(i);
if (position <= fullStart) {
// Moved passed the trivia we need
break;
}
else if (position <= fullStart + trivia.fullWidth() && trivia.isComment()) {
// Found the comment trivia we were looking for
lastTriviaBeforeToken = trivia;
break;
}
fullStart += trivia.fullWidth();
}
}
return lastTriviaBeforeToken && isEntirelyInsideCommentTrivia(lastTriviaBeforeToken, fullStart, position);
}
export function isEntirelyInStringOrRegularExpressionLiteral(sourceUnit: SourceUnitSyntax, position: number): boolean {
var positionedToken = findToken(sourceUnit, position);
if (positionedToken) {
if (positionedToken.kind() === SyntaxKind.EndOfFileToken) {
// EndOfFile token, enusre it did not follow an unterminated string literal
positionedToken = previousToken(positionedToken);
return positionedToken && positionedToken.trailingTriviaWidth() === 0 && isUnterminatedStringLiteral(positionedToken);
}
else if (position > start(positionedToken)) {
// Ensure position falls enterily within the literal if it is terminated, or the line if it is not
return (position < end(positionedToken) && (positionedToken.kind() === TypeScript.SyntaxKind.StringLiteral || positionedToken.kind() === TypeScript.SyntaxKind.RegularExpressionLiteral)) ||
(position <= end(positionedToken) && isUnterminatedStringLiteral(positionedToken));
}
}
return false;
}
function findSkippedTokenOnLeftInTriviaList(positionedToken: ISyntaxToken, position: number, lookInLeadingTriviaList: boolean): ISyntaxToken {
var triviaList: TypeScript.ISyntaxTriviaList = null;
var fullEnd: number;
if (lookInLeadingTriviaList) {
triviaList = positionedToken.leadingTrivia();
fullEnd = positionedToken.fullStart() + triviaList.fullWidth();
}
else {
triviaList = positionedToken.trailingTrivia();
fullEnd = TypeScript.fullEnd(positionedToken);
}
if (triviaList && triviaList.hasSkippedToken()) {
for (var i = triviaList.count() - 1; i >= 0; i--) {
var trivia = triviaList.syntaxTriviaAt(i);
var triviaWidth = trivia.fullWidth();
if (trivia.isSkippedToken() && position >= fullEnd) {
return trivia.skippedToken();
}
fullEnd -= triviaWidth;
}
}
return null;
}
export function findSkippedTokenOnLeft(positionedToken: ISyntaxToken, position: number): ISyntaxToken {
var positionInLeadingTriviaList = (position < start(positionedToken));
return findSkippedTokenOnLeftInTriviaList(positionedToken, position, /*lookInLeadingTriviaList*/ positionInLeadingTriviaList);
}
export function getAncestorOfKind(positionedToken: ISyntaxElement, kind: SyntaxKind): ISyntaxElement {
while (positionedToken && positionedToken.parent) {
if (positionedToken.parent.kind() === kind) {
if (positionedToken.parent.kind === kind) {
return positionedToken.parent;
}
positionedToken = positionedToken.parent;
}
return null;
return undefined;
}
export function hasAncestorOfKind(positionedToken: ISyntaxElement, kind: SyntaxKind): boolean {
return getAncestorOfKind(positionedToken, kind) !== null;
return !!getAncestorOfKind(positionedToken, kind);
}
export function isIntegerLiteral(expression: IExpressionSyntax): boolean {
if (expression) {
switch (expression.kind()) {
case SyntaxKind.PlusExpression:
case SyntaxKind.NegateExpression:
// Note: if there is a + or - sign, we can only allow a normal integer following
// (and not a hex integer). i.e. -0xA is a legal expression, but it is not a
// *literal*.
expression = (<PrefixUnaryExpressionSyntax>expression).operand;
return isToken(expression) && IntegerUtilities.isInteger((<ISyntaxToken>expression).text());
switch (expression.kind) {
case SyntaxKind.PrefixUnaryExpression:
var prefixExpr = <PrefixUnaryExpressionSyntax>expression;
if (prefixExpr.operatorToken.kind == SyntaxKind.PlusToken || prefixExpr.operatorToken.kind === SyntaxKind.MinusToken) {
// Note: if there is a + or - sign, we can only allow a normal integer following
// (and not a hex integer). i.e. -0xA is a legal expression, but it is not a
// *literal*.
expression = prefixExpr.operand;
return isToken(expression) && IntegerUtilities.isInteger((<ISyntaxToken>expression).text());
}
return false;
case SyntaxKind.NumericLiteral:
// If it doesn't have a + or -, then either an integer literal or a hex literal
@@ -207,25 +94,21 @@ module TypeScript.Syntax {
export function containingNode(element: ISyntaxElement): ISyntaxNode {
var current = element.parent;
while (current !== null && !isNode(current)) {
while (current && !isNode(current)) {
current = current.parent;
}
return <ISyntaxNode>current;
}
export function findTokenOnLeft(element: ISyntaxElement, position: number, includeSkippedTokens: boolean = false): ISyntaxToken {
var positionedToken = findToken(element, position, /*includeSkippedTokens*/ false);
export function findTokenOnLeft(sourceUnit: SourceUnitSyntax, position: number): ISyntaxToken {
var positionedToken = findToken(sourceUnit, position);
var _start = start(positionedToken);
// Position better fall within this token.
// Debug.assert(position >= positionedToken.fullStart());
// Debug.assert(position < positionedToken.fullEnd() || positionedToken.token().tokenKind === SyntaxKind.EndOfFileToken);
if (includeSkippedTokens) {
positionedToken = findSkippedTokenOnLeft(positionedToken, position) || positionedToken;
}
// if position is after the start of the token, then this token is the token on the left.
if (position > _start) {
return positionedToken;
@@ -234,50 +117,24 @@ module TypeScript.Syntax {
// we're in the trivia before the start of the token. Need to return the previous token.
if (positionedToken.fullStart() === 0) {
// Already on the first token. Nothing before us.
return null;
return undefined;
}
return previousToken(positionedToken, includeSkippedTokens);
return previousToken(positionedToken);
}
export function findCompleteTokenOnLeft(element: ISyntaxElement, position: number, includeSkippedTokens: boolean = false): ISyntaxToken {
var positionedToken = findToken(element, position, /*includeSkippedTokens*/ false);
export function findCompleteTokenOnLeft(sourceUnit: SourceUnitSyntax, position: number): ISyntaxToken {
var positionedToken = findToken(sourceUnit, position);
// Position better fall within this token.
// Debug.assert(position >= positionedToken.fullStart());
// Debug.assert(position < positionedToken.fullEnd() || positionedToken.token().tokenKind === SyntaxKind.EndOfFileToken);
if (includeSkippedTokens) {
positionedToken = findSkippedTokenOnLeft(positionedToken, position) || positionedToken;
}
// if position is after the end of the token, then this token is the token on the left.
if (width(positionedToken) > 0 && position >= end(positionedToken)) {
if (width(positionedToken) > 0 && position >= fullEnd(positionedToken)) {
return positionedToken;
}
return previousToken(positionedToken, includeSkippedTokens);
}
export function firstTokenInLineContainingPosition(syntaxTree: SyntaxTree, position: number): ISyntaxToken {
var current = findToken(syntaxTree.sourceUnit(), position);
while (true) {
if (isFirstTokenInLine(current, syntaxTree.lineMap())) {
break;
}
current = previousToken(current);
}
return current;
}
function isFirstTokenInLine(token: ISyntaxToken, lineMap: LineMap): boolean {
var _previousToken = previousToken(token);
if (_previousToken === null) {
return true;
}
return lineMap.getLineNumberFromPosition(end(_previousToken)) !== lineMap.getLineNumberFromPosition(start(token));
return previousToken(positionedToken);
}
}
+156 -254
View File
@@ -1,52 +1,12 @@
///<reference path='references.ts' />
module TypeScript {
// True if there is only a single instance of this element (and thus can be reused in many
// places in a syntax tree). Examples of this include our empty lists. Because empty
// lists can be found all over the tree, we want to save on memory by using this single
// instance instead of creating new objects for each case. Note: because of this, shared
// nodes don't have positions or parents.
export function isShared(element: ISyntaxElement): boolean {
var kind = element.kind();
return (kind === SyntaxKind.List || kind === SyntaxKind.SeparatedList) && (<ISyntaxNodeOrToken[]>element).length === 0;
}
export function childCount(element: ISyntaxElement): number {
var kind = element.kind();
if (kind === SyntaxKind.List) {
return (<ISyntaxNodeOrToken[]>element).length;
}
else if (kind === SyntaxKind.SeparatedList) {
return (<ISyntaxNodeOrToken[]>element).length + (<ISyntaxNodeOrToken[]>element).separators.length;
}
else if (kind >= SyntaxKind.FirstToken && kind <= SyntaxKind.LastToken) {
return 0;
}
else {
return nodeMetadata[kind].length;
}
}
export function childAt(element: ISyntaxElement, index: number): ISyntaxElement {
var kind = element.kind();
if (kind === SyntaxKind.List) {
return (<ISyntaxNodeOrToken[]>element)[index];
}
else if (kind === SyntaxKind.SeparatedList) {
return (index % 2 === 0) ? (<ISyntaxNodeOrToken[]>element)[index / 2] : (<ISyntaxNodeOrToken[]>element).separators[(index - 1) / 2];
}
else {
// Debug.assert(isNode(element));
return (<any>element)[nodeMetadata[element.kind()][index]];
}
}
export function syntaxTree(element: ISyntaxElement): SyntaxTree {
if (element) {
Debug.assert(!isShared(element));
// Debug.assert(!isShared(element));
while (element) {
if (element.kind() === SyntaxKind.SourceUnit) {
if (element.kind === SyntaxKind.SourceUnit) {
return (<SourceUnitSyntax>element).syntaxTree;
}
@@ -54,11 +14,11 @@ module TypeScript {
}
}
return null;
return undefined;
}
export function parsedInStrictMode(node: ISyntaxNode): boolean {
var info = node.data;
var info = node.__data;
if (info === undefined) {
return false;
}
@@ -66,28 +26,13 @@ module TypeScript {
return (info & SyntaxConstants.NodeParsedInStrictModeMask) !== 0;
}
export function previousToken(token: ISyntaxToken, includeSkippedTokens: boolean = false): ISyntaxToken {
if (includeSkippedTokens) {
var triviaList = token.leadingTrivia();
if (triviaList && triviaList.hasSkippedToken()) {
var currentTriviaEndPosition = TypeScript.start(token);
for (var i = triviaList.count() - 1; i >= 0; i--) {
var trivia = triviaList.syntaxTriviaAt(i);
if (trivia.isSkippedToken()) {
return trivia.skippedToken();
}
currentTriviaEndPosition -= trivia.fullWidth();
}
}
}
export function previousToken(token: ISyntaxToken): ISyntaxToken {
var start = token.fullStart();
if (start === 0) {
return null;
return undefined;
}
return findToken(syntaxTree(token).sourceUnit(), start - 1, includeSkippedTokens);
return findToken(syntaxTree(token).sourceUnit(), start - 1);
}
/**
@@ -103,136 +48,98 @@ module TypeScript {
* Note: findToken will always return a non-missing token with width greater than or equal to
* 1 (except for EOF). Empty tokens synthesized by the parser are never returned.
*/
export function findToken(element: ISyntaxElement, position: number, includeSkippedTokens: boolean = false): ISyntaxToken {
var endOfFileToken = tryGetEndOfFileAt(element, position);
if (endOfFileToken !== null) {
return endOfFileToken;
}
if (position < 0 || position >= fullWidth(element)) {
export function findToken(sourceUnit: SourceUnitSyntax, position: number): ISyntaxToken {
if (position < 0) {
throw Errors.argumentOutOfRange("position");
}
var positionedToken = findTokenWorker(element, position);
if (includeSkippedTokens) {
return findSkippedTokenInPositionedToken(positionedToken, position) || positionedToken;
var token = findTokenInNodeOrToken(sourceUnit, 0, position);
if (token) {
Debug.assert(token.fullWidth() > 0);
return token;
}
// Could not find a better match
return positionedToken;
}
export function findSkippedTokenInPositionedToken(positionedToken: ISyntaxToken, position: number): ISyntaxToken {
var positionInLeadingTriviaList = (position < start(positionedToken));
return findSkippedTokenInTriviaList(positionedToken, position, /*lookInLeadingTriviaList*/ positionInLeadingTriviaList);
}
export function findSkippedTokenInLeadingTriviaList(positionedToken: ISyntaxToken, position: number): ISyntaxToken {
return findSkippedTokenInTriviaList(positionedToken, position, /*lookInLeadingTriviaList*/ true);
}
export function findSkippedTokenInTrailingTriviaList(positionedToken: ISyntaxToken, position: number): ISyntaxToken {
return findSkippedTokenInTriviaList(positionedToken, position, /*lookInLeadingTriviaList*/ false);
}
function findSkippedTokenInTriviaList(positionedToken: ISyntaxToken, position: number, lookInLeadingTriviaList: boolean): ISyntaxToken {
var triviaList: TypeScript.ISyntaxTriviaList = null;
var fullStart: number;
if (lookInLeadingTriviaList) {
triviaList = positionedToken.leadingTrivia();
fullStart = positionedToken.fullStart();
}
else {
triviaList = positionedToken.trailingTrivia();
fullStart = end(positionedToken);
if (position === fullWidth(sourceUnit)) {
return sourceUnit.endOfFileToken;
}
if (triviaList && triviaList.hasSkippedToken()) {
for (var i = 0, n = triviaList.count(); i < n; i++) {
var trivia = triviaList.syntaxTriviaAt(i);
var triviaWidth = trivia.fullWidth();
if (trivia.isSkippedToken() && position >= fullStart && position <= fullStart + triviaWidth) {
return trivia.skippedToken();
}
fullStart += triviaWidth;
}
}
return null;
}
function findTokenWorker(element: ISyntaxElement, position: number): ISyntaxToken {
// Debug.assert(position >= 0 && position < this.fullWidth());
if (isToken(element)) {
Debug.assert(fullWidth(element) > 0);
return <ISyntaxToken>element;
}
if (isShared(element)) {
// This should never have been called on this element. It has a 0 width, so the client
// should have skipped over this.
throw Errors.invalidOperation();
}
// Consider: we could use a binary search here to find the child more quickly.
for (var i = 0, n = childCount(element); i < n; i++) {
var child = childAt(element, i);
if (child !== null) {
var childFullWidth = fullWidth(child);
if (childFullWidth > 0) {
var childFullStart = fullStart(child);
if (position >= childFullStart) {
var childFullEnd = childFullStart + childFullWidth;
if (position < childFullEnd) {
return findTokenWorker(child, position);
}
}
}
}
if (position > fullWidth(sourceUnit)) {
throw Errors.argumentOutOfRange("position");
}
throw Errors.invalidOperation();
}
function findTokenWorker(element: ISyntaxElement, elementPosition: number, position: number): ISyntaxToken {
if (isList(element)) {
return findTokenInList(<ISyntaxNodeOrToken[]>element, elementPosition, position);
}
else {
return findTokenInNodeOrToken(<ISyntaxNodeOrToken>element, elementPosition, position);
}
}
function findTokenInList(list: ISyntaxNodeOrToken[], elementPosition: number, position: number): ISyntaxToken {
for (var i = 0, n = list.length; i < n; i++) {
var child = list[i];
var childFullWidth = fullWidth(child);
var elementEndPosition = elementPosition + childFullWidth;
if (position < elementEndPosition) {
return findTokenWorker(child, elementPosition, position);
}
elementPosition = elementEndPosition;
}
return undefined;
}
function findTokenInNodeOrToken(nodeOrToken: ISyntaxNodeOrToken, elementPosition: number, position: number): ISyntaxToken {
if (isToken(nodeOrToken)) {
return <ISyntaxToken>nodeOrToken;
}
for (var i = 0, n = childCount(nodeOrToken); i < n; i++) {
var child = nodeOrToken.childAt(i);
if (child) {
var childFullWidth = fullWidth(child);
var elementEndPosition = elementPosition + childFullWidth;
if (position < elementEndPosition) {
return findTokenWorker(child, elementPosition, position);
}
elementPosition = elementEndPosition;
}
}
return undefined;
}
function tryGetEndOfFileAt(element: ISyntaxElement, position: number): ISyntaxToken {
if (element.kind() === SyntaxKind.SourceUnit && position === fullWidth(element)) {
if (element.kind === SyntaxKind.SourceUnit && position === fullWidth(element)) {
var sourceUnit = <SourceUnitSyntax>element;
return sourceUnit.endOfFileToken;
}
return null;
return undefined;
}
export function nextToken(token: ISyntaxToken, text?: ISimpleText, includeSkippedTokens: boolean = false): ISyntaxToken {
if (token.kind() === SyntaxKind.EndOfFileToken) {
return null;
export function nextToken(token: ISyntaxToken, text?: ISimpleText): ISyntaxToken {
if (token.kind === SyntaxKind.EndOfFileToken) {
return undefined;
}
if (includeSkippedTokens) {
var triviaList = token.trailingTrivia(text);
if (triviaList && triviaList.hasSkippedToken()) {
for (var i = 0, n = triviaList.count(); i < n; i++) {
var trivia = triviaList.syntaxTriviaAt(i);
if (trivia.isSkippedToken()) {
return trivia.skippedToken();
}
}
}
}
return findToken(syntaxTree(token).sourceUnit(), fullEnd(token), includeSkippedTokens);
return findToken(syntaxTree(token).sourceUnit(), fullEnd(token));
}
export function isNode(element: ISyntaxElement): boolean {
if (element !== null) {
var kind = element.kind();
if (element) {
var kind = element.kind;
return kind >= SyntaxKind.FirstNode && kind <= SyntaxKind.LastNode;
}
@@ -244,25 +151,21 @@ module TypeScript {
}
export function isToken(element: ISyntaxElement): boolean {
if (element !== null) {
return isTokenKind(element.kind());
if (element) {
return isTokenKind(element.kind);
}
return false;
}
export function isList(element: ISyntaxElement): boolean {
return element !== null && element.kind() === SyntaxKind.List;
}
export function isSeparatedList(element: ISyntaxElement): boolean {
return element !== null && element.kind() === SyntaxKind.SeparatedList;
return element instanceof Array;
}
export function syntaxID(element: ISyntaxElement): number {
if (isShared(element)) {
throw Errors.invalidOperation("Should not use shared syntax element as a key.");
}
//if (isShared(element)) {
// throw Errors.invalidOperation("Should not use shared syntax element as a key.");
//}
var obj = <any>element;
if (obj._syntaxID === undefined) {
@@ -301,69 +204,37 @@ module TypeScript {
return token ? token.leadingTriviaWidth(text) : 0;
}
export function trailingTriviaWidth(element: ISyntaxElement, text?: ISimpleText): number {
var token = lastToken(element);
return token ? token.trailingTriviaWidth(text) : 0;
}
export function firstToken(element: ISyntaxElement): ISyntaxToken {
if (element) {
var kind = element.kind();
var kind = element.kind;
if (isTokenKind(kind)) {
return fullWidth(element) > 0 || element.kind() === SyntaxKind.EndOfFileToken ? <ISyntaxToken>element : null;
return (<ISyntaxToken>element).fullWidth() > 0 || kind === SyntaxKind.EndOfFileToken ? <ISyntaxToken>element : undefined;
}
if (kind === SyntaxKind.List) {
var array = <ISyntaxNodeOrToken[]>element;
for (var i = 0, n = array.length; i < n; i++) {
var token = firstToken(array[i]);
if (token) {
return token;
}
}
}
else if (kind === SyntaxKind.SeparatedList) {
var array = <ISyntaxNodeOrToken[]>element;
var separators = array.separators;
for (var i = 0, n = array.length + separators.length; i < n; i++) {
var token = firstToken(i % 2 === 0 ? array[i / 2] : separators[(i - 1) / 2]);
if (token) {
return token;
}
}
}
else {
var metadata = nodeMetadata[kind];
for (var i = 0, n = metadata.length; i < n; i++) {
var child = (<any>element)[metadata[i]];
var token = firstToken(child);
if (token) {
return token;
}
}
if (element.kind() === SyntaxKind.SourceUnit) {
return (<SourceUnitSyntax>element).endOfFileToken;
for (var i = 0, n = childCount(element); i < n; i++) {
var token = firstToken(childAt(element, i));
if (token) {
return token;
}
}
}
return null;
return undefined;
}
export function lastToken(element: ISyntaxElement): ISyntaxToken {
if (isToken(element)) {
return fullWidth(element) > 0 || element.kind() === SyntaxKind.EndOfFileToken ? <ISyntaxToken>element : null;
return fullWidth(element) > 0 || element.kind === SyntaxKind.EndOfFileToken ? <ISyntaxToken>element : undefined;
}
if (element.kind() === SyntaxKind.SourceUnit) {
if (element.kind === SyntaxKind.SourceUnit) {
return (<SourceUnitSyntax>element).endOfFileToken;
}
for (var i = childCount(element) - 1; i >= 0; i--) {
var child = childAt(element, i);
if (child !== null) {
if (child) {
var token = lastToken(child);
if (token) {
return token;
@@ -371,11 +242,11 @@ module TypeScript {
}
}
return null;
return undefined;
}
export function fullStart(element: ISyntaxElement): number {
Debug.assert(!isShared(element));
// Debug.assert(!isShared(element));
var token = isToken(element) ? <ISyntaxToken>element : firstToken(element);
return token ? token.fullStart() : -1;
}
@@ -385,10 +256,6 @@ module TypeScript {
return (<ISyntaxToken>element).fullWidth();
}
if (isShared(element)) {
return 0;
}
var info = data(element);
return info >>> SyntaxConstants.NodeFullWidthShift;
}
@@ -398,54 +265,74 @@ module TypeScript {
return (<ISyntaxToken>element).isIncrementallyUnusable();
}
if (isShared(element)) {
// All shared lists are reusable.
return false;
}
return (data(element) & SyntaxConstants.NodeIncrementallyUnusableMask) !== 0;
}
function data(element: ISyntaxElement): number {
Debug.assert(isNode(element) || isList(element) || isSeparatedList(element));
// Debug.assert(isNode(element) || isList(element));
// Lists and nodes all have a 'data' element.
var dataElement = <{ data: number }><any>element;
var dataElement = <ISyntaxNode>element;
var info = dataElement.data;
var info = dataElement.__data;
if (info === undefined) {
info = 0;
}
if ((info & SyntaxConstants.NodeDataComputed) === 0) {
info |= computeData(element);
dataElement.data = info;
dataElement.__data = info;
}
return info;
}
function computeData(element: ISyntaxElement): number {
var slotCount = childCount(element);
function combineData(fullWidth: number, isIncrementallyUnusable: boolean) {
return (fullWidth << SyntaxConstants.NodeFullWidthShift)
| (isIncrementallyUnusable ? SyntaxConstants.NodeIncrementallyUnusableMask : 0)
| SyntaxConstants.NodeDataComputed;
}
function listComputeData(list: ISyntaxNodeOrToken[]): number {
var fullWidth = 0;
var isIncrementallyUnusable = false;
for (var i = 0, n = list.length; i < n; i++) {
var child: ISyntaxElement = list[i];
fullWidth += TypeScript.fullWidth(child);
isIncrementallyUnusable = isIncrementallyUnusable || TypeScript.isIncrementallyUnusable(child);
}
return combineData(fullWidth, isIncrementallyUnusable);
}
function computeData(element: ISyntaxElement): number {
if (isList(element)) {
return listComputeData(<ISyntaxNodeOrToken[]>element);
}
else {
return nodeOrTokenComputeData(<ISyntaxNodeOrToken>element);
}
}
function nodeOrTokenComputeData(nodeOrToken: ISyntaxNodeOrToken) {
var fullWidth = 0;
var slotCount = nodeOrToken.childCount;
// If we have no children (like an OmmittedExpressionSyntax), we're automatically not reusable.
var isIncrementallyUnusable = slotCount === 0;
for (var i = 0, n = slotCount; i < n; i++) {
var child = childAt(element, i);
var child = nodeOrToken.childAt(i);
if (child) {
fullWidth += TypeScript.fullWidth(child);
isIncrementallyUnusable = isIncrementallyUnusable || TypeScript.isIncrementallyUnusable(child);
}
}
return (fullWidth << SyntaxConstants.NodeFullWidthShift)
| (isIncrementallyUnusable ? SyntaxConstants.NodeIncrementallyUnusableMask : 0)
| SyntaxConstants.NodeDataComputed;
return combineData(fullWidth, isIncrementallyUnusable);
}
export function start(element: ISyntaxElement, text?: ISimpleText): number {
@@ -453,16 +340,11 @@ module TypeScript {
return token ? token.fullStart() + token.leadingTriviaWidth(text) : -1;
}
export function end(element: ISyntaxElement, text?: ISimpleText): number {
var token = isToken(element) ? <ISyntaxToken>element : lastToken(element);
return token ? fullEnd(token) - token.trailingTriviaWidth(text) : -1;
}
export function width(element: ISyntaxElement, text?: ISimpleText): number {
if (isToken(element)) {
return (<ISyntaxToken>element).text().length;
}
return fullWidth(element) - leadingTriviaWidth(element, text) - trailingTriviaWidth(element, text);
return fullWidth(element) - leadingTriviaWidth(element, text);
}
export function fullEnd(element: ISyntaxElement): number {
@@ -474,21 +356,22 @@ module TypeScript {
return false;
}
if (token1 === null || token2 === null) {
if (!token1 || !token2) {
return true;
}
var lineMap = text.lineMap();
return lineMap.getLineNumberFromPosition(end(token1, text)) !== lineMap.getLineNumberFromPosition(start(token2, text));
return lineMap.getLineNumberFromPosition(fullEnd(token1)) !== lineMap.getLineNumberFromPosition(start(token2, text));
}
export interface ISyntaxElement {
kind(): SyntaxKind;
parent?: ISyntaxElement;
kind: SyntaxKind;
parent: ISyntaxElement;
}
export interface ISyntaxNode extends ISyntaxNodeOrToken {
data: number;
__data: number;
__cachedTokens: ISyntaxToken[];
}
export interface IModuleReferenceSyntax extends ISyntaxNode {
@@ -496,6 +379,7 @@ module TypeScript {
}
export interface IModuleElementSyntax extends ISyntaxNode {
_moduleElementBrand: any;
}
export interface IStatementSyntax extends IModuleElementSyntax {
@@ -503,15 +387,28 @@ module TypeScript {
}
export interface ITypeMemberSyntax extends ISyntaxNode {
_typeMemberBrand: any;
}
export interface IClassElementSyntax extends ISyntaxNode {
_classElementBrand: any;
}
export interface IMemberDeclarationSyntax extends IClassElementSyntax {
_memberDeclarationBrand: any;
}
export interface IPropertyAssignmentSyntax extends IClassElementSyntax {
export interface IPropertyAssignmentSyntax extends ISyntaxNodeOrToken {
_propertyAssignmentBrand: any;
}
export interface IAccessorSyntax extends IPropertyAssignmentSyntax, IMemberDeclarationSyntax {
_accessorBrand: any;
modifiers: ISyntaxToken[];
propertyName: IPropertyNameSyntax;
callSignature: CallSignatureSyntax;
block: BlockSyntax;
}
export interface ISwitchClauseSyntax extends ISyntaxNode {
@@ -553,5 +450,10 @@ module TypeScript {
}
export interface INameSyntax extends ITypeSyntax {
_nameBrand: any;
}
export interface IPropertyNameSyntax extends ISyntaxNodeOrToken {
_propertyNameBrand: any;
}
}
+51 -105
View File
@@ -134,7 +134,7 @@ module TypeScript.SyntaxFacts {
export function getText(kind: SyntaxKind): string {
var result = kindToText[kind];
return result !== undefined ? result : null;
return result;// !== undefined ? result : undefined;
}
export function isAnyKeyword(kind: SyntaxKind): boolean {
@@ -146,114 +146,60 @@ module TypeScript.SyntaxFacts {
}
export function isPrefixUnaryExpressionOperatorToken(tokenKind: SyntaxKind): boolean {
return getPrefixUnaryExpressionFromOperatorToken(tokenKind) !== SyntaxKind.None;
switch (tokenKind) {
case SyntaxKind.PlusToken:
case SyntaxKind.MinusToken:
case SyntaxKind.TildeToken:
case SyntaxKind.ExclamationToken:
case SyntaxKind.PlusPlusToken:
case SyntaxKind.MinusMinusToken:
return true;
default:
return false;
}
}
export function isBinaryExpressionOperatorToken(tokenKind: SyntaxKind): boolean {
return getBinaryExpressionFromOperatorToken(tokenKind) !== SyntaxKind.None;
}
export function getPrefixUnaryExpressionFromOperatorToken(tokenKind: SyntaxKind): SyntaxKind {
switch (tokenKind) {
case SyntaxKind.PlusToken: return SyntaxKind.PlusExpression;
case SyntaxKind.MinusToken: return SyntaxKind.NegateExpression;
case SyntaxKind.TildeToken: return SyntaxKind.BitwiseNotExpression;
case SyntaxKind.ExclamationToken: return SyntaxKind.LogicalNotExpression;
case SyntaxKind.PlusPlusToken: return SyntaxKind.PreIncrementExpression;
case SyntaxKind.MinusMinusToken: return SyntaxKind.PreDecrementExpression;
default: return SyntaxKind.None;
}
}
export function getPostfixUnaryExpressionFromOperatorToken(tokenKind: SyntaxKind): SyntaxKind {
switch (tokenKind) {
case SyntaxKind.PlusPlusToken: return SyntaxKind.PostIncrementExpression;
case SyntaxKind.MinusMinusToken: return SyntaxKind.PostDecrementExpression;
default: return SyntaxKind.None;
}
}
export function getBinaryExpressionFromOperatorToken(tokenKind: SyntaxKind): SyntaxKind {
switch (tokenKind) {
case SyntaxKind.AsteriskToken: return SyntaxKind.MultiplyExpression;
case SyntaxKind.SlashToken: return SyntaxKind.DivideExpression;
case SyntaxKind.PercentToken: return SyntaxKind.ModuloExpression;
case SyntaxKind.PlusToken: return SyntaxKind.AddExpression;
case SyntaxKind.MinusToken: return SyntaxKind.SubtractExpression;
case SyntaxKind.LessThanLessThanToken: return SyntaxKind.LeftShiftExpression;
case SyntaxKind.GreaterThanGreaterThanToken: return SyntaxKind.SignedRightShiftExpression;
case SyntaxKind.GreaterThanGreaterThanGreaterThanToken: return SyntaxKind.UnsignedRightShiftExpression;
case SyntaxKind.LessThanToken: return SyntaxKind.LessThanExpression;
case SyntaxKind.GreaterThanToken: return SyntaxKind.GreaterThanExpression;
case SyntaxKind.LessThanEqualsToken: return SyntaxKind.LessThanOrEqualExpression;
case SyntaxKind.GreaterThanEqualsToken: return SyntaxKind.GreaterThanOrEqualExpression;
case SyntaxKind.InstanceOfKeyword: return SyntaxKind.InstanceOfExpression;
case SyntaxKind.InKeyword: return SyntaxKind.InExpression;
case SyntaxKind.EqualsEqualsToken: return SyntaxKind.EqualsWithTypeConversionExpression;
case SyntaxKind.ExclamationEqualsToken: return SyntaxKind.NotEqualsWithTypeConversionExpression;
case SyntaxKind.EqualsEqualsEqualsToken: return SyntaxKind.EqualsExpression;
case SyntaxKind.ExclamationEqualsEqualsToken: return SyntaxKind.NotEqualsExpression;
case SyntaxKind.AmpersandToken: return SyntaxKind.BitwiseAndExpression;
case SyntaxKind.CaretToken: return SyntaxKind.BitwiseExclusiveOrExpression;
case SyntaxKind.BarToken: return SyntaxKind.BitwiseOrExpression;
case SyntaxKind.AmpersandAmpersandToken: return SyntaxKind.LogicalAndExpression;
case SyntaxKind.BarBarToken: return SyntaxKind.LogicalOrExpression;
case SyntaxKind.BarEqualsToken: return SyntaxKind.OrAssignmentExpression;
case SyntaxKind.AmpersandEqualsToken: return SyntaxKind.AndAssignmentExpression;
case SyntaxKind.CaretEqualsToken: return SyntaxKind.ExclusiveOrAssignmentExpression;
case SyntaxKind.LessThanLessThanEqualsToken: return SyntaxKind.LeftShiftAssignmentExpression;
case SyntaxKind.GreaterThanGreaterThanEqualsToken: return SyntaxKind.SignedRightShiftAssignmentExpression;
case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: return SyntaxKind.UnsignedRightShiftAssignmentExpression;
case SyntaxKind.PlusEqualsToken: return SyntaxKind.AddAssignmentExpression;
case SyntaxKind.MinusEqualsToken: return SyntaxKind.SubtractAssignmentExpression;
case SyntaxKind.AsteriskEqualsToken: return SyntaxKind.MultiplyAssignmentExpression;
case SyntaxKind.SlashEqualsToken: return SyntaxKind.DivideAssignmentExpression;
case SyntaxKind.PercentEqualsToken: return SyntaxKind.ModuloAssignmentExpression;
case SyntaxKind.EqualsToken: return SyntaxKind.AssignmentExpression;
case SyntaxKind.CommaToken: return SyntaxKind.CommaExpression;
default: return SyntaxKind.None;
}
}
export function getOperatorTokenFromBinaryExpression(tokenKind: SyntaxKind): SyntaxKind {
switch (tokenKind) {
case SyntaxKind.MultiplyExpression: return SyntaxKind.AsteriskToken;
case SyntaxKind.DivideExpression: return SyntaxKind.SlashToken;
case SyntaxKind.ModuloExpression: return SyntaxKind.PercentToken;
case SyntaxKind.AddExpression: return SyntaxKind.PlusToken;
case SyntaxKind.SubtractExpression: return SyntaxKind.MinusToken;
case SyntaxKind.LeftShiftExpression: return SyntaxKind.LessThanLessThanToken;
case SyntaxKind.SignedRightShiftExpression: return SyntaxKind.GreaterThanGreaterThanToken;
case SyntaxKind.UnsignedRightShiftExpression: return SyntaxKind.GreaterThanGreaterThanGreaterThanToken;
case SyntaxKind.LessThanExpression: return SyntaxKind.LessThanToken;
case SyntaxKind.GreaterThanExpression: return SyntaxKind.GreaterThanToken;
case SyntaxKind.LessThanOrEqualExpression: return SyntaxKind.LessThanEqualsToken;
case SyntaxKind.GreaterThanOrEqualExpression: return SyntaxKind.GreaterThanEqualsToken;
case SyntaxKind.InstanceOfExpression: return SyntaxKind.InstanceOfKeyword;
case SyntaxKind.InExpression: return SyntaxKind.InKeyword;
case SyntaxKind.EqualsWithTypeConversionExpression: return SyntaxKind.EqualsEqualsToken;
case SyntaxKind.NotEqualsWithTypeConversionExpression: return SyntaxKind.ExclamationEqualsToken;
case SyntaxKind.EqualsExpression: return SyntaxKind.EqualsEqualsEqualsToken;
case SyntaxKind.NotEqualsExpression: return SyntaxKind.ExclamationEqualsEqualsToken;
case SyntaxKind.BitwiseAndExpression: return SyntaxKind.AmpersandToken;
case SyntaxKind.BitwiseExclusiveOrExpression: return SyntaxKind.CaretToken;
case SyntaxKind.BitwiseOrExpression: return SyntaxKind.BarToken;
case SyntaxKind.LogicalAndExpression: return SyntaxKind.AmpersandAmpersandToken;
case SyntaxKind.LogicalOrExpression: return SyntaxKind.BarBarToken;
case SyntaxKind.OrAssignmentExpression: return SyntaxKind.BarEqualsToken;
case SyntaxKind.AndAssignmentExpression: return SyntaxKind.AmpersandEqualsToken;
case SyntaxKind.ExclusiveOrAssignmentExpression: return SyntaxKind.CaretEqualsToken;
case SyntaxKind.LeftShiftAssignmentExpression: return SyntaxKind.LessThanLessThanEqualsToken;
case SyntaxKind.SignedRightShiftAssignmentExpression: return SyntaxKind.GreaterThanGreaterThanEqualsToken;
case SyntaxKind.UnsignedRightShiftAssignmentExpression: return SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken;
case SyntaxKind.AddAssignmentExpression: return SyntaxKind.PlusEqualsToken;
case SyntaxKind.SubtractAssignmentExpression: return SyntaxKind.MinusEqualsToken;
case SyntaxKind.MultiplyAssignmentExpression: return SyntaxKind.AsteriskEqualsToken;
case SyntaxKind.DivideAssignmentExpression: return SyntaxKind.SlashEqualsToken;
case SyntaxKind.ModuloAssignmentExpression: return SyntaxKind.PercentEqualsToken;
case SyntaxKind.AssignmentExpression: return SyntaxKind.EqualsToken;
case SyntaxKind.CommaExpression: return SyntaxKind.CommaToken;
default: return SyntaxKind.None;
case SyntaxKind.AsteriskToken:
case SyntaxKind.SlashToken:
case SyntaxKind.PercentToken:
case SyntaxKind.PlusToken:
case SyntaxKind.MinusToken:
case SyntaxKind.LessThanLessThanToken:
case SyntaxKind.GreaterThanGreaterThanToken:
case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
case SyntaxKind.LessThanToken:
case SyntaxKind.GreaterThanToken:
case SyntaxKind.LessThanEqualsToken:
case SyntaxKind.GreaterThanEqualsToken:
case SyntaxKind.InstanceOfKeyword:
case SyntaxKind.InKeyword:
case SyntaxKind.EqualsEqualsToken:
case SyntaxKind.ExclamationEqualsToken:
case SyntaxKind.EqualsEqualsEqualsToken:
case SyntaxKind.ExclamationEqualsEqualsToken:
case SyntaxKind.AmpersandToken:
case SyntaxKind.CaretToken:
case SyntaxKind.BarToken:
case SyntaxKind.AmpersandAmpersandToken:
case SyntaxKind.BarBarToken:
case SyntaxKind.BarEqualsToken:
case SyntaxKind.AmpersandEqualsToken:
case SyntaxKind.CaretEqualsToken:
case SyntaxKind.LessThanLessThanEqualsToken:
case SyntaxKind.GreaterThanGreaterThanEqualsToken:
case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
case SyntaxKind.PlusEqualsToken:
case SyntaxKind.MinusEqualsToken:
case SyntaxKind.AsteriskEqualsToken:
case SyntaxKind.SlashEqualsToken:
case SyntaxKind.PercentEqualsToken:
case SyntaxKind.EqualsToken:
case SyntaxKind.CommaToken:
return true;
default:
return false;
}
}
+3 -11
View File
@@ -2,16 +2,8 @@
module TypeScript.SyntaxFacts {
export function isDirectivePrologueElement(node: ISyntaxNodeOrToken): boolean {
if (node.kind() === SyntaxKind.ExpressionStatement) {
var expressionStatement = <ExpressionStatementSyntax>node;
var expression = expressionStatement.expression;
if (expression.kind() === SyntaxKind.StringLiteral) {
return true;
}
}
return false;
return node.kind === SyntaxKind.ExpressionStatement &&
(<ExpressionStatementSyntax>node).expression.kind === SyntaxKind.StringLiteral;
}
export function isUseStrictDirective(node: ISyntaxNodeOrToken): boolean {
@@ -23,7 +15,7 @@ module TypeScript.SyntaxFacts {
}
export function isIdentifierNameOrAnyKeyword(token: ISyntaxToken): boolean {
var tokenKind = token.kind();
var tokenKind = token.kind;
return tokenKind === SyntaxKind.IdentifierName || SyntaxFacts.isAnyKeyword(tokenKind);
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+16 -50
View File
@@ -5,8 +5,6 @@ module TypeScript {
// Variable width tokens, trivia and lists.
None,
List,
SeparatedList,
TriviaList,
// Trivia
WhitespaceTrivia,
@@ -28,6 +26,12 @@ module TypeScript {
NumericLiteral,
StringLiteral,
// Template tokens
NoSubstitutionTemplateToken,
TemplateStartToken,
TemplateMiddleToken,
TemplateEndToken,
// All fixed width tokens follow.
// Keywords
@@ -159,6 +163,8 @@ module TypeScript {
GenericType,
TypeQuery,
TupleType,
UnionType,
ParenthesizedType,
// Module elements.
InterfaceDeclaration,
@@ -207,54 +213,13 @@ module TypeScript {
WithStatement,
// Expressions
PlusExpression,
NegateExpression,
BitwiseNotExpression,
LogicalNotExpression,
PreIncrementExpression,
PreDecrementExpression,
PrefixUnaryExpression,
DeleteExpression,
TypeOfExpression,
VoidExpression,
CommaExpression,
AssignmentExpression,
AddAssignmentExpression,
SubtractAssignmentExpression,
MultiplyAssignmentExpression,
DivideAssignmentExpression,
ModuloAssignmentExpression,
AndAssignmentExpression,
ExclusiveOrAssignmentExpression,
OrAssignmentExpression,
LeftShiftAssignmentExpression,
SignedRightShiftAssignmentExpression,
UnsignedRightShiftAssignmentExpression,
ConditionalExpression,
LogicalOrExpression,
LogicalAndExpression,
BitwiseOrExpression,
BitwiseExclusiveOrExpression,
BitwiseAndExpression,
EqualsWithTypeConversionExpression,
NotEqualsWithTypeConversionExpression,
EqualsExpression,
NotEqualsExpression,
LessThanExpression,
GreaterThanExpression,
LessThanOrEqualExpression,
GreaterThanOrEqualExpression,
InstanceOfExpression,
InExpression,
LeftShiftExpression,
SignedRightShiftExpression,
UnsignedRightShiftExpression,
MultiplyExpression,
DivideExpression,
ModuloExpression,
AddExpression,
SubtractExpression,
PostIncrementExpression,
PostDecrementExpression,
BinaryExpression,
PostfixUnaryExpression,
MemberAccessExpression,
InvocationExpression,
ArrayLiteralExpression,
@@ -267,6 +232,8 @@ module TypeScript {
ElementAccessExpression,
FunctionExpression,
OmittedExpression,
TemplateExpression,
TemplateAccessExpression,
// Variable declarations
VariableDeclaration,
@@ -279,14 +246,14 @@ module TypeScript {
TypeParameterList,
// Clauses
ExtendsHeritageClause,
ImplementsHeritageClause,
HeritageClause,
EqualsValueClause,
CaseSwitchClause,
DefaultSwitchClause,
ElseClause,
CatchClause,
FinallyClause,
TemplateClause,
// Generics
TypeParameter,
@@ -294,14 +261,13 @@ module TypeScript {
// Property Assignment
SimplePropertyAssignment,
// GetAccessorPropertyAssignment,
// SetAccessorPropertyAssignment,
FunctionPropertyAssignment,
// Misc.
Parameter,
EnumElement,
TypeAnnotation,
ComputedPropertyName,
ExternalModuleReference,
ModuleNameModuleReference,
+51 -77
View File
@@ -1,95 +1,69 @@
///<reference path='references.ts' />
interface Array<T> {
data: number;
separators?: TypeScript.ISyntaxToken[];
__data: number;
kind(): TypeScript.SyntaxKind;
kind: TypeScript.SyntaxKind;
parent: TypeScript.ISyntaxElement;
}
separatorCount(): number;
separatorAt(index: number): TypeScript.ISyntaxToken;
module TypeScript {
export interface ISeparatedSyntaxList<T extends ISyntaxNodeOrToken> extends Array<ISyntaxNodeOrToken> {
//separatorCount(): number;
//separatorAt(index: number): TypeScript.ISyntaxToken;
//nonSeparatorCount(): number;
//nonSeparatorAt(index: number): T;
}
}
module TypeScript {
export function separatorCount(list: ISeparatedSyntaxList<ISyntaxNodeOrToken>) {
return list === undefined ? 0 : list.length >> 1;
}
export function nonSeparatorCount(list: ISeparatedSyntaxList<ISyntaxNodeOrToken>) {
return list === undefined ? 0 : (list.length + 1) >> 1;
}
export function separatorAt(list: ISeparatedSyntaxList<ISyntaxNodeOrToken>, index: number): ISyntaxToken {
return <ISyntaxToken>list[(index << 1) + 1];
}
export function nonSeparatorAt<T extends ISyntaxNodeOrToken>(list: ISeparatedSyntaxList<T>, index: number): T {
return <T>list[index << 1];
}
}
module TypeScript.Syntax {
var _emptyList: ISyntaxNodeOrToken[] = [];
var _emptySeparatedList: ISyntaxNodeOrToken[] = [];
var _emptySeparators: ISyntaxToken[] = [];
_emptySeparatedList.separators = _emptySeparators;
function assertEmptyLists() {
// Debug.assert(_emptyList.length === 0);
// var separators = _emptySeparatedList.separators;
// Debug.assert(!separators || separators.length === 0);
function addArrayPrototypeValue(name: string, val: any) {
if (Object.defineProperty && (<any>Array.prototype)[name] === undefined) {
Object.defineProperty(Array.prototype, name, { value: val, writable: false });
}
else {
(<any>Array.prototype)[name] = val;
}
}
Array.prototype.kind = function () {
return this.separators === undefined ? SyntaxKind.List : SyntaxKind.SeparatedList;
}
Array.prototype.separatorCount = function (): number {
assertEmptyLists();
// Debug.assert(this.kind === SyntaxKind.SeparatedList);
return this.separators.length;
}
Array.prototype.separatorAt = function (index: number): ISyntaxToken {
assertEmptyLists();
// Debug.assert(this.kind === SyntaxKind.SeparatedList);
// Debug.assert(index >= 0 && index < this.separators.length);
return this.separators[index];
}
export function emptyList<T extends ISyntaxNodeOrToken>(): T[] {
return <T[]><any>_emptyList;
}
export function emptySeparatedList<T extends ISyntaxNodeOrToken>(): T[] {
return <T[]><any>_emptySeparatedList;
}
addArrayPrototypeValue("kind", SyntaxKind.List);
export function list<T extends ISyntaxNodeOrToken>(nodes: T[]): T[] {
if (nodes === undefined || nodes === null || nodes.length === 0) {
return emptyList<T>();
}
for (var i = 0, n = nodes.length; i < n; i++) {
nodes[i].parent = nodes;
}
return nodes;
}
export function separatedList<T extends ISyntaxNodeOrToken>(nodes: T[], separators: ISyntaxToken[]): T[] {
if (nodes === undefined || nodes === null || nodes.length === 0) {
return emptySeparatedList<T>();
}
// Debug.assert(separators.length === nodes.length || separators.length == (nodes.length - 1));
for (var i = 0, n = nodes.length; i < n; i++) {
nodes[i].parent = nodes;
}
for (var i = 0, n = separators.length; i < n; i++) {
separators[i].parent = nodes;
}
nodes.separators = separators.length === 0 ? _emptySeparators : separators;
return nodes;
}
export function nonSeparatorIndexOf<T extends ISyntaxNodeOrToken>(list: T[], ast: ISyntaxNodeOrToken): number {
for (var i = 0, n = list.length; i < n; i++) {
if (list[i] === ast) {
return i;
if (nodes !== undefined) {
for (var i = 0, n = nodes.length; i < n; i++) {
nodes[i].parent = nodes;
}
}
return -1;
return nodes;
}
export function separatedList<T extends ISyntaxNodeOrToken>(nodesAndTokens: ISyntaxNodeOrToken[]): ISeparatedSyntaxList<T> {
if (nodesAndTokens !== undefined) {
for (var i = 0, n = nodesAndTokens.length; i < n; i++) {
nodesAndTokens[i].parent = nodesAndTokens;
}
}
return <ISeparatedSyntaxList<T>>nodesAndTokens;
}
}
-19
View File
@@ -1,19 +0,0 @@
///<reference path='references.ts' />
module TypeScript {
export class SyntaxNode implements ISyntaxNodeOrToken {
private __kind: SyntaxKind;
public data: number;
public parent: ISyntaxElement;
constructor(data: number) {
if (data) {
this.data = data;
}
}
public kind(): SyntaxKind {
return this.__kind;
}
}
}
+2
View File
@@ -2,5 +2,7 @@
module TypeScript {
export interface ISyntaxNodeOrToken extends ISyntaxElement {
childCount: number;
childAt(index: number): ISyntaxElement;
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+86 -110
View File
@@ -1,7 +1,7 @@
///<reference path='references.ts' />
module TypeScript {
export interface ISyntaxToken extends ISyntaxNodeOrToken, INameSyntax, IPrimaryExpressionSyntax {
export interface ISyntaxToken extends ISyntaxNodeOrToken, INameSyntax, IPrimaryExpressionSyntax, IPropertyAssignmentSyntax, IPropertyNameSyntax {
// Adjusts the full start of this token. Should only be called by the parser.
setFullStart(fullStart: number): void;
@@ -16,17 +16,12 @@ module TypeScript {
fullText(text?: ISimpleText): string;
hasLeadingTrivia(): boolean;
hasTrailingTrivia(): boolean;
hasLeadingNewLine(): boolean;
hasLeadingComment(): boolean;
hasTrailingComment(): boolean;
hasSkippedToken(): boolean;
hasLeadingSkippedToken(): boolean;
leadingTrivia(text?: ISimpleText): ISyntaxTriviaList;
trailingTrivia(text?: ISimpleText): ISyntaxTriviaList;
leadingTriviaWidth(text?: ISimpleText): number;
trailingTriviaWidth(text?: ISimpleText): number;
// True if this was a keyword that the parser converted to an identifier. i.e. if you have
// x.public
@@ -71,10 +66,10 @@ module TypeScript {
module TypeScript {
export function tokenValue(token: ISyntaxToken): any {
if (token.fullWidth() === 0) {
return null;
return undefined;
}
var kind = token.kind();
var kind = token.kind;
var text = token.text();
if (kind === SyntaxKind.IdentifierName) {
@@ -87,7 +82,7 @@ module TypeScript {
case SyntaxKind.FalseKeyword:
return false;
case SyntaxKind.NullKeyword:
return null;
return undefined;
}
if (SyntaxFacts.isAnyKeyword(kind) || SyntaxFacts.isAnyPunctuation(kind)) {
@@ -98,21 +93,29 @@ module TypeScript {
return IntegerUtilities.isHexInteger(text) ? parseInt(text, /*radix:*/ 16) : parseFloat(text);
}
else if (kind === SyntaxKind.StringLiteral) {
if (text.length > 1 && text.charCodeAt(text.length - 1) === text.charCodeAt(0)) {
// Properly terminated. Remove the quotes, and massage any escape characters we see.
return massageEscapes(text.substr(1, text.length - 2));
}
else {
// Not property terminated. Remove the first quote and massage any escape characters we see.
return massageEscapes(text.substr(1));
}
return (text.length > 1 && text.charCodeAt(text.length - 1) === text.charCodeAt(0))
? massageEscapes(text.substr(1, text.length - "''".length))
: massageEscapes(text.substr(1));
}
else if (kind === SyntaxKind.NoSubstitutionTemplateToken || kind === SyntaxKind.TemplateEndToken) {
// Both of these template types may be missing their closing backtick (if they were at
// the end of the file). Check to make sure it is there before grabbing the portion
// we're examining.
return (text.length > 1 && text.charCodeAt(text.length - 1) === CharacterCodes.backtick)
? massageTemplate(text.substr(1, text.length - "``".length))
: massageTemplate(text.substr(1));
}
else if (kind === SyntaxKind.TemplateStartToken || kind === SyntaxKind.TemplateMiddleToken) {
// Both these tokens must have been properly ended. i.e. if it didn't end with a ${
// then we would not have parsed a start or middle token out at all. So we don't
// need to check for an incomplete token.
return massageTemplate(text.substr(1, text.length - "`${".length));
}
else if (kind === SyntaxKind.RegularExpressionLiteral) {
return regularExpressionValue(text);
}
else if (kind === SyntaxKind.EndOfFileToken || kind === SyntaxKind.ErrorToken) {
return null;
return undefined;
}
else {
throw Errors.invalidOperation();
@@ -121,7 +124,19 @@ module TypeScript {
export function tokenValueText(token: ISyntaxToken): string {
var value = tokenValue(token);
return value === null ? "" : massageDisallowedIdentifiers(value.toString());
return value === undefined ? "" : massageDisallowedIdentifiers(value.toString());
}
function massageTemplate(text: string): string {
// First, convert all carriage-return newlines into line-feed newlines. This is due to:
//
// The TRV of LineTerminatorSequence :: <CR> is the code unit value 0x000A.
// ...
// The TRV of LineTerminatorSequence :: <CR><LF> is the sequence consisting of the code unit value 0x000A.
text = text.replace("\r\n", "\n").replace("\r", "\n");
// Now remove any escape characters that may be in the string.
return massageEscapes(text);
}
export function massageEscapes(text: string): string {
@@ -136,7 +151,7 @@ module TypeScript {
return new RegExp(body, flags);
}
catch (e) {
return null;
return undefined;
}
}
@@ -235,13 +250,13 @@ module TypeScript {
characterArray.push(ch);
if (i && !(i % 1024)) {
result = result.concat(String.fromCharCode.apply(null, characterArray));
result = result.concat(String.fromCharCode.apply(undefined, characterArray));
characterArray.length = 0;
}
}
if (characterArray.length) {
result = result.concat(String.fromCharCode.apply(null, characterArray));
result = result.concat(String.fromCharCode.apply(undefined, characterArray));
}
return result;
@@ -264,7 +279,7 @@ module TypeScript {
module TypeScript.Syntax {
export function realizeToken(token: ISyntaxToken, text: ISimpleText): ISyntaxToken {
return new RealizedToken(token.fullStart(), token.kind(), token.isKeywordConvertedToIdentifier(), token.leadingTrivia(text), token.text(), token.trailingTrivia(text));
return new RealizedToken(token.fullStart(), token.kind, token.isKeywordConvertedToIdentifier(), token.leadingTrivia(text), token.text());
}
export function convertKeywordToIdentifier(token: ISyntaxToken): ISyntaxToken {
@@ -272,11 +287,7 @@ module TypeScript.Syntax {
}
export function withLeadingTrivia(token: ISyntaxToken, leadingTrivia: ISyntaxTriviaList, text: ISimpleText): ISyntaxToken {
return new RealizedToken(token.fullStart(), token.kind(), token.isKeywordConvertedToIdentifier(), leadingTrivia, token.text(), token.trailingTrivia(text));
}
export function withTrailingTrivia(token: ISyntaxToken, trailingTrivia: ISyntaxTriviaList, text: ISimpleText): ISyntaxToken {
return new RealizedToken(token.fullStart(), token.kind(), token.isKeywordConvertedToIdentifier(), token.leadingTrivia(text), token.text(), trailingTrivia);
return new RealizedToken(token.fullStart(), token.kind, token.isKeywordConvertedToIdentifier(), leadingTrivia, token.text());
}
export function emptyToken(kind: SyntaxKind): ISyntaxToken {
@@ -284,21 +295,22 @@ module TypeScript.Syntax {
}
class EmptyToken implements ISyntaxToken {
public _primaryExpressionBrand: any; public _memberExpressionBrand: any; public _leftHandSideExpressionBrand: any; public _postfixExpressionBrand: any; public _unaryExpressionBrand: any; public _expressionBrand: any; public _typeBrand: any;
public _primaryExpressionBrand: any; public _memberExpressionBrand: any; public _leftHandSideExpressionBrand: any; public _postfixExpressionBrand: any; public _unaryExpressionBrand: any; public _expressionBrand: any; public _typeBrand: any; public _nameBrand: any; public _propertyAssignmentBrand: any; public _propertyNameBrand: any;
constructor(private _kind: SyntaxKind) {
public parent: ISyntaxElement;
public childCount: number;
constructor(public kind: SyntaxKind) {
}
public setFullStart(fullStart: number): void {
// An empty token is always at the -1 position.
}
public kind(): SyntaxKind {
return this._kind;
}
public childAt(index: number): ISyntaxElement { throw Errors.invalidOperation() }
public clone(): ISyntaxToken {
return new EmptyToken(this.kind());
return new EmptyToken(this.kind);
}
// Empty tokens are never incrementally reusable.
@@ -330,15 +342,15 @@ module TypeScript.Syntax {
// the full-start of this token to be at the full-end of that element.
var previousElement = this.previousNonZeroWidthElement();
return previousElement === null ? 0 : fullStart(previousElement) + fullWidth(previousElement);
return !previousElement ? 0 : fullStart(previousElement) + fullWidth(previousElement);
}
private previousNonZeroWidthElement(): ISyntaxElement {
var current: ISyntaxElement = this;
while (true) {
var parent = current.parent;
if (parent === null) {
Debug.assert(current.kind() === SyntaxKind.SourceUnit, "We had a node without a parent that was not the root node!");
if (parent === undefined) {
Debug.assert(current.kind === SyntaxKind.SourceUnit, "We had a node without a parent that was not the root node!");
// We walked all the way to the top, and never found a previous element. This
// can happen with code like:
@@ -346,9 +358,9 @@ module TypeScript.Syntax {
// / b;
//
// We will have an empty identifier token as the first token in the tree. In
// this case, return null so that the position of the empty token will be
// this case, return undefined so that the position of the empty token will be
// considered to be 0.
return null;
return undefined;
}
// Ok. We have a parent. First, find out which slot we're at in the parent.
@@ -383,61 +395,50 @@ module TypeScript.Syntax {
public fullText(): string { return ""; }
public hasLeadingTrivia() { return false; }
public hasTrailingTrivia() { return false; }
public hasLeadingNewLine() { return false; }
public hasLeadingComment() { return false; }
public hasTrailingComment() { return false; }
public hasSkippedToken() { return false; }
public hasLeadingSkippedToken() { return false; }
public leadingTriviaWidth() { return 0; }
public trailingTriviaWidth() { return 0; }
public leadingTrivia(): ISyntaxTriviaList { return Syntax.emptyTriviaList; }
public trailingTrivia(): ISyntaxTriviaList { return Syntax.emptyTriviaList; }
}
EmptyToken.prototype.childCount = 0;
class RealizedToken implements ISyntaxToken {
public _primaryExpressionBrand: any; public _memberExpressionBrand: any; public _leftHandSideExpressionBrand: any; public _postfixExpressionBrand: any; public _unaryExpressionBrand: any; public _expressionBrand: any; public _typeBrand: any; public _nameBrand: any; public _propertyAssignmentBrand: any; public _propertyNameBrand: any;
private _fullStart: number;
private _kind: SyntaxKind;
private _isKeywordConvertedToIdentifier: boolean;
private _leadingTrivia: ISyntaxTriviaList;
private _text: string;
private _trailingTrivia: ISyntaxTriviaList;
public _primaryExpressionBrand: any; public _memberExpressionBrand: any; public _leftHandSideExpressionBrand: any; public _postfixExpressionBrand: any; public _unaryExpressionBrand: any; public _expressionBrand: any; public _typeBrand: any;
public parent: ISyntaxElement;
public childCount: number;
constructor(fullStart: number,
kind: SyntaxKind,
isKeywordConvertedToIdentifier: boolean,
leadingTrivia: ISyntaxTriviaList,
text: string,
trailingTrivia: ISyntaxTriviaList) {
public kind: SyntaxKind,
isKeywordConvertedToIdentifier: boolean,
leadingTrivia: ISyntaxTriviaList,
text: string) {
this._fullStart = fullStart;
this._kind = kind;
this._isKeywordConvertedToIdentifier = isKeywordConvertedToIdentifier;
this._text = text;
this._leadingTrivia = leadingTrivia.clone();
this._trailingTrivia = trailingTrivia.clone();
if (!this._leadingTrivia.isShared()) {
this._leadingTrivia.parent = this;
}
if (!this._trailingTrivia.isShared()) {
this._trailingTrivia.parent = this;
}
}
public setFullStart(fullStart: number): void {
this._fullStart = fullStart;
}
public kind(): SyntaxKind {
return this._kind;
}
public childAt(index: number): ISyntaxElement { throw Errors.invalidOperation() }
public clone(): ISyntaxToken {
return new RealizedToken(this._fullStart, this.kind(), this._isKeywordConvertedToIdentifier, this._leadingTrivia, this._text, this._trailingTrivia);
return new RealizedToken(this._fullStart, this.kind, this._isKeywordConvertedToIdentifier, this._leadingTrivia, this._text);
}
// Realized tokens are created from the parser. They are *never* incrementally reusable.
@@ -448,39 +449,37 @@ module TypeScript.Syntax {
}
public fullStart(): number { return this._fullStart; }
public fullWidth(): number { return this._leadingTrivia.fullWidth() + this._text.length + this._trailingTrivia.fullWidth(); }
public fullWidth(): number { return this._leadingTrivia.fullWidth() + this._text.length; }
public text(): string { return this._text; }
public fullText(): string { return this._leadingTrivia.fullText() + this.text() + this._trailingTrivia.fullText(); }
public fullText(): string { return this._leadingTrivia.fullText() + this.text(); }
public hasLeadingTrivia(): boolean { return this._leadingTrivia.count() > 0; }
public hasTrailingTrivia(): boolean { return this._trailingTrivia.count() > 0; }
public hasLeadingNewLine(): boolean { return this._leadingTrivia.hasNewLine(); }
public hasLeadingComment(): boolean { return this._leadingTrivia.hasComment(); }
public hasTrailingComment(): boolean { return this._trailingTrivia.hasComment(); }
public leadingTriviaWidth(): number { return this._leadingTrivia.fullWidth(); }
public trailingTriviaWidth(): number { return this._trailingTrivia.fullWidth(); }
public hasSkippedToken(): boolean { return this._leadingTrivia.hasSkippedToken() || this._trailingTrivia.hasSkippedToken(); }
public hasLeadingSkippedToken(): boolean { return this._leadingTrivia.hasSkippedToken(); }
public leadingTrivia(): ISyntaxTriviaList { return this._leadingTrivia; }
public trailingTrivia(): ISyntaxTriviaList { return this._trailingTrivia; }
public leadingTriviaWidth(): number { return this._leadingTrivia.fullWidth(); }
}
RealizedToken.prototype.childCount = 0;
class ConvertedKeywordToken implements ISyntaxToken {
public _primaryExpressionBrand: any; public _memberExpressionBrand: any; public _leftHandSideExpressionBrand: any; public _postfixExpressionBrand: any; public _unaryExpressionBrand: any; public _expressionBrand: any; public _typeBrand: any;
public _primaryExpressionBrand: any; public _memberExpressionBrand: any; public _leftHandSideExpressionBrand: any; public _postfixExpressionBrand: any; public _unaryExpressionBrand: any; public _expressionBrand: any; public _typeBrand: any; public _nameBrand: any; public _propertyAssignmentBrand: any; public _propertyNameBrand: any;
public parent: ISyntaxElement;
public kind: SyntaxKind;
public childCount: number;
constructor(private underlyingToken: ISyntaxToken) {
}
public kind() {
return SyntaxKind.IdentifierName;
}
public setFullStart(fullStart: number): void {
this.underlyingToken.setFullStart(fullStart);
}
public childAt(index: number): ISyntaxElement { throw Errors.invalidOperation() }
public fullStart(): number {
return this.underlyingToken.fullStart();
}
@@ -503,25 +502,10 @@ module TypeScript.Syntax {
return this.underlyingToken.fullText(this.syntaxTreeText(text));
}
public hasLeadingTrivia(): boolean {
return this.underlyingToken.hasLeadingTrivia();
}
public hasTrailingTrivia(): boolean {
return this.underlyingToken.hasTrailingTrivia();
}
public hasLeadingComment(): boolean {
return this.underlyingToken.hasLeadingComment();
}
public hasTrailingComment(): boolean {
return this.underlyingToken.hasTrailingComment();
}
public hasSkippedToken(): boolean {
return this.underlyingToken.hasSkippedToken();
}
public hasLeadingTrivia(): boolean { return this.underlyingToken.hasLeadingTrivia(); }
public hasLeadingNewLine(): boolean { return this.underlyingToken.hasLeadingNewLine(); }
public hasLeadingComment(): boolean { return this.underlyingToken.hasLeadingComment(); }
public hasLeadingSkippedToken(): boolean { return this.underlyingToken.hasLeadingSkippedToken(); }
public leadingTrivia(text?: ISimpleText): ISyntaxTriviaList {
var result = this.underlyingToken.leadingTrivia(this.syntaxTreeText(text));
@@ -529,20 +513,10 @@ module TypeScript.Syntax {
return result;
}
public trailingTrivia(text?: ISimpleText): ISyntaxTriviaList {
var result = this.underlyingToken.trailingTrivia(this.syntaxTreeText(text));
result.parent = this;
return result;
}
public leadingTriviaWidth(text?: ISimpleText): number {
return this.underlyingToken.leadingTriviaWidth(this.syntaxTreeText(text));
}
public trailingTriviaWidth(text?: ISimpleText): number {
return this.underlyingToken.trailingTriviaWidth(this.syntaxTreeText(text));
}
public isKeywordConvertedToIdentifier(): boolean {
return true;
}
@@ -559,4 +533,6 @@ module TypeScript.Syntax {
return new ConvertedKeywordToken(this.underlyingToken);
}
}
ConvertedKeywordToken.prototype.kind = SyntaxKind.IdentifierName;
ConvertedKeywordToken.prototype.childCount = 0;
}
+164 -114
View File
@@ -4,11 +4,10 @@ module TypeScript {
export var syntaxDiagnosticsTime: number = 0;
export class SyntaxTree {
private _isConcrete: boolean;
private _sourceUnit: SourceUnitSyntax;
private _isDeclaration: boolean;
private _parserDiagnostics: Diagnostic[];
private _allDiagnostics: Diagnostic[] = null;
private _allDiagnostics: Diagnostic[] = undefined;
private _fileName: string;
private _lineMap: LineMap;
private _languageVersion: ts.ScriptTarget;
@@ -17,14 +16,12 @@ module TypeScript {
private _amdDependencies: string[];
private _isExternalModule: boolean;
constructor(isConcrete: boolean,
sourceUnit: SourceUnitSyntax,
constructor(sourceUnit: SourceUnitSyntax,
isDeclaration: boolean,
diagnostics: Diagnostic[],
fileName: string,
public text: ISimpleText,
languageVersion: ts.ScriptTarget) {
this._isConcrete = isConcrete;
this._sourceUnit = sourceUnit;
this._isDeclaration = isDeclaration;
this._parserDiagnostics = diagnostics;
@@ -35,10 +32,6 @@ module TypeScript {
sourceUnit.syntaxTree = this;
}
public isConcrete(): boolean {
return this._isConcrete;
}
public sourceUnit(): SourceUnitSyntax {
return this._sourceUnit;
}
@@ -60,7 +53,7 @@ module TypeScript {
}
public diagnostics(): Diagnostic[] {
if (this._allDiagnostics === null) {
if (!this._allDiagnostics) {
var start = new Date().getTime();
this._allDiagnostics = this.computeDiagnostics();
syntaxDiagnosticsTime += new Date().getTime() - start;
@@ -87,7 +80,7 @@ module TypeScript {
var firstToken = firstSyntaxTreeToken(this);
var leadingTrivia = firstToken.leadingTrivia(this.text);
this._isExternalModule = externalModuleIndicatorSpanWorker(this, firstToken) !== null;
this._isExternalModule = !!externalModuleIndicatorSpanWorker(this, firstToken);
var amdDependencies: string[] = [];
for (var i = 0, n = leadingTrivia.count(); i < n; i++) {
@@ -106,7 +99,7 @@ module TypeScript {
private getAmdDependency(comment: string): string {
var amdDependencyRegEx = /^\/\/\/\s*<amd-dependency\s+path=('|")(.+?)\1/gim;
var match = amdDependencyRegEx.exec(comment);
return match ? match[2] : null;
return match ? match[2] : undefined;
}
public isExternalModule(): boolean {
@@ -144,7 +137,7 @@ module TypeScript {
this.text = syntaxTree.text;
}
private pushDiagnostic(element: ISyntaxElement, diagnosticKey: string, args: any[] = null): void {
private pushDiagnostic(element: ISyntaxElement, diagnosticKey: string, args?: any[]): void {
this.diagnostics.push(new Diagnostic(
this.syntaxTree.fileName(), this.syntaxTree.lineMap(), start(element, this.text), width(element), diagnosticKey, args));
}
@@ -169,10 +162,10 @@ module TypeScript {
private checkParameterListOrder(node: ParameterListSyntax): boolean {
var seenOptionalParameter = false;
var parameterCount = node.parameters.length;
var parameterCount = nonSeparatorCount(node.parameters);
for (var i = 0; i < parameterCount; i++) {
var parameter = node.parameters[i];
var parameter = nonSeparatorAt(node.parameters, i);
if (parameter.dotDotDotToken) {
if (i !== (parameterCount - 1)) {
@@ -210,8 +203,8 @@ module TypeScript {
}
private checkParameterListAcessibilityModifiers(node: ParameterListSyntax): boolean {
for (var i = 0, n = node.parameters.length; i < n; i++) {
var parameter = node.parameters[i];
for (var i = 0, n = nonSeparatorCount(node.parameters); i < n; i++) {
var parameter = nonSeparatorAt(node.parameters, i);
if (this.checkParameterAccessibilityModifiers(node, parameter)) {
return true;
@@ -238,7 +231,7 @@ module TypeScript {
}
private checkParameterAccessibilityModifier(parameterList: ParameterListSyntax, modifier: ISyntaxToken, modifierIndex: number): boolean {
if (!SyntaxFacts.isAccessibilityModifier(modifier.kind())) {
if (!SyntaxFacts.isAccessibilityModifier(modifier.kind)) {
this.pushDiagnostic(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_parameter, [modifier.text()]);
return true;
}
@@ -255,17 +248,17 @@ module TypeScript {
private checkForTrailingComma(list: ISyntaxNodeOrToken[]): boolean {
// If we have at least one child, and we have an even number of children, then that
// means we have an illegal trailing separator.
if (childCount(list) === 0 || childCount(list) % 2 === 1) {
if (list.length === 0 || list.length % 2 === 1) {
return false;
}
var child = childAt(list, childCount(list) - 1);
var child = list[list.length - 1];
this.pushDiagnostic(child, DiagnosticCode.Trailing_comma_not_allowed);
return true;
}
private checkForAtLeastOneElement(parent: ISyntaxElement, list: ISyntaxNodeOrToken[], reportToken: ISyntaxToken, listKind: string): boolean {
private checkForAtLeastOneElement(list: ISyntaxNodeOrToken[], reportToken: ISyntaxToken, listKind: string): boolean {
if (childCount(list) > 0) {
return false;
}
@@ -287,7 +280,7 @@ module TypeScript {
public visitHeritageClause(node: HeritageClauseSyntax): void {
if (this.checkForTrailingComma(node.typeNames) ||
this.checkForAtLeastOneElement(node, node.typeNames, node.extendsOrImplementsKeyword, SyntaxFacts.getText(node.extendsOrImplementsKeyword.kind()))) {
this.checkForAtLeastOneElement(node.typeNames, node.extendsOrImplementsKeyword, SyntaxFacts.getText(node.extendsOrImplementsKeyword.kind))) {
return;
}
@@ -303,7 +296,7 @@ module TypeScript {
}
public visitVariableDeclaration(node: VariableDeclarationSyntax): void {
if (this.checkForAtLeastOneElement(node, node.variableDeclarators, node.varKeyword, getLocalizedText(DiagnosticCode.variable_declaration, null)) ||
if (this.checkForAtLeastOneElement(node.variableDeclarators, node.varKeyword, getLocalizedText(DiagnosticCode.variable_declaration, undefined)) ||
this.checkForTrailingComma(node.variableDeclarators)) {
return;
}
@@ -313,7 +306,7 @@ module TypeScript {
public visitTypeArgumentList(node: TypeArgumentListSyntax): void {
if (this.checkForTrailingComma(node.typeArguments) ||
this.checkForAtLeastOneElement(node, node.typeArguments, node.lessThanToken, getLocalizedText(DiagnosticCode.type_argument, null))) {
this.checkForAtLeastOneElement(node.typeArguments, node.lessThanToken, getLocalizedText(DiagnosticCode.type_argument, undefined))) {
return;
}
@@ -322,7 +315,7 @@ module TypeScript {
public visitTupleType(node: TupleTypeSyntax): void {
if (this.checkForTrailingComma(node.types) ||
this.checkForAtLeastOneElement(node, node.types, node.openBracketToken, getLocalizedText(DiagnosticCode.type, null))) {
this.checkForAtLeastOneElement(node.types, node.openBracketToken, getLocalizedText(DiagnosticCode.type, undefined))) {
return
}
@@ -331,7 +324,7 @@ module TypeScript {
public visitTypeParameterList(node: TypeParameterListSyntax): void {
if (this.checkForTrailingComma(node.typeParameters) ||
this.checkForAtLeastOneElement(node, node.typeParameters, node.lessThanToken, getLocalizedText(DiagnosticCode.type_parameter, null))) {
this.checkForAtLeastOneElement(node.typeParameters, node.lessThanToken, getLocalizedText(DiagnosticCode.type_parameter, undefined))) {
return;
}
@@ -344,7 +337,7 @@ module TypeScript {
return true;
}
var parameter = node.parameters[0];
var parameter = nonSeparatorAt(node.parameters, 0);
if (parameter.dotDotDotToken) {
this.pushDiagnostic(parameter, DiagnosticCode.Index_signatures_cannot_have_rest_parameters);
@@ -366,8 +359,8 @@ module TypeScript {
this.pushDiagnostic(parameter, DiagnosticCode.Index_signature_parameter_must_have_a_type_annotation);
return true;
}
else if (parameter.typeAnnotation.type.kind() !== SyntaxKind.StringKeyword &&
parameter.typeAnnotation.type.kind() !== SyntaxKind.NumberKeyword) {
else if (parameter.typeAnnotation.type.kind !== SyntaxKind.StringKeyword &&
parameter.typeAnnotation.type.kind !== SyntaxKind.NumberKeyword) {
this.pushDiagnostic(parameter, DiagnosticCode.Index_signature_parameter_type_must_be_string_or_number);
return true;
}
@@ -396,7 +389,7 @@ module TypeScript {
Debug.assert(i <= 2);
var heritageClause = node.heritageClauses[i];
if (heritageClause.extendsOrImplementsKeyword.kind() === SyntaxKind.ExtendsKeyword) {
if (heritageClause.extendsOrImplementsKeyword.kind === SyntaxKind.ExtendsKeyword) {
if (seenExtendsClause) {
this.pushDiagnostic(heritageClause, DiagnosticCode.extends_clause_already_seen);
return true;
@@ -407,7 +400,7 @@ module TypeScript {
return true;
}
if (heritageClause.typeNames.length > 1) {
if (nonSeparatorCount(heritageClause.typeNames) > 1) {
this.pushDiagnostic(heritageClause, DiagnosticCode.Classes_can_only_extend_a_single_class);
return true;
}
@@ -415,7 +408,7 @@ module TypeScript {
seenExtendsClause = true;
}
else {
Debug.assert(heritageClause.extendsOrImplementsKeyword.kind() === SyntaxKind.ImplementsKeyword);
Debug.assert(heritageClause.extendsOrImplementsKeyword.kind === SyntaxKind.ImplementsKeyword);
if (seenImplementsClause) {
this.pushDiagnostic(heritageClause, DiagnosticCode.implements_clause_already_seen);
return true;
@@ -475,7 +468,7 @@ module TypeScript {
Debug.assert(i <= 1);
var heritageClause = node.heritageClauses[i];
if (heritageClause.extendsOrImplementsKeyword.kind() === SyntaxKind.ExtendsKeyword) {
if (heritageClause.extendsOrImplementsKeyword.kind === SyntaxKind.ExtendsKeyword) {
if (seenExtendsClause) {
this.pushDiagnostic(heritageClause, DiagnosticCode.extends_clause_already_seen);
return true;
@@ -484,7 +477,7 @@ module TypeScript {
seenExtendsClause = true;
}
else {
Debug.assert(heritageClause.extendsOrImplementsKeyword.kind() === SyntaxKind.ImplementsKeyword);
Debug.assert(heritageClause.extendsOrImplementsKeyword.kind === SyntaxKind.ImplementsKeyword);
this.pushDiagnostic(heritageClause, DiagnosticCode.Interface_declaration_cannot_have_implements_clause);
return true;
}
@@ -496,7 +489,7 @@ module TypeScript {
private checkInterfaceModifiers(modifiers: ISyntaxToken[]): boolean {
for (var i = 0, n = modifiers.length; i < n; i++) {
var modifier = modifiers[i];
if (modifier.kind() === SyntaxKind.DeclareKeyword) {
if (modifier.kind === SyntaxKind.DeclareKeyword) {
this.pushDiagnostic(modifier,
DiagnosticCode.A_declare_modifier_cannot_be_used_with_an_interface_declaration);
return true;
@@ -523,7 +516,7 @@ module TypeScript {
for (var i = 0, n = list.length; i < n; i++) {
var modifier = list[i];
if (SyntaxFacts.isAccessibilityModifier(modifier.kind())) {
if (SyntaxFacts.isAccessibilityModifier(modifier.kind)) {
if (seenAccessibilityModifier) {
this.pushDiagnostic(modifier, DiagnosticCode.Accessibility_modifier_already_seen);
return true;
@@ -537,7 +530,7 @@ module TypeScript {
seenAccessibilityModifier = true;
}
else if (modifier.kind() === SyntaxKind.StaticKeyword) {
else if (modifier.kind === SyntaxKind.StaticKeyword) {
if (seenStaticModifier) {
this.pushDiagnostic(modifier, DiagnosticCode._0_modifier_already_seen, [modifier.text()]);
return true;
@@ -562,8 +555,27 @@ module TypeScript {
super.visitMemberVariableDeclaration(node);
}
public visitMethodSignature(node: MethodSignatureSyntax): void {
if (this.checkForDisallowedTemplatePropertyName(node.propertyName) ||
this.checkForDisallowedComputedPropertyName(node.propertyName)) {
return;
}
super.visitMethodSignature(node);
}
public visitPropertySignature(node: PropertySignatureSyntax): void {
if (this.checkForDisallowedTemplatePropertyName(node.propertyName) ||
this.checkForDisallowedComputedPropertyName(node.propertyName)) {
return;
}
super.visitPropertySignature(node);
}
public visitMemberFunctionDeclaration(node: MemberFunctionDeclarationSyntax): void {
if (this.checkClassElementModifiers(node.modifiers)) {
if (this.checkClassElementModifiers(node.modifiers) ||
this.checkForDisallowedTemplatePropertyName(node.propertyName)) {
return;
}
@@ -589,14 +601,14 @@ module TypeScript {
private checkIndexMemberModifiers(node: IndexMemberDeclarationSyntax): boolean {
if (node.modifiers.length > 0) {
this.pushDiagnostic(childAt(node.modifiers, 0), DiagnosticCode.Modifiers_cannot_appear_here);
this.pushDiagnostic(node.modifiers[0], DiagnosticCode.Modifiers_cannot_appear_here);
return true;
}
return false;
}
private checkEcmaScriptVersionIsAtLeast(parent: ISyntaxElement, reportToken: ISyntaxToken, languageVersion: ts.ScriptTarget, diagnosticKey: string): boolean {
private checkEcmaScriptVersionIsAtLeast(reportToken: ISyntaxToken, languageVersion: ts.ScriptTarget, diagnosticKey: string): boolean {
if (this.syntaxTree.languageVersion() < languageVersion) {
this.pushDiagnostic(reportToken, diagnosticKey);
return true;
@@ -614,11 +626,12 @@ module TypeScript {
public visitGetAccessor(node: GetAccessorSyntax): void {
if (this.checkForAccessorDeclarationInAmbientContext(node) ||
this.checkEcmaScriptVersionIsAtLeast(node, node.propertyName, ts.ScriptTarget.ES5, DiagnosticCode.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher) ||
this.checkForDisallowedModifiers(node, node.modifiers) ||
this.checkEcmaScriptVersionIsAtLeast(node.getKeyword, ts.ScriptTarget.ES5, DiagnosticCode.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher) ||
this.checkForDisallowedModifiers(node.modifiers) ||
this.checkClassElementModifiers(node.modifiers) ||
this.checkForDisallowedAccessorTypeParameters(node.callSignature) ||
this.checkGetAccessorParameter(node)) {
this.checkGetAccessorParameter(node) ||
this.checkForDisallowedTemplatePropertyName(node.propertyName)) {
return;
}
@@ -635,7 +648,7 @@ module TypeScript {
}
private checkForDisallowedAccessorTypeParameters(callSignature: CallSignatureSyntax): boolean {
if (callSignature.typeParameterList !== null) {
if (callSignature.typeParameterList) {
this.pushDiagnostic(callSignature.typeParameterList, DiagnosticCode.Type_parameters_cannot_appear_on_an_accessor);
return true;
}
@@ -654,12 +667,12 @@ module TypeScript {
private checkSetAccessorParameter(node: SetAccessorSyntax): boolean {
var parameters = node.callSignature.parameterList.parameters;
if (childCount(parameters) !== 1) {
if (nonSeparatorCount(parameters) !== 1) {
this.pushDiagnostic(node.propertyName, DiagnosticCode.set_accessor_must_have_exactly_one_parameter);
return true;
}
var parameter = parameters[0];
var parameter = nonSeparatorAt(parameters, 0);
if (parameter.questionToken) {
this.pushDiagnostic(parameter, DiagnosticCode.set_accessor_parameter_cannot_be_optional);
@@ -679,14 +692,23 @@ module TypeScript {
return false;
}
public visitSimplePropertyAssignment(node: SimplePropertyAssignmentSyntax): void {
if (this.checkForDisallowedTemplatePropertyName(node.propertyName)) {
return;
}
super.visitSimplePropertyAssignment(node);
}
public visitSetAccessor(node: SetAccessorSyntax): void {
if (this.checkForAccessorDeclarationInAmbientContext(node) ||
this.checkEcmaScriptVersionIsAtLeast(node, node.propertyName, ts.ScriptTarget.ES5, DiagnosticCode.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher) ||
this.checkForDisallowedModifiers(node, node.modifiers) ||
this.checkEcmaScriptVersionIsAtLeast(node.setKeyword, ts.ScriptTarget.ES5, DiagnosticCode.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher) ||
this.checkForDisallowedModifiers(node.modifiers) ||
this.checkClassElementModifiers(node.modifiers) ||
this.checkForDisallowedAccessorTypeParameters(node.callSignature) ||
this.checkForDisallowedSetAccessorTypeAnnotation(node) ||
this.checkSetAccessorParameter(node)) {
this.checkSetAccessorParameter(node) ||
this.checkForDisallowedTemplatePropertyName(node.propertyName)) {
return;
}
@@ -710,28 +732,28 @@ module TypeScript {
private checkEnumElements(node: EnumDeclarationSyntax): boolean {
var previousValueWasComputed = false;
for (var i = 0, n = childCount(node.enumElements); i < n; i++) {
var child = childAt(node.enumElements, i);
for (var i = 0, n = nonSeparatorCount(node.enumElements); i < n; i++) {
var enumElement = nonSeparatorAt(node.enumElements, i);
if (i % 2 === 0) {
var enumElement = <EnumElementSyntax>child;
if (!enumElement.equalsValueClause && previousValueWasComputed) {
this.pushDiagnostic(enumElement, DiagnosticCode.Enum_member_must_have_initializer);
return true;
}
if (!enumElement.equalsValueClause && previousValueWasComputed) {
this.pushDiagnostic(enumElement, DiagnosticCode.Enum_member_must_have_initializer);
return true;
}
if (enumElement.equalsValueClause) {
var value = enumElement.equalsValueClause.value;
previousValueWasComputed = !Syntax.isIntegerLiteral(value);
}
if (enumElement.equalsValueClause) {
var value = enumElement.equalsValueClause.value;
previousValueWasComputed = !Syntax.isIntegerLiteral(value);
}
}
return false;
}
public visitEnumElement(node: EnumElementSyntax): void {
if (this.checkForDisallowedTemplatePropertyName(node.propertyName) ||
this.checkForDisallowedComputedPropertyName(node.propertyName)) {
return;
}
if (this.inAmbientDeclaration && node.equalsValueClause) {
var expression = node.equalsValueClause.value;
if (!Syntax.isIntegerLiteral(expression)) {
@@ -744,8 +766,8 @@ module TypeScript {
}
public visitInvocationExpression(node: InvocationExpressionSyntax): void {
if (node.expression.kind() === SyntaxKind.SuperKeyword &&
node.argumentList.typeArgumentList !== null) {
if (node.expression.kind === SyntaxKind.SuperKeyword &&
node.argumentList.typeArgumentList) {
this.pushDiagnostic(node, DiagnosticCode.super_invocation_cannot_have_type_arguments);
}
@@ -758,13 +780,13 @@ module TypeScript {
for (var i = 0, n = modifiers.length; i < n; i++) {
var modifier = modifiers[i];
if (SyntaxFacts.isAccessibilityModifier(modifier.kind()) ||
modifier.kind() === SyntaxKind.StaticKeyword) {
if (SyntaxFacts.isAccessibilityModifier(modifier.kind) ||
modifier.kind === SyntaxKind.StaticKeyword) {
this.pushDiagnostic(modifier, DiagnosticCode._0_modifier_cannot_appear_on_a_module_element, [modifier.text()]);
return true;
}
if (modifier.kind() === SyntaxKind.DeclareKeyword) {
if (modifier.kind === SyntaxKind.DeclareKeyword) {
if (seenDeclareModifier) {
this.pushDiagnostic(modifier, DiagnosticCode.Accessibility_modifier_already_seen);
return;
@@ -772,7 +794,7 @@ module TypeScript {
seenDeclareModifier = true;
}
else if (modifier.kind() === SyntaxKind.ExportKeyword) {
else if (modifier.kind === SyntaxKind.ExportKeyword) {
if (seenExportModifier) {
this.pushDiagnostic(modifier, DiagnosticCode._0_modifier_already_seen, [modifier.text()]);
return;
@@ -792,12 +814,12 @@ module TypeScript {
}
private checkForDisallowedImportDeclaration(node: ModuleDeclarationSyntax): boolean {
if (!node.stringLiteral) {
if (node.name.kind !== SyntaxKind.StringLiteral) {
for (var i = 0, n = node.moduleElements.length; i < n; i++) {
var child = node.moduleElements[i];
if (child.kind() === SyntaxKind.ImportDeclaration) {
if (child.kind === SyntaxKind.ImportDeclaration) {
var importDeclaration = <ImportDeclarationSyntax>child;
if (importDeclaration.moduleReference.kind() === SyntaxKind.ExternalModuleReference) {
if (importDeclaration.moduleReference.kind === SyntaxKind.ExternalModuleReference) {
this.pushDiagnostic(importDeclaration, DiagnosticCode.Import_declarations_in_an_internal_module_cannot_reference_an_external_module);
}
}
@@ -827,21 +849,21 @@ module TypeScript {
public visitModuleDeclaration(node: ModuleDeclarationSyntax): void {
if (this.checkForDisallowedDeclareModifier(node.modifiers) ||
this.checkForRequiredDeclareModifier(node, node.stringLiteral ? node.stringLiteral : firstToken(node.name), node.modifiers) ||
this.checkForRequiredDeclareModifier(node, firstToken(node.name), node.modifiers) ||
this.checkModuleElementModifiers(node.modifiers) ||
this.checkForDisallowedImportDeclaration(node)) {
return;
}
if (node.stringLiteral) {
if (node.name.kind === SyntaxKind.StringLiteral) {
if (!this.inAmbientDeclaration && !SyntaxUtilities.containsToken(node.modifiers, SyntaxKind.DeclareKeyword)) {
this.pushDiagnostic(node.stringLiteral, DiagnosticCode.Only_ambient_modules_can_use_quoted_names);
this.pushDiagnostic(node.name, DiagnosticCode.Only_ambient_modules_can_use_quoted_names);
return;
}
}
if (!node.stringLiteral && this.checkForDisallowedExportAssignment(node)) {
if (node.name.kind !== SyntaxKind.StringLiteral && this.checkForDisallowedExportAssignment(node)) {
return;
}
@@ -855,7 +877,7 @@ module TypeScript {
for (var i = 0, n = node.moduleElements.length; i < n; i++) {
var child = node.moduleElements[i];
if (child.kind() === SyntaxKind.ExportAssignment) {
if (child.kind === SyntaxKind.ExportAssignment) {
this.pushDiagnostic(child, DiagnosticCode.Export_assignment_cannot_be_used_in_internal_modules);
return true;
}
@@ -879,7 +901,7 @@ module TypeScript {
if (this.inAmbientDeclaration || this.syntaxTree.isDeclaration()) {
// Provide a specialized message for a block as a statement versus the block as a
// function body.
if (node.parent.kind() === SyntaxKind.List) {
if (node.parent.kind === SyntaxKind.List) {
this.pushDiagnostic(firstToken(node), DiagnosticCode.Statements_are_not_allowed_in_ambient_contexts);
}
else {
@@ -960,7 +982,7 @@ module TypeScript {
private inSwitchStatement(ast: ISyntaxElement): boolean {
while (ast) {
if (ast.kind() === SyntaxKind.SwitchStatement) {
if (ast.kind === SyntaxKind.SwitchStatement) {
return true;
}
@@ -975,7 +997,7 @@ module TypeScript {
}
private isIterationStatement(ast: ISyntaxElement): boolean {
switch (ast.kind()) {
switch (ast.kind) {
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.WhileStatement:
@@ -1007,7 +1029,7 @@ module TypeScript {
element = element.parent;
while (element) {
if (element.kind() === SyntaxKind.LabeledStatement) {
if (element.kind === SyntaxKind.LabeledStatement) {
var labeledStatement = <LabeledStatementSyntax>element;
if (breakable) {
// Breakable labels can be placed on any construct
@@ -1033,7 +1055,7 @@ module TypeScript {
}
private labelIsOnContinuableConstruct(statement: ISyntaxElement): boolean {
switch (statement.kind()) {
switch (statement.kind) {
case SyntaxKind.LabeledStatement:
// Labels work transitively. i.e. if you have:
// foo:
@@ -1136,7 +1158,7 @@ module TypeScript {
}
private checkForInLeftHandSideExpression(node: ForInStatementSyntax): boolean {
if (node.left && !SyntaxUtilities.isLeftHandSizeExpression(node.left)) {
if (node.left.kind !== SyntaxKind.VariableDeclaration && !SyntaxUtilities.isLeftHandSizeExpression(node.left)) {
this.pushDiagnostic(node.left, DiagnosticCode.Invalid_left_hand_side_in_for_in_statement);
return true;
}
@@ -1148,8 +1170,8 @@ module TypeScript {
// The parser accepts a Variable Declaration in a ForInStatement, but the grammar only
// allows a very restricted form. Specifically, there must be only a single Variable
// Declarator in the Declaration.
if (node.variableDeclaration && node.variableDeclaration.variableDeclarators.length > 1) {
this.pushDiagnostic(node.variableDeclaration, DiagnosticCode.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement);
if (node.left.kind === SyntaxKind.VariableDeclaration && (<VariableDeclarationSyntax>node.left).variableDeclarators.length > 1) {
this.pushDiagnostic(node.left, DiagnosticCode.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement);
return true;
}
@@ -1283,10 +1305,10 @@ module TypeScript {
return false;
}
private checkForDisallowedModifiers(parent: ISyntaxElement, modifiers: ISyntaxToken[]): boolean {
private checkForDisallowedModifiers(modifiers: ISyntaxToken[]): boolean {
if (this.inBlock || this.inObjectLiteralExpression) {
if (modifiers.length > 0) {
this.pushDiagnostic(childAt(modifiers, 0), DiagnosticCode.Modifiers_cannot_appear_here);
this.pushDiagnostic(modifiers[0], DiagnosticCode.Modifiers_cannot_appear_here);
return true;
}
}
@@ -1296,7 +1318,7 @@ module TypeScript {
public visitFunctionDeclaration(node: FunctionDeclarationSyntax): void {
if (this.checkForDisallowedDeclareModifier(node.modifiers) ||
this.checkForDisallowedModifiers(node, node.modifiers) ||
this.checkForDisallowedModifiers(node.modifiers) ||
this.checkForRequiredDeclareModifier(node, node.identifier, node.modifiers) ||
this.checkModuleElementModifiers(node.modifiers) ||
this.checkForDisallowedEvalOrArguments(node, node.identifier)) {
@@ -1318,9 +1340,17 @@ module TypeScript {
super.visitFunctionExpression(node);
}
public visitFunctionPropertyAssignment(node: FunctionPropertyAssignmentSyntax): void {
if (this.checkForDisallowedTemplatePropertyName(node.propertyName)) {
return;
}
super.visitFunctionPropertyAssignment(node);
}
public visitVariableStatement(node: VariableStatementSyntax): void {
if (this.checkForDisallowedDeclareModifier(node.modifiers) ||
this.checkForDisallowedModifiers(node, node.modifiers) ||
this.checkForDisallowedModifiers(node.modifiers) ||
this.checkForRequiredDeclareModifier(node, node.variableDeclaration.varKeyword, node.modifiers) ||
this.checkModuleElementModifiers(node.modifiers)) {
@@ -1333,10 +1363,10 @@ module TypeScript {
this.inAmbientDeclaration = savedInAmbientDeclaration;
}
private checkListSeparators<T extends ISyntaxNodeOrToken>(parent: ISyntaxElement, list: T[], kind: SyntaxKind): boolean {
for (var i = 0, n = childCount(list); i < n; i++) {
var child = childAt(list, i);
if (i % 2 === 1 && child.kind() !== kind) {
private checkListSeparators<T extends ISyntaxNodeOrToken>(list: ISeparatedSyntaxList<T>, kind: SyntaxKind): boolean {
for (var i = 0, n = separatorCount(list); i < n; i++) {
var child = separatorAt(list, i);
if (child.kind !== kind) {
this.pushDiagnostic(child, DiagnosticCode._0_expected, [SyntaxFacts.getText(kind)]);
}
}
@@ -1345,7 +1375,7 @@ module TypeScript {
}
public visitObjectType(node: ObjectTypeSyntax): void {
if (this.checkListSeparators(node, node.typeMembers, SyntaxKind.SemicolonToken)) {
if (this.checkListSeparators(node.typeMembers, SyntaxKind.SemicolonToken)) {
return;
}
@@ -1382,16 +1412,36 @@ module TypeScript {
public visitVariableDeclarator(node: VariableDeclaratorSyntax): void {
if (this.checkVariableDeclaratorInitializer(node) ||
this.checkVariableDeclaratorIdentifier(node)) {
this.checkVariableDeclaratorIdentifier(node) ||
this.checkForDisallowedTemplatePropertyName(node.propertyName)) {
return;
}
super.visitVariableDeclarator(node);
}
private checkForDisallowedTemplatePropertyName(propertyName: IPropertyNameSyntax): boolean {
if (propertyName.kind === SyntaxKind.NoSubstitutionTemplateToken) {
this.pushDiagnostic(propertyName, DiagnosticCode.Template_literal_cannot_be_used_as_an_element_name);
return true;
}
return false;
}
private checkForDisallowedComputedPropertyName(propertyName: IPropertyNameSyntax): boolean {
if (propertyName.kind === SyntaxKind.ComputedPropertyName) {
this.pushDiagnostic(propertyName, DiagnosticCode.Computed_property_names_cannot_be_used_here);
return true;
}
return false;
}
private checkVariableDeclaratorIdentifier(node: VariableDeclaratorSyntax): boolean {
if (node.parent.kind() !== SyntaxKind.MemberVariableDeclaration) {
if (this.checkForDisallowedEvalOrArguments(node, node.propertyName)) {
if (node.parent.kind !== SyntaxKind.MemberVariableDeclaration) {
Debug.assert(isToken(node.propertyName), "A normal variable declarator must always have a token for a name.");
if (this.checkForDisallowedEvalOrArguments(node, <ISyntaxToken>node.propertyName)) {
return true;
}
}
@@ -1423,8 +1473,8 @@ module TypeScript {
private checkConstructorModifiers(modifiers: ISyntaxToken[]): boolean {
for (var i = 0, n = modifiers.length; i < n; i++) {
var child = modifiers[i];
if (child.kind() !== SyntaxKind.PublicKeyword) {
this.pushDiagnostic(child, DiagnosticCode._0_modifier_cannot_appear_on_a_constructor_declaration, [SyntaxFacts.getText(child.kind())]);
if (child.kind !== SyntaxKind.PublicKeyword) {
this.pushDiagnostic(child, DiagnosticCode._0_modifier_cannot_appear_on_a_constructor_declaration, [SyntaxFacts.getText(child.kind)]);
return true;
}
}
@@ -1494,9 +1544,9 @@ module TypeScript {
}
private isPreIncrementOrDecrementExpression(node: PrefixUnaryExpressionSyntax) {
switch (node.kind()) {
case SyntaxKind.PreDecrementExpression:
case SyntaxKind.PreIncrementExpression:
switch (node.operatorToken.kind) {
case SyntaxKind.MinusMinusToken:
case SyntaxKind.PlusPlusToken:
return true;
}
@@ -1504,7 +1554,7 @@ module TypeScript {
}
public visitDeleteExpression(node: DeleteExpressionSyntax): void {
if (parsedInStrictMode(node) && node.expression.kind() === SyntaxKind.IdentifierName) {
if (parsedInStrictMode(node) && node.expression.kind === SyntaxKind.IdentifierName) {
this.pushDiagnostic(firstToken(node), DiagnosticCode.delete_cannot_be_called_on_an_identifier_in_strict_mode);
return;
}
@@ -1513,7 +1563,7 @@ module TypeScript {
}
private checkIllegalAssignment(node: BinaryExpressionSyntax): boolean {
if (parsedInStrictMode(node) && SyntaxFacts.isAssignmentOperatorToken(node.operatorToken.kind()) && this.isEvalOrArguments(node.left)) {
if (parsedInStrictMode(node) && SyntaxFacts.isAssignmentOperatorToken(node.operatorToken.kind) && this.isEvalOrArguments(node.left)) {
this.pushDiagnostic(node.operatorToken, DiagnosticCode.Invalid_use_of_0_in_strict_mode, [this.getEvalOrArguments(node.left)]);
return true;
}
@@ -1522,18 +1572,18 @@ module TypeScript {
}
private getEvalOrArguments(expr: IExpressionSyntax): string {
if (expr.kind() === SyntaxKind.IdentifierName) {
if (expr.kind === SyntaxKind.IdentifierName) {
var text = tokenValueText(<ISyntaxToken>expr);
if (text === "eval" || text === "arguments") {
return text;
}
}
return null;
return undefined;
}
private isEvalOrArguments(expr: IExpressionSyntax): boolean {
return this.getEvalOrArguments(expr) !== null;
return !!this.getEvalOrArguments(expr);
}
public visitConstraint(node: ConstraintSyntax): void {
@@ -1545,7 +1595,7 @@ module TypeScript {
}
private checkConstraintType(node: ConstraintSyntax): boolean {
if (!SyntaxFacts.isType(node.typeOrExpression.kind())) {
if (!SyntaxFacts.isType(node.typeOrExpression.kind)) {
this.pushDiagnostic(node.typeOrExpression, DiagnosticCode.Type_expected);
return true;
}
@@ -1583,7 +1633,7 @@ module TypeScript {
}
}
return null;
return undefined;
}
function implicitImportSpanWorker(trivia: ISyntaxTrivia): TextSpan {
@@ -1594,7 +1644,7 @@ module TypeScript {
return new TextSpan(trivia.fullStart(), trivia.fullWidth());
}
return null;
return undefined;
}
function topLevelImportOrExportSpan(node: SourceUnitSyntax): TextSpan {
@@ -1602,19 +1652,19 @@ module TypeScript {
var moduleElement = node.moduleElements[i];
var _firstToken = firstToken(moduleElement);
if (_firstToken !== null && _firstToken.kind() === SyntaxKind.ExportKeyword) {
if (_firstToken && _firstToken.kind === SyntaxKind.ExportKeyword) {
return new TextSpan(start(_firstToken), width(_firstToken));
}
if (moduleElement.kind() === SyntaxKind.ImportDeclaration) {
if (moduleElement.kind === SyntaxKind.ImportDeclaration) {
var importDecl = <ImportDeclarationSyntax>moduleElement;
if (importDecl.moduleReference.kind() === SyntaxKind.ExternalModuleReference) {
if (importDecl.moduleReference.kind === SyntaxKind.ExternalModuleReference) {
var literal = (<TypeScript.ExternalModuleReferenceSyntax>importDecl.moduleReference).stringLiteral;
return new TextSpan(start(literal), width(literal));
}
}
}
return null;
return undefined;
}
}
+9 -12
View File
@@ -2,8 +2,8 @@
module TypeScript {
export interface ISyntaxTrivia {
parent?: ISyntaxTriviaList;
kind(): SyntaxKind;
parent: ISyntaxTriviaList;
kind: SyntaxKind;
isWhitespace(): boolean;
isComment(): boolean;
@@ -25,11 +25,9 @@ module TypeScript {
module TypeScript.Syntax {
class AbstractTrivia implements ISyntaxTrivia {
constructor(private _kind: SyntaxKind) {
}
public parent: ISyntaxTriviaList;
public kind(): SyntaxKind {
return this._kind;
constructor(public kind: SyntaxKind) {
}
public clone(): ISyntaxTrivia {
@@ -53,19 +51,19 @@ module TypeScript.Syntax {
}
public isWhitespace(): boolean {
return this.kind() === SyntaxKind.WhitespaceTrivia;
return this.kind === SyntaxKind.WhitespaceTrivia;
}
public isComment(): boolean {
return this.kind() === SyntaxKind.SingleLineCommentTrivia || this.kind() === SyntaxKind.MultiLineCommentTrivia;
return this.kind === SyntaxKind.SingleLineCommentTrivia || this.kind === SyntaxKind.MultiLineCommentTrivia;
}
public isNewLine(): boolean {
return this.kind() === SyntaxKind.NewLineTrivia;
return this.kind === SyntaxKind.NewLineTrivia;
}
public isSkippedToken(): boolean {
return this.kind() === SyntaxKind.SkippedTokenTrivia;
return this.kind === SyntaxKind.SkippedTokenTrivia;
}
}
@@ -103,7 +101,7 @@ module TypeScript.Syntax {
}
public clone(): ISyntaxTrivia {
return new DeferredTrivia(this.kind(), this._text, this._fullStart, this._fullWidth);
return new DeferredTrivia(this.kind, this._text, this._fullStart, this._fullWidth);
}
public fullStart(): number {
@@ -129,7 +127,6 @@ module TypeScript.Syntax {
export function skippedTokenTrivia(token: ISyntaxToken, text: ISimpleText): ISyntaxTrivia {
Debug.assert(!token.hasLeadingTrivia());
Debug.assert(!token.hasTrailingTrivia());
Debug.assert(token.fullWidth() > 0);
return new SkippedTokenTrivia(token, token.fullText(text));
}
+6 -18
View File
@@ -28,10 +28,6 @@ module TypeScript {
module TypeScript.Syntax {
class EmptyTriviaList implements ISyntaxTriviaList {
public kind() {
return SyntaxKind.TriviaList;
}
public isShared(): boolean {
return true;
}
@@ -80,7 +76,7 @@ module TypeScript.Syntax {
export var emptyTriviaList: ISyntaxTriviaList = new EmptyTriviaList();
function isComment(trivia: ISyntaxTrivia): boolean {
return trivia.kind() === SyntaxKind.MultiLineCommentTrivia || trivia.kind() === SyntaxKind.SingleLineCommentTrivia;
return trivia.kind === SyntaxKind.MultiLineCommentTrivia || trivia.kind === SyntaxKind.SingleLineCommentTrivia;
}
class SingletonSyntaxTriviaList implements ISyntaxTriviaList {
@@ -91,10 +87,6 @@ module TypeScript.Syntax {
this.item.parent = this;
}
public kind() {
return SyntaxKind.TriviaList;
}
public isShared(): boolean {
return false;
}
@@ -128,11 +120,11 @@ module TypeScript.Syntax {
}
public hasNewLine(): boolean {
return this.item.kind() === SyntaxKind.NewLineTrivia;
return this.item.kind === SyntaxKind.NewLineTrivia;
}
public hasSkippedToken(): boolean {
return this.item.kind() === SyntaxKind.SkippedTokenTrivia;
return this.item.kind === SyntaxKind.SkippedTokenTrivia;
}
public toArray(): ISyntaxTrivia[] {
@@ -155,10 +147,6 @@ module TypeScript.Syntax {
});
}
public kind() {
return SyntaxKind.TriviaList;
}
public isShared(): boolean {
return false;
}
@@ -205,7 +193,7 @@ module TypeScript.Syntax {
public hasNewLine(): boolean {
for (var i = 0; i < this.trivia.length; i++) {
if (this.trivia[i].kind() === SyntaxKind.NewLineTrivia) {
if (this.trivia[i].kind === SyntaxKind.NewLineTrivia) {
return true;
}
}
@@ -215,7 +203,7 @@ module TypeScript.Syntax {
public hasSkippedToken(): boolean {
for (var i = 0; i < this.trivia.length; i++) {
if (this.trivia[i].kind() === SyntaxKind.SkippedTokenTrivia) {
if (this.trivia[i].kind === SyntaxKind.SkippedTokenTrivia) {
return true;
}
}
@@ -233,7 +221,7 @@ module TypeScript.Syntax {
}
export function triviaList(trivia: ISyntaxTrivia[]): ISyntaxTriviaList {
if (trivia === undefined || trivia === null || trivia.length === 0) {
if (!trivia || trivia.length === 0) {
return Syntax.emptyTriviaList;
}
+44 -113
View File
@@ -1,9 +1,19 @@
///<reference path='references.ts' />
module TypeScript {
export class SyntaxUtilities {
public static isAnyFunctionExpressionOrDeclaration(ast: ISyntaxElement): boolean {
switch (ast.kind()) {
export function childCount(element: ISyntaxElement): number {
if (isList(element)) { return (<ISyntaxNodeOrToken[]>element).length; }
return (<ISyntaxNodeOrToken>element).childCount;
}
export function childAt(element: ISyntaxElement, index: number): ISyntaxElement {
if (isList(element)) { return (<ISyntaxNodeOrToken[]>element)[index]; }
return (<ISyntaxNodeOrToken>element).childAt(index);
}
export module SyntaxUtilities {
export function isAnyFunctionExpressionOrDeclaration(ast: ISyntaxElement): boolean {
switch (ast.kind) {
case SyntaxKind.SimpleArrowFunctionExpression:
case SyntaxKind.ParenthesizedArrowFunctionExpression:
case SyntaxKind.FunctionExpression:
@@ -19,24 +29,25 @@ module TypeScript {
return false;
}
public static isLastTokenOnLine(token: ISyntaxToken, text: ISimpleText): boolean {
export function isLastTokenOnLine(token: ISyntaxToken, text: ISimpleText): boolean {
var _nextToken = nextToken(token, text);
if (_nextToken === null) {
if (_nextToken === undefined) {
return true;
}
var lineMap = text.lineMap();
var tokenLine = lineMap.getLineNumberFromPosition(end(token, text));
var tokenLine = lineMap.getLineNumberFromPosition(fullEnd(token));
var nextTokenLine = lineMap.getLineNumberFromPosition(start(_nextToken, text));
return tokenLine !== nextTokenLine;
}
public static isLeftHandSizeExpression(element: ISyntaxElement) {
export function isLeftHandSizeExpression(element: ISyntaxElement) {
if (element) {
switch (element.kind()) {
switch (element.kind) {
case SyntaxKind.MemberAccessExpression:
case SyntaxKind.ElementAccessExpression:
case SyntaxKind.TemplateAccessExpression:
case SyntaxKind.ObjectCreationExpression:
case SyntaxKind.InvocationExpression:
case SyntaxKind.ArrayLiteralExpression:
@@ -59,89 +70,9 @@ module TypeScript {
return false;
}
public static isExpression(element: ISyntaxElement) {
export function isSwitchClause(element: ISyntaxElement) {
if (element) {
switch (element.kind()) {
case SyntaxKind.IdentifierName:
case SyntaxKind.RegularExpressionLiteral:
case SyntaxKind.NumericLiteral:
case SyntaxKind.StringLiteral:
case SyntaxKind.FalseKeyword:
case SyntaxKind.NullKeyword:
case SyntaxKind.ThisKeyword:
case SyntaxKind.TrueKeyword:
case SyntaxKind.SuperKeyword:
case SyntaxKind.PlusExpression:
case SyntaxKind.NegateExpression:
case SyntaxKind.BitwiseNotExpression:
case SyntaxKind.LogicalNotExpression:
case SyntaxKind.PreIncrementExpression:
case SyntaxKind.PreDecrementExpression:
case SyntaxKind.DeleteExpression:
case SyntaxKind.TypeOfExpression:
case SyntaxKind.VoidExpression:
case SyntaxKind.CommaExpression:
case SyntaxKind.AssignmentExpression:
case SyntaxKind.AddAssignmentExpression:
case SyntaxKind.SubtractAssignmentExpression:
case SyntaxKind.MultiplyAssignmentExpression:
case SyntaxKind.DivideAssignmentExpression:
case SyntaxKind.ModuloAssignmentExpression:
case SyntaxKind.AndAssignmentExpression:
case SyntaxKind.ExclusiveOrAssignmentExpression:
case SyntaxKind.OrAssignmentExpression:
case SyntaxKind.LeftShiftAssignmentExpression:
case SyntaxKind.SignedRightShiftAssignmentExpression:
case SyntaxKind.UnsignedRightShiftAssignmentExpression:
case SyntaxKind.ConditionalExpression:
case SyntaxKind.LogicalOrExpression:
case SyntaxKind.LogicalAndExpression:
case SyntaxKind.BitwiseOrExpression:
case SyntaxKind.BitwiseExclusiveOrExpression:
case SyntaxKind.BitwiseAndExpression:
case SyntaxKind.EqualsWithTypeConversionExpression:
case SyntaxKind.NotEqualsWithTypeConversionExpression:
case SyntaxKind.EqualsExpression:
case SyntaxKind.NotEqualsExpression:
case SyntaxKind.LessThanExpression:
case SyntaxKind.GreaterThanExpression:
case SyntaxKind.LessThanOrEqualExpression:
case SyntaxKind.GreaterThanOrEqualExpression:
case SyntaxKind.InstanceOfExpression:
case SyntaxKind.InExpression:
case SyntaxKind.LeftShiftExpression:
case SyntaxKind.SignedRightShiftExpression:
case SyntaxKind.UnsignedRightShiftExpression:
case SyntaxKind.MultiplyExpression:
case SyntaxKind.DivideExpression:
case SyntaxKind.ModuloExpression:
case SyntaxKind.AddExpression:
case SyntaxKind.SubtractExpression:
case SyntaxKind.PostIncrementExpression:
case SyntaxKind.PostDecrementExpression:
case SyntaxKind.MemberAccessExpression:
case SyntaxKind.InvocationExpression:
case SyntaxKind.ArrayLiteralExpression:
case SyntaxKind.ObjectLiteralExpression:
case SyntaxKind.ObjectCreationExpression:
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.ParenthesizedArrowFunctionExpression:
case SyntaxKind.SimpleArrowFunctionExpression:
case SyntaxKind.CastExpression:
case SyntaxKind.ElementAccessExpression:
case SyntaxKind.FunctionExpression:
case SyntaxKind.OmittedExpression:
return true;
}
}
return false;
}
public static isSwitchClause(element: ISyntaxElement) {
if (element) {
switch (element.kind()) {
switch (element.kind) {
case SyntaxKind.CaseSwitchClause:
case SyntaxKind.DefaultSwitchClause:
return true;
@@ -151,9 +82,9 @@ module TypeScript {
return false;
}
public static isTypeMember(element: ISyntaxElement) {
export function isTypeMember(element: ISyntaxElement) {
if (element) {
switch (element.kind()) {
switch (element.kind) {
case SyntaxKind.ConstructSignature:
case SyntaxKind.MethodSignature:
case SyntaxKind.IndexSignature:
@@ -166,9 +97,9 @@ module TypeScript {
return false;
}
public static isClassElement(element: ISyntaxElement) {
export function isClassElement(element: ISyntaxElement) {
if (element) {
switch (element.kind()) {
switch (element.kind) {
case SyntaxKind.ConstructorDeclaration:
case SyntaxKind.IndexMemberDeclaration:
case SyntaxKind.MemberFunctionDeclaration:
@@ -183,9 +114,9 @@ module TypeScript {
return false;
}
public static isModuleElement(element: ISyntaxElement) {
export function isModuleElement(element: ISyntaxElement) {
if (element) {
switch (element.kind()) {
switch (element.kind) {
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ExportAssignment:
case SyntaxKind.ClassDeclaration:
@@ -220,9 +151,9 @@ module TypeScript {
return false;
}
public static isStatement(element: ISyntaxElement) {
export function isStatement(element: ISyntaxElement) {
if (element) {
switch (element.kind()) {
switch (element.kind) {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.VariableStatement:
case SyntaxKind.Block:
@@ -249,11 +180,11 @@ module TypeScript {
return false;
}
public static isAngleBracket(positionedElement: ISyntaxElement): boolean {
export function isAngleBracket(positionedElement: ISyntaxElement): boolean {
var element = positionedElement;
var parent = positionedElement.parent;
if (parent !== null && (element.kind() === SyntaxKind.LessThanToken || element.kind() === SyntaxKind.GreaterThanToken)) {
switch (parent.kind()) {
if (parent && (element.kind === SyntaxKind.LessThanToken || element.kind === SyntaxKind.GreaterThanToken)) {
switch (parent.kind) {
case SyntaxKind.TypeArgumentList:
case SyntaxKind.TypeParameterList:
case SyntaxKind.CastExpression:
@@ -264,27 +195,27 @@ module TypeScript {
return false;
}
public static getToken(list: ISyntaxToken[], kind: SyntaxKind): ISyntaxToken {
export function getToken(list: ISyntaxToken[], kind: SyntaxKind): ISyntaxToken {
for (var i = 0, n = list.length; i < n; i++) {
var token = list[i];
if (token.kind() === kind) {
if (token.kind === kind) {
return token;
}
}
return null;
return undefined;
}
public static containsToken(list: ISyntaxToken[], kind: SyntaxKind): boolean {
return SyntaxUtilities.getToken(list, kind) !== null;
export function containsToken(list: ISyntaxToken[], kind: SyntaxKind): boolean {
return !!SyntaxUtilities.getToken(list, kind);
}
public static hasExportKeyword(moduleElement: IModuleElementSyntax): boolean {
return SyntaxUtilities.getExportKeyword(moduleElement) !== null;
export function hasExportKeyword(moduleElement: IModuleElementSyntax): boolean {
return !!SyntaxUtilities.getExportKeyword(moduleElement);
}
public static getExportKeyword(moduleElement: IModuleElementSyntax): ISyntaxToken {
switch (moduleElement.kind()) {
export function getExportKeyword(moduleElement: IModuleElementSyntax): ISyntaxToken {
switch (moduleElement.kind) {
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.FunctionDeclaration:
@@ -294,17 +225,17 @@ module TypeScript {
case SyntaxKind.ImportDeclaration:
return SyntaxUtilities.getToken((<any>moduleElement).modifiers, SyntaxKind.ExportKeyword);
default:
return null;
return undefined;
}
}
public static isAmbientDeclarationSyntax(positionNode: ISyntaxNode): boolean {
export function isAmbientDeclarationSyntax(positionNode: ISyntaxNode): boolean {
if (!positionNode) {
return false;
}
var node = positionNode;
switch (node.kind()) {
switch (node.kind) {
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.FunctionDeclaration:
+19 -13
View File
@@ -2,9 +2,8 @@
module TypeScript {
export function visitNodeOrToken(visitor: ISyntaxVisitor, element: ISyntaxNodeOrToken): any {
if (element === null) { return null; }
if (isToken(element)) { return visitor.visitToken(<ISyntaxToken>element); }
switch (element.kind()) {
if (element === undefined) { return undefined; }
switch (element.kind) {
case SyntaxKind.SourceUnit: return visitor.visitSourceUnit(<SourceUnitSyntax>element);
case SyntaxKind.QualifiedName: return visitor.visitQualifiedName(<QualifiedNameSyntax>element);
case SyntaxKind.ObjectType: return visitor.visitObjectType(<ObjectTypeSyntax>element);
@@ -14,6 +13,8 @@ module TypeScript {
case SyntaxKind.GenericType: return visitor.visitGenericType(<GenericTypeSyntax>element);
case SyntaxKind.TypeQuery: return visitor.visitTypeQuery(<TypeQuerySyntax>element);
case SyntaxKind.TupleType: return visitor.visitTupleType(<TupleTypeSyntax>element);
case SyntaxKind.UnionType: return visitor.visitUnionType(<UnionTypeSyntax>element);
case SyntaxKind.ParenthesizedType: return visitor.visitParenthesizedType(<ParenthesizedTypeSyntax>element);
case SyntaxKind.InterfaceDeclaration: return visitor.visitInterfaceDeclaration(<InterfaceDeclarationSyntax>element);
case SyntaxKind.FunctionDeclaration: return visitor.visitFunctionDeclaration(<FunctionDeclarationSyntax>element);
case SyntaxKind.ModuleDeclaration: return visitor.visitModuleDeclaration(<ModuleDeclarationSyntax>element);
@@ -50,16 +51,13 @@ module TypeScript {
case SyntaxKind.DoStatement: return visitor.visitDoStatement(<DoStatementSyntax>element);
case SyntaxKind.DebuggerStatement: return visitor.visitDebuggerStatement(<DebuggerStatementSyntax>element);
case SyntaxKind.WithStatement: return visitor.visitWithStatement(<WithStatementSyntax>element);
case SyntaxKind.PreIncrementExpression: case SyntaxKind.PreDecrementExpression: case SyntaxKind.PlusExpression: case SyntaxKind.NegateExpression: case SyntaxKind.BitwiseNotExpression: case SyntaxKind.LogicalNotExpression:
return visitor.visitPrefixUnaryExpression(<PrefixUnaryExpressionSyntax>element);
case SyntaxKind.PrefixUnaryExpression: return visitor.visitPrefixUnaryExpression(<PrefixUnaryExpressionSyntax>element);
case SyntaxKind.DeleteExpression: return visitor.visitDeleteExpression(<DeleteExpressionSyntax>element);
case SyntaxKind.TypeOfExpression: return visitor.visitTypeOfExpression(<TypeOfExpressionSyntax>element);
case SyntaxKind.VoidExpression: return visitor.visitVoidExpression(<VoidExpressionSyntax>element);
case SyntaxKind.ConditionalExpression: return visitor.visitConditionalExpression(<ConditionalExpressionSyntax>element);
case SyntaxKind.MultiplyExpression: case SyntaxKind.DivideExpression: case SyntaxKind.ModuloExpression: case SyntaxKind.AddExpression: case SyntaxKind.SubtractExpression: case SyntaxKind.LeftShiftExpression: case SyntaxKind.SignedRightShiftExpression: case SyntaxKind.UnsignedRightShiftExpression: case SyntaxKind.LessThanExpression: case SyntaxKind.GreaterThanExpression: case SyntaxKind.LessThanOrEqualExpression: case SyntaxKind.GreaterThanOrEqualExpression: case SyntaxKind.InstanceOfExpression: case SyntaxKind.InExpression: case SyntaxKind.EqualsWithTypeConversionExpression: case SyntaxKind.NotEqualsWithTypeConversionExpression: case SyntaxKind.EqualsExpression: case SyntaxKind.NotEqualsExpression: case SyntaxKind.BitwiseAndExpression: case SyntaxKind.BitwiseExclusiveOrExpression: case SyntaxKind.BitwiseOrExpression: case SyntaxKind.LogicalAndExpression: case SyntaxKind.LogicalOrExpression: case SyntaxKind.OrAssignmentExpression: case SyntaxKind.AndAssignmentExpression: case SyntaxKind.ExclusiveOrAssignmentExpression: case SyntaxKind.LeftShiftAssignmentExpression: case SyntaxKind.SignedRightShiftAssignmentExpression: case SyntaxKind.UnsignedRightShiftAssignmentExpression: case SyntaxKind.AddAssignmentExpression: case SyntaxKind.SubtractAssignmentExpression: case SyntaxKind.MultiplyAssignmentExpression: case SyntaxKind.DivideAssignmentExpression: case SyntaxKind.ModuloAssignmentExpression: case SyntaxKind.AssignmentExpression: case SyntaxKind.CommaExpression:
return visitor.visitBinaryExpression(<BinaryExpressionSyntax>element);
case SyntaxKind.PostIncrementExpression: case SyntaxKind.PostDecrementExpression:
return visitor.visitPostfixUnaryExpression(<PostfixUnaryExpressionSyntax>element);
case SyntaxKind.BinaryExpression: return visitor.visitBinaryExpression(<BinaryExpressionSyntax>element);
case SyntaxKind.PostfixUnaryExpression: return visitor.visitPostfixUnaryExpression(<PostfixUnaryExpressionSyntax>element);
case SyntaxKind.MemberAccessExpression: return visitor.visitMemberAccessExpression(<MemberAccessExpressionSyntax>element);
case SyntaxKind.InvocationExpression: return visitor.visitInvocationExpression(<InvocationExpressionSyntax>element);
case SyntaxKind.ArrayLiteralExpression: return visitor.visitArrayLiteralExpression(<ArrayLiteralExpressionSyntax>element);
@@ -72,20 +70,22 @@ module TypeScript {
case SyntaxKind.ElementAccessExpression: return visitor.visitElementAccessExpression(<ElementAccessExpressionSyntax>element);
case SyntaxKind.FunctionExpression: return visitor.visitFunctionExpression(<FunctionExpressionSyntax>element);
case SyntaxKind.OmittedExpression: return visitor.visitOmittedExpression(<OmittedExpressionSyntax>element);
case SyntaxKind.TemplateExpression: return visitor.visitTemplateExpression(<TemplateExpressionSyntax>element);
case SyntaxKind.TemplateAccessExpression: return visitor.visitTemplateAccessExpression(<TemplateAccessExpressionSyntax>element);
case SyntaxKind.VariableDeclaration: return visitor.visitVariableDeclaration(<VariableDeclarationSyntax>element);
case SyntaxKind.VariableDeclarator: return visitor.visitVariableDeclarator(<VariableDeclaratorSyntax>element);
case SyntaxKind.ArgumentList: return visitor.visitArgumentList(<ArgumentListSyntax>element);
case SyntaxKind.ParameterList: return visitor.visitParameterList(<ParameterListSyntax>element);
case SyntaxKind.TypeArgumentList: return visitor.visitTypeArgumentList(<TypeArgumentListSyntax>element);
case SyntaxKind.TypeParameterList: return visitor.visitTypeParameterList(<TypeParameterListSyntax>element);
case SyntaxKind.ExtendsHeritageClause: case SyntaxKind.ImplementsHeritageClause:
return visitor.visitHeritageClause(<HeritageClauseSyntax>element);
case SyntaxKind.HeritageClause: return visitor.visitHeritageClause(<HeritageClauseSyntax>element);
case SyntaxKind.EqualsValueClause: return visitor.visitEqualsValueClause(<EqualsValueClauseSyntax>element);
case SyntaxKind.CaseSwitchClause: return visitor.visitCaseSwitchClause(<CaseSwitchClauseSyntax>element);
case SyntaxKind.DefaultSwitchClause: return visitor.visitDefaultSwitchClause(<DefaultSwitchClauseSyntax>element);
case SyntaxKind.ElseClause: return visitor.visitElseClause(<ElseClauseSyntax>element);
case SyntaxKind.CatchClause: return visitor.visitCatchClause(<CatchClauseSyntax>element);
case SyntaxKind.FinallyClause: return visitor.visitFinallyClause(<FinallyClauseSyntax>element);
case SyntaxKind.TemplateClause: return visitor.visitTemplateClause(<TemplateClauseSyntax>element);
case SyntaxKind.TypeParameter: return visitor.visitTypeParameter(<TypeParameterSyntax>element);
case SyntaxKind.Constraint: return visitor.visitConstraint(<ConstraintSyntax>element);
case SyntaxKind.SimplePropertyAssignment: return visitor.visitSimplePropertyAssignment(<SimplePropertyAssignmentSyntax>element);
@@ -93,11 +93,11 @@ module TypeScript {
case SyntaxKind.Parameter: return visitor.visitParameter(<ParameterSyntax>element);
case SyntaxKind.EnumElement: return visitor.visitEnumElement(<EnumElementSyntax>element);
case SyntaxKind.TypeAnnotation: return visitor.visitTypeAnnotation(<TypeAnnotationSyntax>element);
case SyntaxKind.ComputedPropertyName: return visitor.visitComputedPropertyName(<ComputedPropertyNameSyntax>element);
case SyntaxKind.ExternalModuleReference: return visitor.visitExternalModuleReference(<ExternalModuleReferenceSyntax>element);
case SyntaxKind.ModuleNameModuleReference: return visitor.visitModuleNameModuleReference(<ModuleNameModuleReferenceSyntax>element);
default: return visitor.visitToken(<ISyntaxToken>element);
}
throw Errors.invalidOperation();
}
export interface ISyntaxVisitor {
@@ -111,6 +111,8 @@ module TypeScript {
visitGenericType(node: GenericTypeSyntax): any;
visitTypeQuery(node: TypeQuerySyntax): any;
visitTupleType(node: TupleTypeSyntax): any;
visitUnionType(node: UnionTypeSyntax): any;
visitParenthesizedType(node: ParenthesizedTypeSyntax): any;
visitInterfaceDeclaration(node: InterfaceDeclarationSyntax): any;
visitFunctionDeclaration(node: FunctionDeclarationSyntax): any;
visitModuleDeclaration(node: ModuleDeclarationSyntax): any;
@@ -166,6 +168,8 @@ module TypeScript {
visitElementAccessExpression(node: ElementAccessExpressionSyntax): any;
visitFunctionExpression(node: FunctionExpressionSyntax): any;
visitOmittedExpression(node: OmittedExpressionSyntax): any;
visitTemplateExpression(node: TemplateExpressionSyntax): any;
visitTemplateAccessExpression(node: TemplateAccessExpressionSyntax): any;
visitVariableDeclaration(node: VariableDeclarationSyntax): any;
visitVariableDeclarator(node: VariableDeclaratorSyntax): any;
visitArgumentList(node: ArgumentListSyntax): any;
@@ -179,6 +183,7 @@ module TypeScript {
visitElseClause(node: ElseClauseSyntax): any;
visitCatchClause(node: CatchClauseSyntax): any;
visitFinallyClause(node: FinallyClauseSyntax): any;
visitTemplateClause(node: TemplateClauseSyntax): any;
visitTypeParameter(node: TypeParameterSyntax): any;
visitConstraint(node: ConstraintSyntax): any;
visitSimplePropertyAssignment(node: SimplePropertyAssignmentSyntax): any;
@@ -186,6 +191,7 @@ module TypeScript {
visitParameter(node: ParameterSyntax): any;
visitEnumElement(node: EnumElementSyntax): any;
visitTypeAnnotation(node: TypeAnnotationSyntax): any;
visitComputedPropertyName(node: ComputedPropertyNameSyntax): any;
visitExternalModuleReference(node: ExternalModuleReferenceSyntax): any;
visitModuleNameModuleReference(node: ModuleNameModuleReferenceSyntax): any;
}
+161 -172
View File
@@ -5,53 +5,17 @@ module TypeScript {
public visitToken(token: ISyntaxToken): void {
}
public visitNode(node: ISyntaxNode): void {
visitNodeOrToken(this, node);
}
public visitNodeOrToken(nodeOrToken: ISyntaxNodeOrToken): void {
if (isToken(nodeOrToken)) {
this.visitToken(<ISyntaxToken>nodeOrToken);
}
else {
this.visitNode(<ISyntaxNode>nodeOrToken);
}
}
private visitOptionalToken(token: ISyntaxToken): void {
if (token === null) {
if (token === undefined) {
return;
}
this.visitToken(token);
}
public visitOptionalNode(node: ISyntaxNode): void {
if (node === null) {
return;
}
this.visitNode(node);
}
public visitOptionalNodeOrToken(nodeOrToken: ISyntaxNodeOrToken): void {
if (nodeOrToken === null) {
return;
}
this.visitNodeOrToken(nodeOrToken);
}
public visitList(list: ISyntaxNodeOrToken[]): void {
for (var i = 0, n = list.length; i < n; i++) {
this.visitNodeOrToken(list[i]);
}
}
public visitSeparatedList(list: ISyntaxNodeOrToken[]): void {
for (var i = 0, n = childCount(list); i < n; i++) {
var item = childAt(list, i);
this.visitNodeOrToken(item);
visitNodeOrToken(this, list[i]);
}
}
@@ -61,77 +25,87 @@ module TypeScript {
}
public visitQualifiedName(node: QualifiedNameSyntax): void {
this.visitNodeOrToken(node.left);
visitNodeOrToken(this, node.left);
this.visitToken(node.dotToken);
this.visitToken(node.right);
}
public visitObjectType(node: ObjectTypeSyntax): void {
this.visitToken(node.openBraceToken);
this.visitSeparatedList(node.typeMembers);
this.visitList(node.typeMembers);
this.visitToken(node.closeBraceToken);
}
public visitFunctionType(node: FunctionTypeSyntax): void {
this.visitOptionalNode(node.typeParameterList);
this.visitNode(node.parameterList);
visitNodeOrToken(this, node.typeParameterList);
visitNodeOrToken(this, node.parameterList);
this.visitToken(node.equalsGreaterThanToken);
this.visitNodeOrToken(node.type);
visitNodeOrToken(this, node.type);
}
public visitArrayType(node: ArrayTypeSyntax): void {
this.visitNodeOrToken(node.type);
visitNodeOrToken(this, node.type);
this.visitToken(node.openBracketToken);
this.visitToken(node.closeBracketToken);
}
public visitConstructorType(node: ConstructorTypeSyntax): void {
this.visitToken(node.newKeyword);
this.visitOptionalNode(node.typeParameterList);
this.visitNode(node.parameterList);
visitNodeOrToken(this, node.typeParameterList);
visitNodeOrToken(this, node.parameterList);
this.visitToken(node.equalsGreaterThanToken);
this.visitNodeOrToken(node.type);
visitNodeOrToken(this, node.type);
}
public visitGenericType(node: GenericTypeSyntax): void {
this.visitNodeOrToken(node.name);
this.visitNode(node.typeArgumentList);
visitNodeOrToken(this, node.name);
visitNodeOrToken(this, node.typeArgumentList);
}
public visitTypeQuery(node: TypeQuerySyntax): void {
this.visitToken(node.typeOfKeyword);
this.visitNodeOrToken(node.name);
visitNodeOrToken(this, node.name);
}
public visitTupleType(node: TupleTypeSyntax): void {
this.visitToken(node.openBracketToken);
this.visitSeparatedList(node.types);
this.visitList(node.types);
this.visitToken(node.closeBracketToken);
}
public visitUnionType(node: UnionTypeSyntax): void {
visitNodeOrToken(this, node.left);
this.visitToken(node.barToken);
visitNodeOrToken(this, node.right);
}
public visitParenthesizedType(node: ParenthesizedTypeSyntax): void {
this.visitToken(node.openParenToken);
visitNodeOrToken(this, node.type);
this.visitToken(node.closeParenToken);
}
public visitInterfaceDeclaration(node: InterfaceDeclarationSyntax): void {
this.visitList(node.modifiers);
this.visitToken(node.interfaceKeyword);
this.visitToken(node.identifier);
this.visitOptionalNode(node.typeParameterList);
visitNodeOrToken(this, node.typeParameterList);
this.visitList(node.heritageClauses);
this.visitNode(node.body);
visitNodeOrToken(this, node.body);
}
public visitFunctionDeclaration(node: FunctionDeclarationSyntax): void {
this.visitList(node.modifiers);
this.visitToken(node.functionKeyword);
this.visitToken(node.identifier);
this.visitNode(node.callSignature);
this.visitOptionalNode(node.block);
this.visitOptionalToken(node.semicolonToken);
visitNodeOrToken(this, node.callSignature);
visitNodeOrToken(this, node.body);
}
public visitModuleDeclaration(node: ModuleDeclarationSyntax): void {
this.visitList(node.modifiers);
this.visitToken(node.moduleKeyword);
this.visitOptionalNodeOrToken(node.name);
this.visitOptionalToken(node.stringLiteral);
visitNodeOrToken(this, node.name);
this.visitToken(node.openBraceToken);
this.visitList(node.moduleElements);
this.visitToken(node.closeBraceToken);
@@ -141,7 +115,7 @@ module TypeScript {
this.visitList(node.modifiers);
this.visitToken(node.classKeyword);
this.visitToken(node.identifier);
this.visitOptionalNode(node.typeParameterList);
visitNodeOrToken(this, node.typeParameterList);
this.visitList(node.heritageClauses);
this.visitToken(node.openBraceToken);
this.visitList(node.classElements);
@@ -153,7 +127,7 @@ module TypeScript {
this.visitToken(node.enumKeyword);
this.visitToken(node.identifier);
this.visitToken(node.openBraceToken);
this.visitSeparatedList(node.enumElements);
this.visitList(node.enumElements);
this.visitToken(node.closeBraceToken);
}
@@ -162,7 +136,7 @@ module TypeScript {
this.visitToken(node.importKeyword);
this.visitToken(node.identifier);
this.visitToken(node.equalsToken);
this.visitNodeOrToken(node.moduleReference);
visitNodeOrToken(this, node.moduleReference);
this.visitOptionalToken(node.semicolonToken);
}
@@ -175,76 +149,74 @@ module TypeScript {
public visitMemberFunctionDeclaration(node: MemberFunctionDeclarationSyntax): void {
this.visitList(node.modifiers);
this.visitToken(node.propertyName);
this.visitNode(node.callSignature);
this.visitOptionalNode(node.block);
this.visitOptionalToken(node.semicolonToken);
visitNodeOrToken(this, node.propertyName);
visitNodeOrToken(this, node.callSignature);
visitNodeOrToken(this, node.body);
}
public visitMemberVariableDeclaration(node: MemberVariableDeclarationSyntax): void {
this.visitList(node.modifiers);
this.visitNode(node.variableDeclarator);
visitNodeOrToken(this, node.variableDeclarator);
this.visitOptionalToken(node.semicolonToken);
}
public visitConstructorDeclaration(node: ConstructorDeclarationSyntax): void {
this.visitList(node.modifiers);
this.visitToken(node.constructorKeyword);
this.visitNode(node.callSignature);
this.visitOptionalNode(node.block);
this.visitOptionalToken(node.semicolonToken);
visitNodeOrToken(this, node.callSignature);
visitNodeOrToken(this, node.body);
}
public visitIndexMemberDeclaration(node: IndexMemberDeclarationSyntax): void {
this.visitList(node.modifiers);
this.visitNode(node.indexSignature);
visitNodeOrToken(this, node.indexSignature);
this.visitOptionalToken(node.semicolonToken);
}
public visitGetAccessor(node: GetAccessorSyntax): void {
this.visitList(node.modifiers);
this.visitToken(node.getKeyword);
this.visitToken(node.propertyName);
this.visitNode(node.callSignature);
this.visitNode(node.block);
visitNodeOrToken(this, node.propertyName);
visitNodeOrToken(this, node.callSignature);
visitNodeOrToken(this, node.block);
}
public visitSetAccessor(node: SetAccessorSyntax): void {
this.visitList(node.modifiers);
this.visitToken(node.setKeyword);
this.visitToken(node.propertyName);
this.visitNode(node.callSignature);
this.visitNode(node.block);
visitNodeOrToken(this, node.propertyName);
visitNodeOrToken(this, node.callSignature);
visitNodeOrToken(this, node.block);
}
public visitPropertySignature(node: PropertySignatureSyntax): void {
this.visitToken(node.propertyName);
visitNodeOrToken(this, node.propertyName);
this.visitOptionalToken(node.questionToken);
this.visitOptionalNode(node.typeAnnotation);
visitNodeOrToken(this, node.typeAnnotation);
}
public visitCallSignature(node: CallSignatureSyntax): void {
this.visitOptionalNode(node.typeParameterList);
this.visitNode(node.parameterList);
this.visitOptionalNode(node.typeAnnotation);
visitNodeOrToken(this, node.typeParameterList);
visitNodeOrToken(this, node.parameterList);
visitNodeOrToken(this, node.typeAnnotation);
}
public visitConstructSignature(node: ConstructSignatureSyntax): void {
this.visitToken(node.newKeyword);
this.visitNode(node.callSignature);
visitNodeOrToken(this, node.callSignature);
}
public visitIndexSignature(node: IndexSignatureSyntax): void {
this.visitToken(node.openBracketToken);
this.visitSeparatedList(node.parameters);
this.visitList(node.parameters);
this.visitToken(node.closeBracketToken);
this.visitOptionalNode(node.typeAnnotation);
visitNodeOrToken(this, node.typeAnnotation);
}
public visitMethodSignature(node: MethodSignatureSyntax): void {
this.visitToken(node.propertyName);
visitNodeOrToken(this, node.propertyName);
this.visitOptionalToken(node.questionToken);
this.visitNode(node.callSignature);
visitNodeOrToken(this, node.callSignature);
}
public visitBlock(node: BlockSyntax): void {
@@ -256,33 +228,33 @@ module TypeScript {
public visitIfStatement(node: IfStatementSyntax): void {
this.visitToken(node.ifKeyword);
this.visitToken(node.openParenToken);
this.visitNodeOrToken(node.condition);
visitNodeOrToken(this, node.condition);
this.visitToken(node.closeParenToken);
this.visitNodeOrToken(node.statement);
this.visitOptionalNode(node.elseClause);
visitNodeOrToken(this, node.statement);
visitNodeOrToken(this, node.elseClause);
}
public visitVariableStatement(node: VariableStatementSyntax): void {
this.visitList(node.modifiers);
this.visitNode(node.variableDeclaration);
visitNodeOrToken(this, node.variableDeclaration);
this.visitOptionalToken(node.semicolonToken);
}
public visitExpressionStatement(node: ExpressionStatementSyntax): void {
this.visitNodeOrToken(node.expression);
visitNodeOrToken(this, node.expression);
this.visitOptionalToken(node.semicolonToken);
}
public visitReturnStatement(node: ReturnStatementSyntax): void {
this.visitToken(node.returnKeyword);
this.visitOptionalNodeOrToken(node.expression);
visitNodeOrToken(this, node.expression);
this.visitOptionalToken(node.semicolonToken);
}
public visitSwitchStatement(node: SwitchStatementSyntax): void {
this.visitToken(node.switchKeyword);
this.visitToken(node.openParenToken);
this.visitNodeOrToken(node.expression);
visitNodeOrToken(this, node.expression);
this.visitToken(node.closeParenToken);
this.visitToken(node.openBraceToken);
this.visitList(node.switchClauses);
@@ -304,25 +276,23 @@ module TypeScript {
public visitForStatement(node: ForStatementSyntax): void {
this.visitToken(node.forKeyword);
this.visitToken(node.openParenToken);
this.visitOptionalNode(node.variableDeclaration);
this.visitOptionalNodeOrToken(node.initializer);
visitNodeOrToken(this, node.initializer);
this.visitToken(node.firstSemicolonToken);
this.visitOptionalNodeOrToken(node.condition);
visitNodeOrToken(this, node.condition);
this.visitToken(node.secondSemicolonToken);
this.visitOptionalNodeOrToken(node.incrementor);
visitNodeOrToken(this, node.incrementor);
this.visitToken(node.closeParenToken);
this.visitNodeOrToken(node.statement);
visitNodeOrToken(this, node.statement);
}
public visitForInStatement(node: ForInStatementSyntax): void {
this.visitToken(node.forKeyword);
this.visitToken(node.openParenToken);
this.visitOptionalNode(node.variableDeclaration);
this.visitOptionalNodeOrToken(node.left);
visitNodeOrToken(this, node.left);
this.visitToken(node.inKeyword);
this.visitNodeOrToken(node.expression);
visitNodeOrToken(this, node.right);
this.visitToken(node.closeParenToken);
this.visitNodeOrToken(node.statement);
visitNodeOrToken(this, node.statement);
}
public visitEmptyStatement(node: EmptyStatementSyntax): void {
@@ -331,37 +301,37 @@ module TypeScript {
public visitThrowStatement(node: ThrowStatementSyntax): void {
this.visitToken(node.throwKeyword);
this.visitNodeOrToken(node.expression);
visitNodeOrToken(this, node.expression);
this.visitOptionalToken(node.semicolonToken);
}
public visitWhileStatement(node: WhileStatementSyntax): void {
this.visitToken(node.whileKeyword);
this.visitToken(node.openParenToken);
this.visitNodeOrToken(node.condition);
visitNodeOrToken(this, node.condition);
this.visitToken(node.closeParenToken);
this.visitNodeOrToken(node.statement);
visitNodeOrToken(this, node.statement);
}
public visitTryStatement(node: TryStatementSyntax): void {
this.visitToken(node.tryKeyword);
this.visitNode(node.block);
this.visitOptionalNode(node.catchClause);
this.visitOptionalNode(node.finallyClause);
visitNodeOrToken(this, node.block);
visitNodeOrToken(this, node.catchClause);
visitNodeOrToken(this, node.finallyClause);
}
public visitLabeledStatement(node: LabeledStatementSyntax): void {
this.visitToken(node.identifier);
this.visitToken(node.colonToken);
this.visitNodeOrToken(node.statement);
visitNodeOrToken(this, node.statement);
}
public visitDoStatement(node: DoStatementSyntax): void {
this.visitToken(node.doKeyword);
this.visitNodeOrToken(node.statement);
visitNodeOrToken(this, node.statement);
this.visitToken(node.whileKeyword);
this.visitToken(node.openParenToken);
this.visitNodeOrToken(node.condition);
visitNodeOrToken(this, node.condition);
this.visitToken(node.closeParenToken);
this.visitOptionalToken(node.semicolonToken);
}
@@ -374,172 +344,180 @@ module TypeScript {
public visitWithStatement(node: WithStatementSyntax): void {
this.visitToken(node.withKeyword);
this.visitToken(node.openParenToken);
this.visitNodeOrToken(node.condition);
visitNodeOrToken(this, node.condition);
this.visitToken(node.closeParenToken);
this.visitNodeOrToken(node.statement);
visitNodeOrToken(this, node.statement);
}
public visitPrefixUnaryExpression(node: PrefixUnaryExpressionSyntax): void {
this.visitToken(node.operatorToken);
this.visitNodeOrToken(node.operand);
visitNodeOrToken(this, node.operand);
}
public visitDeleteExpression(node: DeleteExpressionSyntax): void {
this.visitToken(node.deleteKeyword);
this.visitNodeOrToken(node.expression);
visitNodeOrToken(this, node.expression);
}
public visitTypeOfExpression(node: TypeOfExpressionSyntax): void {
this.visitToken(node.typeOfKeyword);
this.visitNodeOrToken(node.expression);
visitNodeOrToken(this, node.expression);
}
public visitVoidExpression(node: VoidExpressionSyntax): void {
this.visitToken(node.voidKeyword);
this.visitNodeOrToken(node.expression);
visitNodeOrToken(this, node.expression);
}
public visitConditionalExpression(node: ConditionalExpressionSyntax): void {
this.visitNodeOrToken(node.condition);
visitNodeOrToken(this, node.condition);
this.visitToken(node.questionToken);
this.visitNodeOrToken(node.whenTrue);
visitNodeOrToken(this, node.whenTrue);
this.visitToken(node.colonToken);
this.visitNodeOrToken(node.whenFalse);
visitNodeOrToken(this, node.whenFalse);
}
public visitBinaryExpression(node: BinaryExpressionSyntax): void {
this.visitNodeOrToken(node.left);
visitNodeOrToken(this, node.left);
this.visitToken(node.operatorToken);
this.visitNodeOrToken(node.right);
visitNodeOrToken(this, node.right);
}
public visitPostfixUnaryExpression(node: PostfixUnaryExpressionSyntax): void {
this.visitNodeOrToken(node.operand);
visitNodeOrToken(this, node.operand);
this.visitToken(node.operatorToken);
}
public visitMemberAccessExpression(node: MemberAccessExpressionSyntax): void {
this.visitNodeOrToken(node.expression);
visitNodeOrToken(this, node.expression);
this.visitToken(node.dotToken);
this.visitToken(node.name);
}
public visitInvocationExpression(node: InvocationExpressionSyntax): void {
this.visitNodeOrToken(node.expression);
this.visitNode(node.argumentList);
visitNodeOrToken(this, node.expression);
visitNodeOrToken(this, node.argumentList);
}
public visitArrayLiteralExpression(node: ArrayLiteralExpressionSyntax): void {
this.visitToken(node.openBracketToken);
this.visitSeparatedList(node.expressions);
this.visitList(node.expressions);
this.visitToken(node.closeBracketToken);
}
public visitObjectLiteralExpression(node: ObjectLiteralExpressionSyntax): void {
this.visitToken(node.openBraceToken);
this.visitSeparatedList(node.propertyAssignments);
this.visitList(node.propertyAssignments);
this.visitToken(node.closeBraceToken);
}
public visitObjectCreationExpression(node: ObjectCreationExpressionSyntax): void {
this.visitToken(node.newKeyword);
this.visitNodeOrToken(node.expression);
this.visitOptionalNode(node.argumentList);
visitNodeOrToken(this, node.expression);
visitNodeOrToken(this, node.argumentList);
}
public visitParenthesizedExpression(node: ParenthesizedExpressionSyntax): void {
this.visitToken(node.openParenToken);
this.visitNodeOrToken(node.expression);
visitNodeOrToken(this, node.expression);
this.visitToken(node.closeParenToken);
}
public visitParenthesizedArrowFunctionExpression(node: ParenthesizedArrowFunctionExpressionSyntax): void {
this.visitNode(node.callSignature);
visitNodeOrToken(this, node.callSignature);
this.visitToken(node.equalsGreaterThanToken);
this.visitOptionalNode(node.block);
this.visitOptionalNodeOrToken(node.expression);
visitNodeOrToken(this, node.body);
}
public visitSimpleArrowFunctionExpression(node: SimpleArrowFunctionExpressionSyntax): void {
this.visitNode(node.parameter);
visitNodeOrToken(this, node.parameter);
this.visitToken(node.equalsGreaterThanToken);
this.visitOptionalNode(node.block);
this.visitOptionalNodeOrToken(node.expression);
visitNodeOrToken(this, node.body);
}
public visitCastExpression(node: CastExpressionSyntax): void {
this.visitToken(node.lessThanToken);
this.visitNodeOrToken(node.type);
visitNodeOrToken(this, node.type);
this.visitToken(node.greaterThanToken);
this.visitNodeOrToken(node.expression);
visitNodeOrToken(this, node.expression);
}
public visitElementAccessExpression(node: ElementAccessExpressionSyntax): void {
this.visitNodeOrToken(node.expression);
visitNodeOrToken(this, node.expression);
this.visitToken(node.openBracketToken);
this.visitNodeOrToken(node.argumentExpression);
visitNodeOrToken(this, node.argumentExpression);
this.visitToken(node.closeBracketToken);
}
public visitFunctionExpression(node: FunctionExpressionSyntax): void {
this.visitToken(node.functionKeyword);
this.visitOptionalToken(node.identifier);
this.visitNode(node.callSignature);
this.visitNode(node.block);
visitNodeOrToken(this, node.callSignature);
visitNodeOrToken(this, node.block);
}
public visitOmittedExpression(node: OmittedExpressionSyntax): void {
}
public visitTemplateExpression(node: TemplateExpressionSyntax): void {
this.visitToken(node.templateStartToken);
this.visitList(node.templateClauses);
}
public visitTemplateAccessExpression(node: TemplateAccessExpressionSyntax): void {
visitNodeOrToken(this, node.expression);
visitNodeOrToken(this, node.templateExpression);
}
public visitVariableDeclaration(node: VariableDeclarationSyntax): void {
this.visitToken(node.varKeyword);
this.visitSeparatedList(node.variableDeclarators);
this.visitList(node.variableDeclarators);
}
public visitVariableDeclarator(node: VariableDeclaratorSyntax): void {
this.visitToken(node.propertyName);
this.visitOptionalNode(node.typeAnnotation);
this.visitOptionalNode(node.equalsValueClause);
visitNodeOrToken(this, node.propertyName);
visitNodeOrToken(this, node.typeAnnotation);
visitNodeOrToken(this, node.equalsValueClause);
}
public visitArgumentList(node: ArgumentListSyntax): void {
this.visitOptionalNode(node.typeArgumentList);
visitNodeOrToken(this, node.typeArgumentList);
this.visitToken(node.openParenToken);
this.visitSeparatedList(node.arguments);
this.visitList(node.arguments);
this.visitToken(node.closeParenToken);
}
public visitParameterList(node: ParameterListSyntax): void {
this.visitToken(node.openParenToken);
this.visitSeparatedList(node.parameters);
this.visitList(node.parameters);
this.visitToken(node.closeParenToken);
}
public visitTypeArgumentList(node: TypeArgumentListSyntax): void {
this.visitToken(node.lessThanToken);
this.visitSeparatedList(node.typeArguments);
this.visitList(node.typeArguments);
this.visitToken(node.greaterThanToken);
}
public visitTypeParameterList(node: TypeParameterListSyntax): void {
this.visitToken(node.lessThanToken);
this.visitSeparatedList(node.typeParameters);
this.visitList(node.typeParameters);
this.visitToken(node.greaterThanToken);
}
public visitHeritageClause(node: HeritageClauseSyntax): void {
this.visitToken(node.extendsOrImplementsKeyword);
this.visitSeparatedList(node.typeNames);
this.visitList(node.typeNames);
}
public visitEqualsValueClause(node: EqualsValueClauseSyntax): void {
this.visitToken(node.equalsToken);
this.visitNodeOrToken(node.value);
visitNodeOrToken(this, node.value);
}
public visitCaseSwitchClause(node: CaseSwitchClauseSyntax): void {
this.visitToken(node.caseKeyword);
this.visitNodeOrToken(node.expression);
visitNodeOrToken(this, node.expression);
this.visitToken(node.colonToken);
this.visitList(node.statements);
}
@@ -552,43 +530,48 @@ module TypeScript {
public visitElseClause(node: ElseClauseSyntax): void {
this.visitToken(node.elseKeyword);
this.visitNodeOrToken(node.statement);
visitNodeOrToken(this, node.statement);
}
public visitCatchClause(node: CatchClauseSyntax): void {
this.visitToken(node.catchKeyword);
this.visitToken(node.openParenToken);
this.visitToken(node.identifier);
this.visitOptionalNode(node.typeAnnotation);
visitNodeOrToken(this, node.typeAnnotation);
this.visitToken(node.closeParenToken);
this.visitNode(node.block);
visitNodeOrToken(this, node.block);
}
public visitFinallyClause(node: FinallyClauseSyntax): void {
this.visitToken(node.finallyKeyword);
this.visitNode(node.block);
visitNodeOrToken(this, node.block);
}
public visitTemplateClause(node: TemplateClauseSyntax): void {
visitNodeOrToken(this, node.expression);
this.visitToken(node.templateMiddleOrEndToken);
}
public visitTypeParameter(node: TypeParameterSyntax): void {
this.visitToken(node.identifier);
this.visitOptionalNode(node.constraint);
visitNodeOrToken(this, node.constraint);
}
public visitConstraint(node: ConstraintSyntax): void {
this.visitToken(node.extendsKeyword);
this.visitNodeOrToken(node.typeOrExpression);
visitNodeOrToken(this, node.typeOrExpression);
}
public visitSimplePropertyAssignment(node: SimplePropertyAssignmentSyntax): void {
this.visitToken(node.propertyName);
visitNodeOrToken(this, node.propertyName);
this.visitToken(node.colonToken);
this.visitNodeOrToken(node.expression);
visitNodeOrToken(this, node.expression);
}
public visitFunctionPropertyAssignment(node: FunctionPropertyAssignmentSyntax): void {
this.visitToken(node.propertyName);
this.visitNode(node.callSignature);
this.visitNode(node.block);
visitNodeOrToken(this, node.propertyName);
visitNodeOrToken(this, node.callSignature);
visitNodeOrToken(this, node.block);
}
public visitParameter(node: ParameterSyntax): void {
@@ -596,18 +579,24 @@ module TypeScript {
this.visitList(node.modifiers);
this.visitToken(node.identifier);
this.visitOptionalToken(node.questionToken);
this.visitOptionalNode(node.typeAnnotation);
this.visitOptionalNode(node.equalsValueClause);
visitNodeOrToken(this, node.typeAnnotation);
visitNodeOrToken(this, node.equalsValueClause);
}
public visitEnumElement(node: EnumElementSyntax): void {
this.visitToken(node.propertyName);
this.visitOptionalNode(node.equalsValueClause);
visitNodeOrToken(this, node.propertyName);
visitNodeOrToken(this, node.equalsValueClause);
}
public visitTypeAnnotation(node: TypeAnnotationSyntax): void {
this.visitToken(node.colonToken);
this.visitNodeOrToken(node.type);
visitNodeOrToken(this, node.type);
}
public visitComputedPropertyName(node: ComputedPropertyNameSyntax): void {
this.visitToken(node.openBracketToken);
visitNodeOrToken(this, node.expression);
this.visitToken(node.closeBracketToken);
}
public visitExternalModuleReference(node: ExternalModuleReferenceSyntax): void {
@@ -618,7 +607,7 @@ module TypeScript {
}
public visitModuleNameModuleReference(node: ModuleNameModuleReferenceSyntax): void {
this.visitNodeOrToken(node.moduleName);
visitNodeOrToken(this, node.moduleName);
}
}
}
+18 -52
View File
@@ -1,18 +1,18 @@
module TypeScript {
function assertParent(parent: ISyntaxElement, child: ISyntaxElement) {
if (child && !TypeScript.isShared(child)) {
if (child) {
return Debug.assert(parent === child.parent);
}
}
export function nodeStructuralEquals(node1: TypeScript.ISyntaxNode, node2: TypeScript.ISyntaxNode, checkParents: boolean, text1: ISimpleText, text2: ISimpleText): boolean {
if (node1 === node2) { return true; }
if (node1 === null || node2 === null) { return false; }
if (!node1 || !node2) { return false; }
Debug.assert(node1.kind() === TypeScript.SyntaxKind.SourceUnit || node1.parent);
Debug.assert(node2.kind() === TypeScript.SyntaxKind.SourceUnit || node2.parent);
Debug.assert(node1.kind === TypeScript.SyntaxKind.SourceUnit || node1.parent);
Debug.assert(node2.kind === TypeScript.SyntaxKind.SourceUnit || node2.parent);
if (node1.kind() !== node2.kind()) { return false; }
if (node1.kind !== node2.kind) { return false; }
if (childCount(node1) !== childCount(node2)) { return false; }
for (var i = 0, n = childCount(node1); i < n; i++) {
@@ -37,12 +37,12 @@ module TypeScript {
return true;
}
if (node1 === null || node2 === null) {
if (!node1 || !node2) {
return false;
}
Debug.assert(node1.kind() === TypeScript.SyntaxKind.SourceUnit || node1.parent);
Debug.assert(node2.kind() === TypeScript.SyntaxKind.SourceUnit || node2.parent);
Debug.assert(node1.kind === TypeScript.SyntaxKind.SourceUnit || node1.parent);
Debug.assert(node2.kind === TypeScript.SyntaxKind.SourceUnit || node2.parent);
if (TypeScript.isToken(node1)) {
return TypeScript.isToken(node2) ? tokenStructuralEquals(<TypeScript.ISyntaxToken>node1, <TypeScript.ISyntaxToken>node2, text1, text2) : false;
@@ -56,23 +56,21 @@ module TypeScript {
return true;
}
if (token1 === null || token2 === null) {
if (!token1 || !token2) {
return false;
}
Debug.assert(token1.parent);
Debug.assert(token2.parent);
return token1.kind() === token2.kind() &&
return token1.kind === token2.kind &&
TypeScript.width(token1) === TypeScript.width(token2) &&
token1.fullWidth() === token2.fullWidth() &&
token1.fullStart() === token2.fullStart() &&
TypeScript.fullEnd(token1) === TypeScript.fullEnd(token2) &&
TypeScript.start(token1, text1) === TypeScript.start(token2, text2) &&
TypeScript.end(token1, text1) === TypeScript.end(token2, text2) &&
token1.text() === token2.text() &&
triviaListStructuralEquals(token1.leadingTrivia(text1), token2.leadingTrivia(text2)) &&
triviaListStructuralEquals(token1.trailingTrivia(text1), token2.trailingTrivia(text2));
triviaListStructuralEquals(token1.leadingTrivia(text1), token2.leadingTrivia(text2));
}
export function triviaListStructuralEquals(triviaList1: TypeScript.ISyntaxTriviaList, triviaList2: TypeScript.ISyntaxTriviaList): boolean {
@@ -102,8 +100,8 @@ module TypeScript {
}
function listStructuralEquals<T extends TypeScript.ISyntaxNodeOrToken>(list1: T[], list2: T[], checkParents: boolean, text1: ISimpleText, text2: ISimpleText): boolean {
Debug.assert(TypeScript.isShared(list1) || list1.parent);
Debug.assert(TypeScript.isShared(list2) || list2.parent);
Debug.assert(list1.parent);
Debug.assert(list2.parent);
if (childCount(list1) !== childCount(list2)) {
return false;
@@ -118,32 +116,7 @@ module TypeScript {
assertParent(list2, child2);
}
if (!nodeOrTokenStructuralEquals(child1, child2, checkParents, text1, text2)) {
return false;
}
}
return true;
}
function separatedListStructuralEquals<T extends TypeScript.ISyntaxNodeOrToken>(list1: T[], list2: T[], checkParents: boolean, text1: ISimpleText, text2: ISimpleText): boolean {
Debug.assert(TypeScript.isShared(list1) || list1.parent);
Debug.assert(TypeScript.isShared(list2) || list2.parent);
if (childCount(list1) !== childCount(list2)) {
return false;
}
for (var i = 0, n = childCount(list1); i < n; i++) {
var element1 = childAt(list1, i);
var element2 = childAt(list2, i);
if (checkParents) {
assertParent(list1, element1);
assertParent(list2, element2);
}
if (!nodeOrTokenStructuralEquals(element1, element2, checkParents, text1, text2)) {
if (!elementStructuralEquals(child1, child2, checkParents, text1, text2)) {
return false;
}
}
@@ -156,14 +129,14 @@ module TypeScript {
return true;
}
if (element1 === null || element2 === null) {
if (!element1 || !element2) {
return false;
}
Debug.assert(element1.kind() === SyntaxKind.SourceUnit || element1.parent);
Debug.assert(element2.kind() === SyntaxKind.SourceUnit || element2.parent);
Debug.assert(element1.kind === SyntaxKind.SourceUnit || element1.parent);
Debug.assert(element2.kind === SyntaxKind.SourceUnit || element2.parent);
if (element2.kind() !== element2.kind()) {
if (element2.kind !== element2.kind) {
return false;
}
@@ -175,10 +148,6 @@ module TypeScript {
return false;
}
if (TypeScript.end(element1) !== TypeScript.end(element2)) {
return false;
}
if (TypeScript.fullEnd(element1) !== TypeScript.fullEnd(element2)) {
return false;
}
@@ -192,9 +161,6 @@ module TypeScript {
else if (TypeScript.isList(element1)) {
return listStructuralEquals(<TypeScript.ISyntaxNodeOrToken[]>element1, <TypeScript.ISyntaxNodeOrToken[]>element2, checkParents, text1, text2);
}
else if (TypeScript.isSeparatedList(element1)) {
return separatedListStructuralEquals(<TypeScript.ISyntaxNodeOrToken[]>element1, <TypeScript.ISyntaxNodeOrToken[]>element2, checkParents, text1, text2);
}
throw TypeScript.Errors.invalidOperation();
}
@@ -0,0 +1,4 @@
var fixedWidthArray = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 4, 5, 8, 8, 7, 6, 2, 4, 5, 7, 3, 8, 2, 2, 10, 3, 4, 6, 6, 4, 5, 4, 3, 6, 3, 4, 5, 4, 5, 5, 4, 6, 7, 6, 5, 10, 9, 3, 7, 7, 9, 6, 6, 5, 3, 7, 11, 7, 3, 6, 7, 6, 3, 6, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 1, 1, 1, 1, 2, 2, 2, 2, 3, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 2, 2, 2, 1, 2];
function fixedWidthTokenLength(kind: SyntaxKind) {
return fixedWidthArray[kind];
}
+1
View File
@@ -104,6 +104,7 @@ module TypeScript {
asterisk = 42, // *
at = 64, // @
backslash = 92, // \
backtick = 96, // `
bar = 124, // |
caret = 94, // ^
closeBrace = 125, // }
+1 -1
View File
@@ -32,7 +32,7 @@ module TypeScript {
export module ScriptSnapshot {
class StringScriptSnapshot implements IScriptSnapshot {
private _lineStartPositions: number[] = null;
private _lineStartPositions: number[] = undefined;
constructor(private text: string) {
}
+7 -4
View File
@@ -2,7 +2,7 @@
module TypeScript.SimpleText {
class SimpleStringText implements ISimpleText {
private _lineMap: LineMap = null;
private _lineMap: LineMap = undefined;
constructor(private value: string) {
}
@@ -12,7 +12,10 @@ module TypeScript.SimpleText {
}
public substr(start: number, length: number): string {
return this.value.substr(start, length);
var val = this.value;
return start === 0 && length == val.length
? val
: val.substr(start, length);
}
public charCodeAt(index: number): number {
@@ -30,7 +33,7 @@ module TypeScript.SimpleText {
// Class which wraps a host IScriptSnapshot and exposes an ISimpleText for newer compiler code.
class SimpleScriptSnapshotText implements ISimpleText {
private _lineMap: LineMap = null;
private _lineMap: LineMap = undefined;
constructor(public scriptSnapshot: IScriptSnapshot) {
}
@@ -48,7 +51,7 @@ module TypeScript.SimpleText {
}
public lineMap(): LineMap {
if (this._lineMap === null) {
if (!this._lineMap) {
this._lineMap = new LineMap(() => this.scriptSnapshot.getLineStartPositions(), this.length());
}
+4 -4
View File
@@ -79,7 +79,7 @@ module TypeScript {
}
/**
* Returns the overlap with the given span, or null if there is no overlap.
* Returns the overlap with the given span, or undefined if there is no overlap.
* @param span The span to check.
*/
public overlap(span: TextSpan): TextSpan {
@@ -90,7 +90,7 @@ module TypeScript {
return TextSpan.fromBounds(overlapStart, overlapEnd);
}
return null;
return undefined;
}
/**
@@ -119,7 +119,7 @@ module TypeScript {
}
/**
* Returns the intersection with the given span, or null if there is no intersection.
* Returns the intersection with the given span, or undefined if there is no intersection.
* @param span The span to check.
*/
public intersection(span: TextSpan): TextSpan {
@@ -130,7 +130,7 @@ module TypeScript {
return TextSpan.fromBounds(intersectStart, intersectEnd);
}
return null;
return undefined;
}
/**
+6 -3
View File
@@ -197,7 +197,7 @@ module ts {
}
}
Debug.assert(startNode || n.kind === SyntaxKind.SourceFile);
Debug.assert(startNode !== undefined || n.kind === SyntaxKind.SourceFile);
// Here we know that none of child token nodes embrace the position,
// the only known case is when position is at the end of the file.
@@ -224,7 +224,10 @@ module ts {
return nodeHasTokens((<ExpressionStatement>n).expression);
}
if (n.kind === SyntaxKind.EndOfFileToken || n.kind === SyntaxKind.OmittedExpression || n.kind === SyntaxKind.Missing) {
if (n.kind === SyntaxKind.EndOfFileToken ||
n.kind === SyntaxKind.OmittedExpression ||
n.kind === SyntaxKind.Missing ||
n.kind === SyntaxKind.Unknown) {
return false;
}
@@ -238,7 +241,7 @@ module ts {
}
if (isAnyFunction(node) || node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.InterfaceDeclaration) {
return (<FunctionDeclaration>node).typeParameters;
return (<FunctionLikeDeclaration>node).typeParameters;
}
return undefined;
@@ -6,10 +6,10 @@ tests/cases/compiler/accessors_spec_section-4.5_error-cases.ts(8,16): error TS10
tests/cases/compiler/accessors_spec_section-4.5_error-cases.ts(9,16): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
tests/cases/compiler/accessors_spec_section-4.5_error-cases.ts(11,16): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
tests/cases/compiler/accessors_spec_section-4.5_error-cases.ts(12,16): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
tests/cases/compiler/accessors_spec_section-4.5_error-cases.ts(3,55): error TS2323: Type 'string' is not assignable to type 'number'.
tests/cases/compiler/accessors_spec_section-4.5_error-cases.ts(5,54): error TS2323: Type 'string' is not assignable to type 'number'.
tests/cases/compiler/accessors_spec_section-4.5_error-cases.ts(9,52): error TS2323: Type 'number' is not assignable to type 'string'.
tests/cases/compiler/accessors_spec_section-4.5_error-cases.ts(11,51): error TS2323: Type 'number' is not assignable to type 'string'.
tests/cases/compiler/accessors_spec_section-4.5_error-cases.ts(3,55): error TS2322: Type 'string' is not assignable to type 'number'.
tests/cases/compiler/accessors_spec_section-4.5_error-cases.ts(5,54): error TS2322: Type 'string' is not assignable to type 'number'.
tests/cases/compiler/accessors_spec_section-4.5_error-cases.ts(9,52): error TS2322: Type 'number' is not assignable to type 'string'.
tests/cases/compiler/accessors_spec_section-4.5_error-cases.ts(11,51): error TS2322: Type 'number' is not assignable to type 'string'.
==== tests/cases/compiler/accessors_spec_section-4.5_error-cases.ts (12 errors) ====
@@ -21,13 +21,13 @@ tests/cases/compiler/accessors_spec_section-4.5_error-cases.ts(11,51): error TS2
~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
~~
!!! error TS2323: Type 'string' is not assignable to type 'number'.
!!! error TS2322: Type 'string' is not assignable to type 'number'.
public get AnnotatedSetter_SetterLast() { return ""; }
~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
~~
!!! error TS2323: Type 'string' is not assignable to type 'number'.
!!! error TS2322: Type 'string' is not assignable to type 'number'.
public set AnnotatedSetter_SetterLast(a: number) { }
~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
@@ -39,13 +39,13 @@ tests/cases/compiler/accessors_spec_section-4.5_error-cases.ts(11,51): error TS2
~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
~~~~
!!! error TS2323: Type 'number' is not assignable to type 'string'.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
public set AnnotatedGetter_GetterLast(aStr) { aStr = 0; }
~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
~~~~
!!! error TS2323: Type 'number' is not assignable to type 'string'.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
public get AnnotatedGetter_GetterLast(): string { return ""; }
~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
@@ -50,12 +50,12 @@ var r3 = null + b;
var r4 = null + 1;
var r5 = null + c;
var r6 = null + 0 /* a */;
var r7 = null + E['a'];
var r7 = null + 0 /* 'a' */;
var r8 = b + null;
var r9 = 1 + null;
var r10 = c + null;
var r11 = 0 /* a */ + null;
var r12 = E['a'] + null;
var r12 = 0 /* 'a' */ + null;
// null + string
var r13 = null + d;
var r14 = null + '';
@@ -29,4 +29,4 @@ var r4 = b + b;
var r5 = 0 + a;
var r6 = 0 /* a */ + 0;
var r7 = 0 /* a */ + 1 /* b */;
var r8 = E['a'] + E['b'];
var r8 = 0 /* 'a' */ + 1 /* 'b' */;
@@ -50,12 +50,12 @@ var r3 = undefined + b;
var r4 = undefined + 1;
var r5 = undefined + c;
var r6 = undefined + 0 /* a */;
var r7 = undefined + E['a'];
var r7 = undefined + 0 /* 'a' */;
var r8 = b + undefined;
var r9 = 1 + undefined;
var r10 = c + undefined;
var r11 = 0 /* a */ + undefined;
var r12 = E['a'] + undefined;
var r12 = 0 /* 'a' */ + undefined;
// undefined + string
var r13 = undefined + d;
var r14 = undefined + '';
@@ -1,6 +1,6 @@
tests/cases/compiler/aliasAssignments_1.ts(3,1): error TS2323: Type 'number' is not assignable to type 'typeof "tests/cases/compiler/aliasAssignments_moduleA"'.
tests/cases/compiler/aliasAssignments_1.ts(3,1): error TS2322: Type 'number' is not assignable to type 'typeof "tests/cases/compiler/aliasAssignments_moduleA"'.
Property 'someClass' is missing in type 'Number'.
tests/cases/compiler/aliasAssignments_1.ts(5,1): error TS2323: Type 'typeof "tests/cases/compiler/aliasAssignments_moduleA"' is not assignable to type 'number'.
tests/cases/compiler/aliasAssignments_1.ts(5,1): error TS2322: Type 'typeof "tests/cases/compiler/aliasAssignments_moduleA"' is not assignable to type 'number'.
==== tests/cases/compiler/aliasAssignments_1.ts (2 errors) ====
@@ -8,12 +8,12 @@ tests/cases/compiler/aliasAssignments_1.ts(5,1): error TS2323: Type 'typeof "tes
var x = moduleA;
x = 1; // Should be error
~
!!! error TS2323: Type 'number' is not assignable to type 'typeof "tests/cases/compiler/aliasAssignments_moduleA"'.
!!! error TS2323: Property 'someClass' is missing in type 'Number'.
!!! error TS2322: Type 'number' is not assignable to type 'typeof "tests/cases/compiler/aliasAssignments_moduleA"'.
!!! error TS2322: Property 'someClass' is missing in type 'Number'.
var y = 1;
y = moduleA; // should be error
~
!!! error TS2323: Type 'typeof "tests/cases/compiler/aliasAssignments_moduleA"' is not assignable to type 'number'.
!!! error TS2322: Type 'typeof "tests/cases/compiler/aliasAssignments_moduleA"' is not assignable to type 'number'.
==== tests/cases/compiler/aliasAssignments_moduleA.ts (0 errors) ====
export class someClass {
@@ -1,5 +1,5 @@
tests/cases/compiler/ambiguousOverload.ts(5,5): error TS2323: Type 'number' is not assignable to type 'string'.
tests/cases/compiler/ambiguousOverload.ts(11,5): error TS2323: Type 'string' is not assignable to type 'number'.
tests/cases/compiler/ambiguousOverload.ts(5,5): error TS2322: Type 'number' is not assignable to type 'string'.
tests/cases/compiler/ambiguousOverload.ts(11,5): error TS2322: Type 'string' is not assignable to type 'number'.
==== tests/cases/compiler/ambiguousOverload.ts (2 errors) ====
@@ -9,7 +9,7 @@ tests/cases/compiler/ambiguousOverload.ts(11,5): error TS2323: Type 'string' is
var x: number = foof("s", null);
var y: string = foof("s", null);
~
!!! error TS2323: Type 'number' is not assignable to type 'string'.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
function foof2(bar: string, x): string;
function foof2(bar: string, y): number;
@@ -17,4 +17,4 @@ tests/cases/compiler/ambiguousOverload.ts(11,5): error TS2323: Type 'string' is
var x2: string = foof2("s", null);
var y2: number = foof2("s", null);
~~
!!! error TS2323: Type 'string' is not assignable to type 'number'.
!!! error TS2322: Type 'string' is not assignable to type 'number'.
@@ -1,4 +1,4 @@
tests/cases/compiler/argumentsBindsToFunctionScopeArgumentList.ts(3,5): error TS2323: Type 'number' is not assignable to type 'IArguments'.
tests/cases/compiler/argumentsBindsToFunctionScopeArgumentList.ts(3,5): error TS2322: Type 'number' is not assignable to type 'IArguments'.
Property 'length' is missing in type 'Number'.
@@ -7,6 +7,6 @@ tests/cases/compiler/argumentsBindsToFunctionScopeArgumentList.ts(3,5): error TS
function foo(a) {
arguments = 10; /// This shouldnt be of type number and result in error.
~~~~~~~~~
!!! error TS2323: Type 'number' is not assignable to type 'IArguments'.
!!! error TS2323: Property 'length' is missing in type 'Number'.
!!! error TS2322: Type 'number' is not assignable to type 'IArguments'.
!!! error TS2322: Property 'length' is missing in type 'Number'.
}
@@ -1,49 +1,46 @@
tests/cases/compiler/arrayAssignmentTest1.ts(46,5): error TS2323: Type 'undefined[]' is not assignable to type 'I1'.
tests/cases/compiler/arrayAssignmentTest1.ts(46,5): error TS2322: Type 'undefined[]' is not assignable to type 'I1'.
Property 'IM1' is missing in type 'undefined[]'.
tests/cases/compiler/arrayAssignmentTest1.ts(47,5): error TS2323: Type 'undefined[]' is not assignable to type 'C1'.
tests/cases/compiler/arrayAssignmentTest1.ts(47,5): error TS2322: Type 'undefined[]' is not assignable to type 'C1'.
Property 'IM1' is missing in type 'undefined[]'.
tests/cases/compiler/arrayAssignmentTest1.ts(48,5): error TS2323: Type 'undefined[]' is not assignable to type 'C2'.
tests/cases/compiler/arrayAssignmentTest1.ts(48,5): error TS2322: Type 'undefined[]' is not assignable to type 'C2'.
Property 'C2M1' is missing in type 'undefined[]'.
tests/cases/compiler/arrayAssignmentTest1.ts(49,5): error TS2323: Type 'undefined[]' is not assignable to type 'C3'.
tests/cases/compiler/arrayAssignmentTest1.ts(49,5): error TS2322: Type 'undefined[]' is not assignable to type 'C3'.
Property 'CM3M1' is missing in type 'undefined[]'.
tests/cases/compiler/arrayAssignmentTest1.ts(60,1): error TS2323: Type 'C3[]' is not assignable to type 'I1[]'.
tests/cases/compiler/arrayAssignmentTest1.ts(60,1): error TS2322: Type 'C3[]' is not assignable to type 'I1[]'.
Type 'C3' is not assignable to type 'I1'.
Property 'IM1' is missing in type 'C3'.
tests/cases/compiler/arrayAssignmentTest1.ts(64,1): error TS2323: Type 'I1[]' is not assignable to type 'C1[]'.
tests/cases/compiler/arrayAssignmentTest1.ts(64,1): error TS2322: Type 'I1[]' is not assignable to type 'C1[]'.
Type 'I1' is not assignable to type 'C1'.
Property 'C1M1' is missing in type 'I1'.
tests/cases/compiler/arrayAssignmentTest1.ts(65,1): error TS2323: Type 'C3[]' is not assignable to type 'C1[]'.
tests/cases/compiler/arrayAssignmentTest1.ts(65,1): error TS2322: Type 'C3[]' is not assignable to type 'C1[]'.
Type 'C3' is not assignable to type 'C1'.
Property 'IM1' is missing in type 'C3'.
tests/cases/compiler/arrayAssignmentTest1.ts(68,1): error TS2323: Type 'C1[]' is not assignable to type 'C2[]'.
tests/cases/compiler/arrayAssignmentTest1.ts(68,1): error TS2322: Type 'C1[]' is not assignable to type 'C2[]'.
Type 'C1' is not assignable to type 'C2'.
Property 'C2M1' is missing in type 'C1'.
tests/cases/compiler/arrayAssignmentTest1.ts(69,1): error TS2323: Type 'I1[]' is not assignable to type 'C2[]'.
tests/cases/compiler/arrayAssignmentTest1.ts(69,1): error TS2322: Type 'I1[]' is not assignable to type 'C2[]'.
Type 'I1' is not assignable to type 'C2'.
Property 'C2M1' is missing in type 'I1'.
tests/cases/compiler/arrayAssignmentTest1.ts(70,1): error TS2323: Type 'C3[]' is not assignable to type 'C2[]'.
tests/cases/compiler/arrayAssignmentTest1.ts(70,1): error TS2322: Type 'C3[]' is not assignable to type 'C2[]'.
Type 'C3' is not assignable to type 'C2'.
Property 'C2M1' is missing in type 'C3'.
tests/cases/compiler/arrayAssignmentTest1.ts(75,1): error TS2323: Type 'C2[]' is not assignable to type 'C3[]'.
tests/cases/compiler/arrayAssignmentTest1.ts(75,1): error TS2322: Type 'C2[]' is not assignable to type 'C3[]'.
Type 'C2' is not assignable to type 'C3'.
Property 'CM3M1' is missing in type 'C2'.
tests/cases/compiler/arrayAssignmentTest1.ts(76,1): error TS2323: Type 'C1[]' is not assignable to type 'C3[]'.
tests/cases/compiler/arrayAssignmentTest1.ts(76,1): error TS2322: Type 'C1[]' is not assignable to type 'C3[]'.
Type 'C1' is not assignable to type 'C3'.
Property 'CM3M1' is missing in type 'C1'.
tests/cases/compiler/arrayAssignmentTest1.ts(77,1): error TS2323: Type 'I1[]' is not assignable to type 'C3[]'.
tests/cases/compiler/arrayAssignmentTest1.ts(77,1): error TS2322: Type 'I1[]' is not assignable to type 'C3[]'.
Type 'I1' is not assignable to type 'C3'.
Property 'CM3M1' is missing in type 'I1'.
tests/cases/compiler/arrayAssignmentTest1.ts(79,1): error TS2323: Type '() => C1' is not assignable to type 'any[]'.
tests/cases/compiler/arrayAssignmentTest1.ts(79,1): error TS2322: Type '() => C1' is not assignable to type 'any[]'.
Property 'push' is missing in type '() => C1'.
tests/cases/compiler/arrayAssignmentTest1.ts(80,1): error TS2323: Type '{ one: number; }' is not assignable to type 'any[]'.
tests/cases/compiler/arrayAssignmentTest1.ts(80,1): error TS2322: Type '{ one: number; }' is not assignable to type 'any[]'.
Property 'length' is missing in type '{ one: number; }'.
tests/cases/compiler/arrayAssignmentTest1.ts(82,1): error TS2323: Type 'C1' is not assignable to type 'any[]'.
tests/cases/compiler/arrayAssignmentTest1.ts(82,1): error TS2322: Type 'C1' is not assignable to type 'any[]'.
Property 'length' is missing in type 'C1'.
tests/cases/compiler/arrayAssignmentTest1.ts(83,1): error TS2323: Type 'C2' is not assignable to type 'any[]'.
tests/cases/compiler/arrayAssignmentTest1.ts(83,1): error TS2322: Type 'C2' is not assignable to type 'any[]'.
Property 'length' is missing in type 'C2'.
tests/cases/compiler/arrayAssignmentTest1.ts(84,1): error TS2323: Type 'C3' is not assignable to type 'any[]'.
tests/cases/compiler/arrayAssignmentTest1.ts(84,1): error TS2322: Type 'C3' is not assignable to type 'any[]'.
Property 'length' is missing in type 'C3'.
tests/cases/compiler/arrayAssignmentTest1.ts(85,1): error TS2323: Type 'I1' is not assignable to type 'any[]'.
tests/cases/compiler/arrayAssignmentTest1.ts(85,1): error TS2322: Type 'I1' is not assignable to type 'any[]'.
Property 'length' is missing in type 'I1'.
@@ -95,20 +92,20 @@ tests/cases/compiler/arrayAssignmentTest1.ts(85,1): error TS2323: Type 'I1' is n
var i1_error: I1 = []; // should be an error - is
~~~~~~~~
!!! error TS2323: Type 'undefined[]' is not assignable to type 'I1'.
!!! error TS2323: Property 'IM1' is missing in type 'undefined[]'.
!!! error TS2322: Type 'undefined[]' is not assignable to type 'I1'.
!!! error TS2322: Property 'IM1' is missing in type 'undefined[]'.
var c1_error: C1 = []; // should be an error - is
~~~~~~~~
!!! error TS2323: Type 'undefined[]' is not assignable to type 'C1'.
!!! error TS2323: Property 'IM1' is missing in type 'undefined[]'.
!!! error TS2322: Type 'undefined[]' is not assignable to type 'C1'.
!!! error TS2322: Property 'IM1' is missing in type 'undefined[]'.
var c2_error: C2 = []; // should be an error - is
~~~~~~~~
!!! error TS2323: Type 'undefined[]' is not assignable to type 'C2'.
!!! error TS2323: Property 'C2M1' is missing in type 'undefined[]'.
!!! error TS2322: Type 'undefined[]' is not assignable to type 'C2'.
!!! error TS2322: Property 'C2M1' is missing in type 'undefined[]'.
var c3_error: C3 = []; // should be an error - is
~~~~~~~~
!!! error TS2323: Type 'undefined[]' is not assignable to type 'C3'.
!!! error TS2323: Property 'CM3M1' is missing in type 'undefined[]'.
!!! error TS2322: Type 'undefined[]' is not assignable to type 'C3'.
!!! error TS2322: Property 'CM3M1' is missing in type 'undefined[]'.
arr_any = arr_i1; // should be ok - is
@@ -121,81 +118,78 @@ tests/cases/compiler/arrayAssignmentTest1.ts(85,1): error TS2323: Type 'I1' is n
arr_i1 = arr_c2; // should be ok - subtype relationship - is
arr_i1 = arr_c3; // should be an error - is
~~~~~~
!!! error TS2323: Type 'C3[]' is not assignable to type 'I1[]'.
!!! error TS2323: Type 'C3' is not assignable to type 'I1'.
!!! error TS2323: Property 'IM1' is missing in type 'C3'.
!!! error TS2322: Type 'C3[]' is not assignable to type 'I1[]'.
!!! error TS2322: Type 'C3' is not assignable to type 'I1'.
!!! error TS2322: Property 'IM1' is missing in type 'C3'.
arr_c1 = arr_c1; // should be ok - subtype relationship - is
arr_c1 = arr_c2; // should be ok - subtype relationship - is
arr_c1 = arr_i1; // should be an error - is
~~~~~~
!!! error TS2323: Type 'I1[]' is not assignable to type 'C1[]'.
!!! error TS2323: Type 'I1' is not assignable to type 'C1'.
!!! error TS2323: Property 'C1M1' is missing in type 'I1'.
!!! error TS2322: Type 'I1[]' is not assignable to type 'C1[]'.
!!! error TS2322: Type 'I1' is not assignable to type 'C1'.
!!! error TS2322: Property 'C1M1' is missing in type 'I1'.
arr_c1 = arr_c3; // should be an error - is
~~~~~~
!!! error TS2323: Type 'C3[]' is not assignable to type 'C1[]'.
!!! error TS2323: Type 'C3' is not assignable to type 'C1'.
!!! error TS2323: Property 'IM1' is missing in type 'C3'.
!!! error TS2322: Type 'C3[]' is not assignable to type 'C1[]'.
!!! error TS2322: Type 'C3' is not assignable to type 'C1'.
!!! error TS2322: Property 'IM1' is missing in type 'C3'.
arr_c2 = arr_c2; // should be ok - subtype relationship - is
arr_c2 = arr_c1; // should be an error - subtype relationship - is
~~~~~~
!!! error TS2323: Type 'C1[]' is not assignable to type 'C2[]'.
!!! error TS2323: Type 'C1' is not assignable to type 'C2'.
!!! error TS2323: Property 'C2M1' is missing in type 'C1'.
!!! error TS2322: Type 'C1[]' is not assignable to type 'C2[]'.
!!! error TS2322: Type 'C1' is not assignable to type 'C2'.
!!! error TS2322: Property 'C2M1' is missing in type 'C1'.
arr_c2 = arr_i1; // should be an error - subtype relationship - is
~~~~~~
!!! error TS2323: Type 'I1[]' is not assignable to type 'C2[]'.
!!! error TS2323: Type 'I1' is not assignable to type 'C2'.
!!! error TS2323: Property 'C2M1' is missing in type 'I1'.
!!! error TS2322: Type 'I1[]' is not assignable to type 'C2[]'.
!!! error TS2322: Type 'I1' is not assignable to type 'C2'.
!!! error TS2322: Property 'C2M1' is missing in type 'I1'.
arr_c2 = arr_c3; // should be an error - is
~~~~~~
!!! error TS2323: Type 'C3[]' is not assignable to type 'C2[]'.
!!! error TS2323: Type 'C3' is not assignable to type 'C2'.
!!! error TS2323: Property 'C2M1' is missing in type 'C3'.
!!! error TS2322: Type 'C3[]' is not assignable to type 'C2[]'.
!!! error TS2322: Type 'C3' is not assignable to type 'C2'.
!!! error TS2322: Property 'C2M1' is missing in type 'C3'.
// "clean up bug" occurs at this point
// if you move these three expressions to another file, they raise an error
// something to do with state from the above propagating forward?
arr_c3 = arr_c2_2; // should be an error - is
~~~~~~
!!! error TS2323: Type 'C2[]' is not assignable to type 'C3[]'.
!!! error TS2323: Type 'C2' is not assignable to type 'C3'.
!!! error TS2323: Property 'CM3M1' is missing in type 'C2'.
!!! error TS2322: Type 'C2[]' is not assignable to type 'C3[]'.
!!! error TS2322: Type 'C2' is not assignable to type 'C3'.
arr_c3 = arr_c1_2; // should be an error - is
~~~~~~
!!! error TS2323: Type 'C1[]' is not assignable to type 'C3[]'.
!!! error TS2323: Type 'C1' is not assignable to type 'C3'.
!!! error TS2323: Property 'CM3M1' is missing in type 'C1'.
!!! error TS2322: Type 'C1[]' is not assignable to type 'C3[]'.
!!! error TS2322: Type 'C1' is not assignable to type 'C3'.
arr_c3 = arr_i1_2; // should be an error - is
~~~~~~
!!! error TS2323: Type 'I1[]' is not assignable to type 'C3[]'.
!!! error TS2323: Type 'I1' is not assignable to type 'C3'.
!!! error TS2323: Property 'CM3M1' is missing in type 'I1'.
!!! error TS2322: Type 'I1[]' is not assignable to type 'C3[]'.
!!! error TS2322: Type 'I1' is not assignable to type 'C3'.
arr_any = f1; // should be an error - is
~~~~~~~
!!! error TS2323: Type '() => C1' is not assignable to type 'any[]'.
!!! error TS2323: Property 'push' is missing in type '() => C1'.
!!! error TS2322: Type '() => C1' is not assignable to type 'any[]'.
!!! error TS2322: Property 'push' is missing in type '() => C1'.
arr_any = o1; // should be an error - is
~~~~~~~
!!! error TS2323: Type '{ one: number; }' is not assignable to type 'any[]'.
!!! error TS2323: Property 'length' is missing in type '{ one: number; }'.
!!! error TS2322: Type '{ one: number; }' is not assignable to type 'any[]'.
!!! error TS2322: Property 'length' is missing in type '{ one: number; }'.
arr_any = a1; // should be ok - is
arr_any = c1; // should be an error - is
~~~~~~~
!!! error TS2323: Type 'C1' is not assignable to type 'any[]'.
!!! error TS2323: Property 'length' is missing in type 'C1'.
!!! error TS2322: Type 'C1' is not assignable to type 'any[]'.
!!! error TS2322: Property 'length' is missing in type 'C1'.
arr_any = c2; // should be an error - is
~~~~~~~
!!! error TS2323: Type 'C2' is not assignable to type 'any[]'.
!!! error TS2323: Property 'length' is missing in type 'C2'.
!!! error TS2322: Type 'C2' is not assignable to type 'any[]'.
!!! error TS2322: Property 'length' is missing in type 'C2'.
arr_any = c3; // should be an error - is
~~~~~~~
!!! error TS2323: Type 'C3' is not assignable to type 'any[]'.
!!! error TS2323: Property 'length' is missing in type 'C3'.
!!! error TS2322: Type 'C3' is not assignable to type 'any[]'.
!!! error TS2322: Property 'length' is missing in type 'C3'.
arr_any = i1; // should be an error - is
~~~~~~~
!!! error TS2323: Type 'I1' is not assignable to type 'any[]'.
!!! error TS2323: Property 'length' is missing in type 'I1'.
!!! error TS2322: Type 'I1' is not assignable to type 'any[]'.
!!! error TS2322: Property 'length' is missing in type 'I1'.

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