diff --git a/Jakefile b/Jakefile index 16330305b6a..11dd7c048df 100644 --- a/Jakefile +++ b/Jakefile @@ -35,6 +35,7 @@ var compilerSources = [ "types.ts", "scanner.ts", "parser.ts", + "utilities.ts", "binder.ts", "checker.ts", "emitter.ts", @@ -47,26 +48,53 @@ var compilerSources = [ var servicesSources = [ "core.ts", + "sys.ts", "types.ts", "scanner.ts", "parser.ts", + "utilities.ts", "binder.ts", "checker.ts", - "emitter.ts" + "emitter.ts", + "diagnosticInformationMap.generated.ts" ].map(function (f) { return path.join(compilerDirectory, f); }).concat([ "breakpoints.ts", + "navigationBar.ts", + "outliningElementsCollector.ts", "services.ts", "shims.ts", "signatureHelp.ts", "utilities.ts", - "navigationBar.ts", - "outliningElementsCollector.ts" + "formatting/formatting.ts", + "formatting/formattingContext.ts", + "formatting/formattingRequestKind.ts", + "formatting/formattingScanner.ts", + "formatting/references.ts", + "formatting/rule.ts", + "formatting/ruleAction.ts", + "formatting/ruleDescriptor.ts", + "formatting/ruleFlag.ts", + "formatting/ruleOperation.ts", + "formatting/ruleOperationContext.ts", + "formatting/rules.ts", + "formatting/rulesMap.ts", + "formatting/rulesProvider.ts", + "formatting/smartIndenter.ts", + "formatting/tokenRange.ts" ].map(function (f) { return path.join(servicesDirectory, f); })); +var definitionsRoots = [ + "compiler/types.d.ts", + "compiler/scanner.d.ts", + "compiler/parser.d.ts", + "compiler/checker.d.ts", + "services/services.d.ts", +]; + var harnessSources = [ "harness.ts", "sourceMapRecorder.ts", @@ -84,6 +112,7 @@ var harnessSources = [ ].map(function (f) { return path.join(harnessDirectory, f); }).concat([ + "incrementalParser.ts", "services/colorization.ts", "services/documentRegistry.ts", "services/preProcessFile.ts" @@ -148,25 +177,48 @@ var compilerFilename = "tsc.js"; * @param prefixes: a list of files to prepend to the target file * @param useBuiltCompiler: true to use the built compiler, false to use the LKG * @param noOutFile: true to compile without using --out + * @param generateDeclarations: true to compile using --declaration + * @param outDir: true to compile using --outDir + * @param keepComments: false to compile using --removeComments + * @param callback: a function to execute after the compilation process ends */ -function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, noOutFile, generateDeclarations, callback) { +function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, noOutFile, generateDeclarations, outDir, keepComments, noResolve, callback) { file(outFile, prereqs, function() { var dir = useBuiltCompiler ? builtLocalDirectory : LKGDirectory; - var options = "-removeComments --module commonjs -noImplicitAny "; + var options = "--module commonjs -noImplicitAny"; + + if (!keepComments) { + options += " -removeComments"; + } + if (generateDeclarations) { - options += "--declaration "; + options += " --declaration"; } if (useDebugMode) { - options += "--preserveConstEnums "; + options += " --preserveConstEnums"; + } + + if (outDir) { + options += " --outDir " + outDir; + } + + if (!noOutFile) { + options += " --out " + outFile; + } + + if(noResolve) { + options += " --noResolve"; + } + + if (useDebugMode) { + options += " -sourcemap -mapRoot file:///" + path.resolve(path.dirname(outFile)); } var cmd = host + " " + dir + compilerFilename + " " + options + " "; - cmd = cmd + sources.join(" ") + (!noOutFile ? " -out " + outFile : ""); - if (useDebugMode) { - cmd = cmd + " -sourcemap -mapRoot file:///" + path.resolve(path.dirname(outFile)); - } + cmd = cmd + sources.join(" "); console.log(cmd + "\n"); + var ex = jake.createExec([cmd]); // Add listeners for output and error ex.addListener("stdout", function(output) { @@ -190,7 +242,7 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, noOu }); ex.addListener("error", function() { fs.unlinkSync(outFile); - console.log("Compilation of " + outFile + " unsuccessful"); + fail("Compilation of " + outFile + " unsuccessful"); }); ex.run(); }, {async: true}); @@ -259,24 +311,38 @@ var tscFile = path.join(builtLocalDirectory, compilerFilename); compileFile(tscFile, compilerSources, [builtLocalDirectory, copyright].concat(compilerSources), [copyright], /*useBuiltCompiler:*/ false); var servicesFile = path.join(builtLocalDirectory, "typescriptServices.js"); -var servicesDefinitionsFile = path.join(builtLocalDirectory, "typescriptServices.d.ts"); +compileFile(servicesFile, servicesSources,[builtLocalDirectory, copyright].concat(servicesSources), [copyright], /*useBuiltCompiler*/ true); -compileFile(servicesFile, - servicesSources, - [builtLocalDirectory, copyright].concat(servicesSources), - [copyright], +var nodeDefinitionsFile = path.join(builtLocalDirectory, "typescript.d.ts"); +var standaloneDefinitionsFile = path.join(builtLocalDirectory, "typescriptServices.d.ts"); +var tempDirPath = path.join(builtLocalDirectory, "temptempdir"); +compileFile(nodeDefinitionsFile, servicesSources,[builtLocalDirectory, copyright].concat(servicesSources), + /*prefixes*/ undefined, /*useBuiltCompiler*/ true, - /*noOutFile*/ false, + /*noOutFile*/ true, /*generateDeclarations*/ true, - /*callback*/ fixDeclarationFile); + /*outDir*/ tempDirPath, + /*keepComments*/ true, + /*noResolve*/ true, + /*callback*/ function () { + concatenateFiles(standaloneDefinitionsFile, definitionsRoots.map(function (f) { + return path.join(tempDirPath, f); + })); + prependFile(copyright, standaloneDefinitionsFile); -function fixDeclarationFile() { - fs.appendFileSync(servicesDefinitionsFile, os.EOL + "export = ts;") -} + // Create the node definition file by replacing 'ts' module with '"typescript"' as a module. + jake.cpR(standaloneDefinitionsFile, nodeDefinitionsFile, {silent: true}); + var definitionFileContents = fs.readFileSync(nodeDefinitionsFile).toString(); + definitionFileContents = definitionFileContents.replace(/declare module ts/g, 'declare module "typescript"'); + fs.writeFileSync(nodeDefinitionsFile, definitionFileContents); + + // Delete the temp dir + jake.rmRf(tempDirPath, {silent: true}); + }); // Local target to build the compiler and services desc("Builds the full compiler and services"); -task("local", ["generate-diagnostics", "lib", tscFile, servicesFile]); +task("local", ["generate-diagnostics", "lib", tscFile, servicesFile, nodeDefinitionsFile]); // Local target to build the compiler and services desc("Sets release mode flag"); @@ -327,7 +393,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", ["clean", "release", "local"].concat(libraryTargets), function() { - var expectedFiles = [tscFile, servicesFile, servicesDefinitionsFile].concat(libraryTargets); + var expectedFiles = [tscFile, servicesFile, nodeDefinitionsFile, standaloneDefinitionsFile].concat(libraryTargets); var missingFiles = expectedFiles.filter(function (f) { return !fs.existsSync(f); }); diff --git a/package.json b/package.json index f6391394c6a..a52067a3d08 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "url" : "https://github.com/Microsoft/TypeScript.git" }, "preferGlobal" : true, - "main" : "./bin/tsc.js", + "main" : "./bin/typescriptServices.js", "bin" : { "tsc" : "./bin/tsc" }, diff --git a/scripts/processDiagnosticMessages.ts b/scripts/processDiagnosticMessages.ts index eccfb821bb2..0d32c605fdc 100644 --- a/scripts/processDiagnosticMessages.ts +++ b/scripts/processDiagnosticMessages.ts @@ -15,6 +15,7 @@ interface IIndexable { } function main(): void { + var sys = ts.sys; if (sys.args.length < 1) { sys.write("Usage:" + sys.newLine) sys.write("\tnode processDiagnosticMessages.js " + sys.newLine); diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8c2bac87085..89f1f61e2e7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4,57 +4,12 @@ /// /// /// +/// module ts { var nextSymbolId = 1; var nextNodeId = 1; - var nextMergeId = 1; - - export function getDeclarationOfKind(symbol: Symbol, kind: SyntaxKind): Declaration { - var declarations = symbol.declarations; - for (var i = 0; i < declarations.length; i++) { - var declaration = declarations[i]; - if (declaration.kind === kind) { - return declaration; - } - } - - return undefined; - } - - export interface StringSymbolWriter extends SymbolWriter { - string(): string; - } - - // Pool writers to avoid needing to allocate them for every symbol we write. - var stringWriters: StringSymbolWriter[] = []; - export function getSingleLineStringWriter(): StringSymbolWriter { - if (stringWriters.length == 0) { - var str = ""; - - var writeText: (text: string) => void = text => str += text; - return { - string: () => str, - writeKeyword: writeText, - writeOperator: writeText, - writePunctuation: writeText, - writeSpace: writeText, - writeStringLiteral: writeText, - writeParameter: writeText, - writeSymbol: writeText, - - // Completely ignore indentation for string writers. And map newlines to - // a single space. - writeLine: () => str += " ", - increaseIndent: () => { }, - decreaseIndent: () => { }, - clear: () => str = "", - trackSymbol: () => { } - }; - } - - return stringWriters.pop(); - } + var nextMergeId = 1; /// fullTypeCheck denotes if this instance of the typechecker will be used to get semantic diagnostics. /// If fullTypeCheck === true, then the typechecker should do every possible check to produce all errors @@ -1012,11 +967,6 @@ module ts { }; } - function releaseStringWriter(writer: StringSymbolWriter) { - writer.clear() - stringWriters.push(writer); - } - function writeKeyword(writer: SymbolWriter, kind: SyntaxKind) { writer.writeKeyword(tokenToString(kind)); } @@ -4647,8 +4597,8 @@ module ts { // Get the narrowed type of a given symbol at a given location function getNarrowedTypeOfSymbol(symbol: Symbol, node: Node) { var type = getTypeOfSymbol(symbol); - // Only narrow when symbol is variable of a structured type - if (node && (symbol.flags & SymbolFlags.Variable && type.flags & TypeFlags.Structured)) { + // Only narrow when symbol is variable of an object, union, or type parameter type + if (node && symbol.flags & SymbolFlags.Variable && type.flags & (TypeFlags.ObjectType | TypeFlags.Union | TypeFlags.TypeParameter)) { loop: while (node.parent) { var child = node; node = node.parent; @@ -5644,7 +5594,7 @@ module ts { } // Fall back to any. - if (compilerOptions.noImplicitAny && objectType !== anyType) { + if (compilerOptions.noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors && objectType !== anyType) { error(node, Diagnostics.Index_signature_of_object_type_implicitly_has_an_any_type); } @@ -6634,12 +6584,12 @@ module ts { return numberType; } - // Return true if type is any, an object type, a type parameter, or a union type composed of only those kinds of types + // Return true if type an object type, a type parameter, or a union type composed of only those kinds of types function isStructuredType(type: Type): boolean { if (type.flags & TypeFlags.Union) { return !forEach((type).types, t => !isStructuredType(t)); } - return (type.flags & TypeFlags.Structured) !== 0; + return (type.flags & (TypeFlags.ObjectType | TypeFlags.TypeParameter)) !== 0; } function isConstEnumObjectType(type: Type): boolean { @@ -6656,11 +6606,11 @@ module ts { // and the right operand to be of type Any or a subtype of the 'Function' interface type. // The result is always of the Boolean primitive type. // NOTE: do not raise error if leftType is unknown as related error was already reported - if (leftType !== unknownType && !isStructuredType(leftType)) { + if (!(leftType.flags & TypeFlags.Any || isStructuredType(leftType))) { error(node.left, Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter); } // NOTE: do not raise error if right is unknown as related error was already reported - if (rightType !== unknownType && rightType !== anyType && !isTypeSubtypeOf(rightType, globalFunctionType)) { + if (!(rightType.flags & TypeFlags.Any || isTypeSubtypeOf(rightType, globalFunctionType))) { error(node.right, Diagnostics.The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type); } return booleanType; @@ -6674,7 +6624,7 @@ module ts { if (leftType !== anyType && leftType !== stringType && leftType !== numberType) { error(node.left, Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_types_any_string_or_number); } - if (!isStructuredType(rightType)) { + if (!(rightType.flags & TypeFlags.Any || isStructuredType(rightType))) { error(node.right, Diagnostics.The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter); } return booleanType; @@ -8038,7 +7988,7 @@ module ts { var exprType = checkExpression(node.expression); // unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved // in this case error about missing name is already reported - do not report extra one - if (!isStructuredType(exprType) && exprType !== unknownType) { + if (!(exprType.flags & TypeFlags.Any || isStructuredType(exprType))) { error(node.expression, Diagnostics.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter); } diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 3fabf6c8588..fabc897a355 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -88,6 +88,11 @@ module ts { description: Diagnostics.Redirect_output_structure_to_the_directory, paramType: Diagnostics.DIRECTORY, }, + { + name: "preserveConstEnums", + type: "boolean", + description: Diagnostics.Do_not_erase_const_enum_declarations_in_generated_code + }, { name: "removeComments", type: "boolean", @@ -104,6 +109,11 @@ module ts { description: Diagnostics.Specifies_the_location_where_debugger_should_locate_TypeScript_files_instead_of_source_locations, paramType: Diagnostics.LOCATION, }, + { + name: "suppressImplicitAnyIndexErrors", + type: "boolean", + description: Diagnostics.Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures, + }, { name: "target", shortName: "t", @@ -123,14 +133,9 @@ 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 } ]; - + var shortOptionNames: Map = {}; var optionNameMap: Map = {}; diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 8dfc0d59ea9..6e0c307034b 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -15,10 +15,6 @@ module ts { True = -1 } - export interface Map { - [index: string]: T; - } - export const enum Comparison { LessThan = -1, EqualTo = 0, @@ -591,27 +587,44 @@ module ts { return path; } - var escapedCharsRegExp = /[\t\v\f\b\0\r\n\"\\\u2028\u2029\u0085]/g; + var backslashOrDoubleQuote = /[\"\\]/g; + var escapedCharsRegExp = /[\0-\19\t\v\f\b\0\r\n\u2028\u2029\u0085]/g; var escapedCharsMap: Map = { + "\0": "\\0", "\t": "\\t", "\v": "\\v", "\f": "\\f", "\b": "\\b", - "\0": "\\0", "\r": "\\r", "\n": "\\n", + "\\": "\\\\", "\"": "\\\"", "\u2028": "\\u2028", // lineSeparator "\u2029": "\\u2029", // paragraphSeparator "\u0085": "\\u0085" // nextLine }; - /** NOTE: This *does not* support the full escape characters, it only supports the subset that can be used in file names - * or string literals. If the information encoded in the map changes, this needs to be revisited. */ + /** + * Based heavily on the abstract 'Quote' operation from ECMA-262 (24.3.2.2), + * but augmented for a few select characters. + * Note that this doesn't actually wrap the input in double quotes. + */ export function escapeString(s: string): string { - return escapedCharsRegExp.test(s) ? s.replace(escapedCharsRegExp, c => { - return escapedCharsMap[c] || c; - }) : s; + // Prioritize '"' and '\' + s = backslashOrDoubleQuote.test(s) ? s.replace(backslashOrDoubleQuote, getReplacement) : s; + s = escapedCharsRegExp.test(s) ? s.replace(escapedCharsRegExp, getReplacement) : s; + + return s; + + function getReplacement(c: string) { + return escapedCharsMap[c] || unicodeEscape(c); + } + + function unicodeEscape(c: string): string { + var hexCharCode = c.charCodeAt(0).toString(16); + var paddedHexCode = ("0000" + hexCharCode).slice(-4); + return "\\u" + paddedHexCode; + } } export interface ObjectAllocator { diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index e1ea3e21de0..dbcdc9b3fea 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -144,7 +144,8 @@ module ts { Array_element_destructuring_pattern_expected: { code: 1181, category: DiagnosticCategory.Error, key: "Array element destructuring pattern expected." }, A_destructuring_declaration_must_have_an_initializer: { code: 1182, category: DiagnosticCategory.Error, key: "A destructuring declaration must have an initializer." }, Destructuring_declarations_are_not_allowed_in_ambient_contexts: { code: 1183, category: DiagnosticCategory.Error, key: "Destructuring declarations are not allowed in ambient contexts." }, - A_rest_element_cannot_have_an_initializer: { code: 1184, category: DiagnosticCategory.Error, key: "A rest element cannot have an initializer." }, + Merge_conflict_marker_encountered: { code: 1184, category: DiagnosticCategory.Error, key: "Merge conflict marker encountered." }, + A_rest_element_cannot_have_an_initializer: { code: 1185, category: DiagnosticCategory.Error, key: "A rest element cannot have an initializer." }, 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." }, @@ -418,6 +419,7 @@ module ts { Warn_on_expressions_and_declarations_with_an_implied_any_type: { code: 6052, category: DiagnosticCategory.Message, key: "Warn on expressions and declarations with an implied 'any' type." }, File_0_not_found: { code: 6053, category: DiagnosticCategory.Error, key: "File '{0}' not found." }, File_0_must_have_extension_ts_or_d_ts: { code: 6054, category: DiagnosticCategory.Error, key: "File '{0}' must have extension '.ts' or '.d.ts'." }, + Suppress_noImplicitAny_errors_for_indexing_objects_lacking_index_signatures: { code: 6055, category: DiagnosticCategory.Message, key: "Suppress noImplicitAny errors for indexing objects lacking index signatures." }, Variable_0_implicitly_has_an_1_type: { code: 7005, category: DiagnosticCategory.Error, key: "Variable '{0}' implicitly has an '{1}' type." }, Parameter_0_implicitly_has_an_1_type: { code: 7006, category: DiagnosticCategory.Error, key: "Parameter '{0}' implicitly has an '{1}' type." }, Member_0_implicitly_has_an_1_type: { code: 7008, category: DiagnosticCategory.Error, key: "Member '{0}' implicitly has an '{1}' type." }, @@ -436,6 +438,7 @@ module ts { Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions: { code: 7024, category: DiagnosticCategory.Error, key: "Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions." }, You_cannot_rename_this_element: { code: 8000, category: DiagnosticCategory.Error, key: "You cannot rename this element." }, yield_expressions_are_not_currently_supported: { code: 9000, category: DiagnosticCategory.Error, key: "'yield' expressions are not currently supported." }, - generators_are_not_currently_supported: { code: 9001, category: DiagnosticCategory.Error, key: "'generators' are not currently supported." }, + Generators_are_not_currently_supported: { code: 9001, category: DiagnosticCategory.Error, key: "Generators are not currently supported." }, + Computed_property_names_are_not_currently_supported: { code: 9002, category: DiagnosticCategory.Error, key: "Computed property names are not currently supported." }, }; } \ No newline at end of file diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 6b4274fbc5d..1bd954d353d 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -568,10 +568,14 @@ "category": "Error", "code": 1183 }, - "A rest element cannot have an initializer.": { + "Merge conflict marker encountered.": { "category": "Error", "code": 1184 }, + "A rest element cannot have an initializer.": { + "category": "Error", + "code": 1185 + }, "Duplicate identifier '{0}'.": { "category": "Error", @@ -1671,6 +1675,10 @@ "category": "Error", "code": 6054 }, + "Suppress noImplicitAny errors for indexing objects lacking index signatures.": { + "category": "Message", + "code": 6055 + }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", @@ -1744,8 +1752,12 @@ "category": "Error", "code": 9000 }, - "'generators' are not currently supported.": { + "Generators are not currently supported.": { "category": "Error", "code": 9001 + }, + "Computed property names are not currently supported.": { + "category": "Error", + "code": 9002 } } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 2fcdd876864..dcf9d4f3df2 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2866,9 +2866,8 @@ module ts { function createVoidZero(): Expression { var zero = createNode(SyntaxKind.NumericLiteral); zero.text = "0"; - var result = createNode(SyntaxKind.PrefixUnaryExpression); - result.operator = SyntaxKind.VoidKeyword; - result.operand = zero; + var result = createNode(SyntaxKind.VoidExpression); + result.expression = zero; return result; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 94cab916a05..04c48e0bd33 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1,41 +1,11 @@ /// /// /// +/// module ts { var nodeConstructors = new Array Node>(SyntaxKind.Count); - export function getFullWidth(node: Node) { - return node.end - node.pos; - } - - function hasFlag(val: number, flag: number): boolean { - return (val & flag) !== 0; - } - - // Returns true if this node contains a parse error anywhere underneath it. - export function containsParseError(node: Node): boolean { - if (!hasFlag(node.parserContextFlags, ParserContextFlags.HasPropagatedChildContainsErrorFlag)) { - // A node is considered to contain a parse error if: - // a) the parser explicitly marked that it had an error - // b) any of it's children reported that it had an error. - var val = hasFlag(node.parserContextFlags, ParserContextFlags.ContainsError) || - forEachChild(node, containsParseError); - - // If so, mark ourselves accordingly. - if (val) { - node.parserContextFlags |= ParserContextFlags.ContainsError; - } - - // Also mark that we've propogated the child information to this node. This way we can - // always consult the bit directly on this node without needing to check its children - // again. - node.parserContextFlags |= ParserContextFlags.HasPropagatedChildContainsErrorFlag; - } - - return hasFlag(node.parserContextFlags, ParserContextFlags.ContainsError); - } - export function getNodeConstructor(kind: SyntaxKind): new () => Node { return nodeConstructors[kind] || (nodeConstructors[kind] = objectAllocator.getNodeConstructor(kind)); } @@ -44,182 +14,6 @@ module ts { return new (getNodeConstructor(kind))(); } - export function getSourceFileOfNode(node: Node): SourceFile { - while (node && node.kind !== SyntaxKind.SourceFile) node = node.parent; - return node; - } - - // This is a useful function for debugging purposes. - export function nodePosToString(node: Node): string { - var file = getSourceFileOfNode(node); - var loc = file.getLineAndCharacterFromPosition(node.pos); - return file.filename + "(" + loc.line + "," + loc.character + ")"; - } - - export function getStartPosOfNode(node: Node): number { - return node.pos; - } - - export function isMissingNode(node: Node) { - return node.pos === node.end && node.kind !== SyntaxKind.EndOfFileToken; - } - - export function getTokenPosOfNode(node: Node, sourceFile?: SourceFile): number { - // With nodes that have no width (i.e. 'Missing' nodes), we actually *don't* - // want to skip trivia because this will launch us forward to the next token. - if (isMissingNode(node)) { - return node.pos; - } - - return skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.pos); - } - - export function getSourceTextOfNodeFromSourceFile(sourceFile: SourceFile, node: Node): string { - if (isMissingNode(node)) { - return ""; - } - - var text = sourceFile.text; - return text.substring(skipTrivia(text, node.pos), node.end); - } - - export function getTextOfNodeFromSourceText(sourceText: string, node: Node): string { - if (isMissingNode(node)) { - return ""; - } - - return sourceText.substring(skipTrivia(sourceText, node.pos), node.end); - } - - export function getTextOfNode(node: Node): string { - return getSourceTextOfNodeFromSourceFile(getSourceFileOfNode(node), node); - } - - // Add an extra underscore to identifiers that start with two underscores to avoid issues with magic names like '__proto__' - export function escapeIdentifier(identifier: string): string { - return identifier.length >= 2 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ ? "_" + identifier : identifier; - } - - // Remove extra underscore from escaped identifier - export function unescapeIdentifier(identifier: string): string { - return identifier.length >= 3 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ && identifier.charCodeAt(2) === CharacterCodes._ ? identifier.substr(1) : identifier; - } - - // Return display name of an identifier - // Computed property names will just be emitted as "[]", where is the source - // text of the expression in the computed property. - export function declarationNameToString(name: DeclarationName) { - return getFullWidth(name) === 0 ? "(Missing)" : getTextOfNode(name); - } - - export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): Diagnostic { - node = getErrorSpanForNode(node); - var file = getSourceFileOfNode(node); - - var start = getFullWidth(node) === 0 ? node.pos : skipTrivia(file.text, node.pos); - var length = node.end - start; - - return createFileDiagnostic(file, start, length, message, arg0, arg1, arg2); - } - - export function createDiagnosticForNodeFromMessageChain(node: Node, messageChain: DiagnosticMessageChain, newLine: string): Diagnostic { - node = getErrorSpanForNode(node); - var file = getSourceFileOfNode(node); - var start = skipTrivia(file.text, node.pos); - var length = node.end - start; - return flattenDiagnosticChain(file, start, length, messageChain, newLine); - } - - export function getErrorSpanForNode(node: Node): Node { - var errorSpan: Node; - switch (node.kind) { - // This list is a work in progress. Add missing node kinds to improve their error - // spans. - case SyntaxKind.VariableDeclaration: - case SyntaxKind.BindingElement: - case SyntaxKind.ClassDeclaration: - case SyntaxKind.InterfaceDeclaration: - case SyntaxKind.ModuleDeclaration: - case SyntaxKind.EnumDeclaration: - case SyntaxKind.EnumMember: - errorSpan = (node).name; - break; - } - - // We now have the ideal error span, but it may be a node that is optional and absent - // (e.g. the name of a function expression), in which case errorSpan will be undefined. - // Alternatively, it might be required and missing (e.g. the name of a module), in which - // case its pos will equal its end (length 0). In either of these cases, we should fall - // back to the original node that the error was issued on. - return errorSpan && errorSpan.pos < errorSpan.end ? errorSpan : node; - } - - export function isExternalModule(file: SourceFile): boolean { - return file.externalModuleIndicator !== undefined; - } - - export function isDeclarationFile(file: SourceFile): boolean { - return (file.flags & NodeFlags.DeclarationFile) !== 0; - } - - export function isConstEnumDeclaration(node: Node): boolean { - return node.kind === SyntaxKind.EnumDeclaration && isConst(node); - } - - export function isConst(node: Node): boolean { - return !!(node.flags & NodeFlags.Const); - } - - export function isLet(node: Node): boolean { - return !!(node.flags & NodeFlags.Let); - } - - export function isPrologueDirective(node: Node): boolean { - return node.kind === SyntaxKind.ExpressionStatement && (node).expression.kind === SyntaxKind.StringLiteral; - } - - function isEvalOrArgumentsIdentifier(node: Node): boolean { - return node.kind === SyntaxKind.Identifier && - (node).text && - ((node).text === "eval" || (node).text === "arguments"); - } - - /// Should be called only on prologue directives (isPrologueDirective(node) should be true) - function isUseStrictPrologueDirective(node: Node): boolean { - Debug.assert(isPrologueDirective(node)); - return ((node).expression).text === "use strict"; - } - - export function getLeadingCommentRangesOfNode(node: Node, sourceFileOfNode?: SourceFile) { - sourceFileOfNode = sourceFileOfNode || getSourceFileOfNode(node); - - // If parameter/type parameter, the prev token trailing comments are part of this node too - if (node.kind === SyntaxKind.Parameter || node.kind === SyntaxKind.TypeParameter) { - // e.g. (/** blah */ a, /** blah */ b); - return concatenate(getTrailingCommentRanges(sourceFileOfNode.text, node.pos), - // e.g.: ( - // /** blah */ a, - // /** blah */ b); - getLeadingCommentRanges(sourceFileOfNode.text, node.pos)); - } - else { - return getLeadingCommentRanges(sourceFileOfNode.text, node.pos); - } - } - - export function getJsDocComments(node: Node, sourceFileOfNode: SourceFile) { - return filter(getLeadingCommentRangesOfNode(node, sourceFileOfNode), isJsDocComment); - - function isJsDocComment(comment: CommentRange) { - // True if the comment starts with '/**' but not if it is '/**/' - return sourceFileOfNode.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk && - sourceFileOfNode.text.charCodeAt(comment.pos + 2) === CharacterCodes.asterisk && - sourceFileOfNode.text.charCodeAt(comment.pos + 3) !== CharacterCodes.slash; - } - } - - export var fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*/ - // Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes // stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise, // embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns @@ -468,425 +262,78 @@ module ts { } } - // Warning: This has the same semantics as the forEach family of functions, - // in that traversal terminates in the event that 'visitor' supplies a truthy value. - export function forEachReturnStatement(body: Block, visitor: (stmt: ReturnStatement) => T): T { + // TODO (drosen, mhegazy): Move to a more appropriate file. + export function createCompilerHost(options: CompilerOptions): CompilerHost { + var currentDirectory: string; + var existingDirectories: Map = {}; - return traverse(body); - - function traverse(node: Node): T { - switch (node.kind) { - case SyntaxKind.ReturnStatement: - return visitor(node); - case SyntaxKind.Block: - case SyntaxKind.IfStatement: - case SyntaxKind.DoStatement: - case SyntaxKind.WhileStatement: - case SyntaxKind.ForStatement: - case SyntaxKind.ForInStatement: - case SyntaxKind.WithStatement: - case SyntaxKind.SwitchStatement: - case SyntaxKind.CaseClause: - case SyntaxKind.DefaultClause: - case SyntaxKind.LabeledStatement: - case SyntaxKind.TryStatement: - case SyntaxKind.TryBlock: - case SyntaxKind.CatchClause: - case SyntaxKind.FinallyBlock: - return forEachChild(node, traverse); - } - } - } - - export function isAnyFunction(node: Node): boolean { - if (node) { - switch (node.kind) { - case SyntaxKind.Constructor: - case SyntaxKind.FunctionExpression: - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.ArrowFunction: - case SyntaxKind.MethodDeclaration: - case SyntaxKind.MethodSignature: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - case SyntaxKind.CallSignature: - case SyntaxKind.ConstructSignature: - case SyntaxKind.IndexSignature: - case SyntaxKind.FunctionType: - case SyntaxKind.ConstructorType: - case SyntaxKind.FunctionExpression: - case SyntaxKind.ArrowFunction: - case SyntaxKind.FunctionDeclaration: - return true; - } - } - - return false; - } - - export function isFunctionBlock(node: Node) { - return node && node.kind === SyntaxKind.Block && isAnyFunction(node.parent); - } - - export function isObjectLiteralMethod(node: Node) { - return node && node.kind === SyntaxKind.MethodDeclaration && node.parent.kind === SyntaxKind.ObjectLiteralExpression; - } - - export function getContainingFunction(node: Node): FunctionLikeDeclaration { - while (true) { - node = node.parent; - if (!node || isAnyFunction(node)) { - return node; - } - } - } - - export function getThisContainer(node: Node, includeArrowFunctions: boolean): Node { - while (true) { - node = node.parent; - if (!node) { - return undefined; - } - switch (node.kind) { - case SyntaxKind.ArrowFunction: - if (!includeArrowFunctions) { - continue; - } - // Fall through - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.FunctionExpression: - case SyntaxKind.ModuleDeclaration: - case SyntaxKind.PropertyDeclaration: - case SyntaxKind.PropertySignature: - case SyntaxKind.MethodDeclaration: - case SyntaxKind.MethodSignature: - case SyntaxKind.Constructor: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - case SyntaxKind.EnumDeclaration: - case SyntaxKind.SourceFile: - return node; - } - } - } - - export function getSuperContainer(node: Node): Node { - while (true) { - node = node.parent; - if (!node) { - return undefined; - } - switch (node.kind) { - case SyntaxKind.PropertyDeclaration: - case SyntaxKind.PropertySignature: - case SyntaxKind.MethodDeclaration: - case SyntaxKind.MethodSignature: - case SyntaxKind.Constructor: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - return node; - } - } - } - - export function getInvokedExpression(node: CallLikeExpression): Expression { - if (node.kind === SyntaxKind.TaggedTemplateExpression) { - return (node).tag; + function getCanonicalFileName(fileName: string): string { + // if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form. + // otherwise use toLowerCase as a canonical form. + return sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); } - // Will either be a CallExpression or NewExpression. - return (node).expression; - } + // returned by CScript sys environment + var unsupportedFileEncodingErrorCode = -2147024809; - 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.ArrayLiteralExpression: - case SyntaxKind.ObjectLiteralExpression: - case SyntaxKind.PropertyAccessExpression: - case SyntaxKind.ElementAccessExpression: - case SyntaxKind.CallExpression: - case SyntaxKind.NewExpression: - case SyntaxKind.TaggedTemplateExpression: - case SyntaxKind.TypeAssertionExpression: - case SyntaxKind.ParenthesizedExpression: - case SyntaxKind.FunctionExpression: - case SyntaxKind.ArrowFunction: - case SyntaxKind.VoidExpression: - case SyntaxKind.DeleteExpression: - case SyntaxKind.TypeOfExpression: - case SyntaxKind.PrefixUnaryExpression: - case SyntaxKind.PostfixUnaryExpression: - case SyntaxKind.BinaryExpression: - case SyntaxKind.ConditionalExpression: - case SyntaxKind.SpreadElementExpression: - case SyntaxKind.TemplateExpression: - case SyntaxKind.NoSubstitutionTemplateLiteral: - case SyntaxKind.OmittedExpression: - return true; - case SyntaxKind.QualifiedName: - while (node.parent.kind === SyntaxKind.QualifiedName) { - node = node.parent; + function getSourceFile(filename: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile { + try { + var text = sys.readFile(filename, options.charset); + } + catch (e) { + if (onError) { + onError(e.number === unsupportedFileEncodingErrorCode ? + createCompilerDiagnostic(Diagnostics.Unsupported_file_encoding).messageText : + e.message); } + text = ""; + } - return node.parent.kind === SyntaxKind.TypeQuery; - case SyntaxKind.Identifier: - if (node.parent.kind === SyntaxKind.TypeQuery) { + return text !== undefined ? createSourceFile(filename, text, languageVersion) : undefined; + } + + function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) { + function directoryExists(directoryPath: string): boolean { + if (hasProperty(existingDirectories, directoryPath)) { 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.PropertyDeclaration: - case SyntaxKind.PropertySignature: - case SyntaxKind.EnumMember: - case SyntaxKind.PropertyAssignment: - case SyntaxKind.BindingElement: - return (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 (parent).expression === node; - case SyntaxKind.ForStatement: - return (parent).initializer === node || - (parent).condition === node || - (parent).iterator === node; - case SyntaxKind.ForInStatement: - return (parent).variable === node || - (parent).expression === node; - case SyntaxKind.TypeAssertionExpression: - return node === (parent).expression; - case SyntaxKind.TemplateSpan: - return node === (parent).expression; - default: - if (isExpression(parent)) { - return true; - } + if (sys.directoryExists(directoryPath)) { + existingDirectories[directoryPath] = true; + return true; } - } - return false; - } - - export function isExternalModuleImportDeclaration(node: Node) { - return node.kind === SyntaxKind.ImportDeclaration && (node).moduleReference.kind === SyntaxKind.ExternalModuleReference; - } - - export function getExternalModuleImportDeclarationExpression(node: Node) { - Debug.assert(isExternalModuleImportDeclaration(node)); - return ((node).moduleReference).expression; - } - - export function isInternalModuleImportDeclaration(node: Node) { - return node.kind === SyntaxKind.ImportDeclaration && (node).moduleReference.kind !== SyntaxKind.ExternalModuleReference; - } - - export function hasDotDotDotToken(node: Node) { - return node && node.kind === SyntaxKind.Parameter && (node).dotDotDotToken !== undefined; - } - - export function hasQuestionToken(node: Node) { - if (node) { - switch (node.kind) { - case SyntaxKind.Parameter: - return (node).questionToken !== undefined; - case SyntaxKind.MethodDeclaration: - case SyntaxKind.MethodSignature: - return (node).questionToken !== undefined; - case SyntaxKind.ShorthandPropertyAssignment: - case SyntaxKind.PropertyAssignment: - case SyntaxKind.PropertyDeclaration: - case SyntaxKind.PropertySignature: - return (node).questionToken !== undefined; - } - } - - return false; - } - - export function hasRestParameters(s: SignatureDeclaration): boolean { - return s.parameters.length > 0 && s.parameters[s.parameters.length - 1].dotDotDotToken !== undefined; - } - - 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 isBindingPattern(node: Node) { - return node.kind === SyntaxKind.ArrayBindingPattern || node.kind === SyntaxKind.ObjectBindingPattern; - } - - export function isInAmbientContext(node: Node): boolean { - while (node) { - if (node.flags & (NodeFlags.Ambient | NodeFlags.DeclarationFile)) return true; - node = node.parent; - } - return false; - } - - export function isDeclaration(node: Node): boolean { - switch (node.kind) { - case SyntaxKind.TypeParameter: - case SyntaxKind.Parameter: - case SyntaxKind.VariableDeclaration: - case SyntaxKind.BindingElement: - case SyntaxKind.PropertyDeclaration: - case SyntaxKind.PropertySignature: - case SyntaxKind.PropertyAssignment: - case SyntaxKind.ShorthandPropertyAssignment: - case SyntaxKind.EnumMember: - case SyntaxKind.MethodDeclaration: - case SyntaxKind.MethodSignature: - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - case SyntaxKind.Constructor: - case SyntaxKind.ClassDeclaration: - case SyntaxKind.InterfaceDeclaration: - case SyntaxKind.TypeAliasDeclaration: - case SyntaxKind.EnumDeclaration: - case SyntaxKind.ModuleDeclaration: - case SyntaxKind.ImportDeclaration: - return true; - } - return false; - } - - export function isStatement(n: Node): boolean { - switch(n.kind) { - case SyntaxKind.BreakStatement: - case SyntaxKind.ContinueStatement: - case SyntaxKind.DebuggerStatement: - case SyntaxKind.DoStatement: - case SyntaxKind.ExpressionStatement: - case SyntaxKind.EmptyStatement: - case SyntaxKind.ForInStatement: - case SyntaxKind.ForStatement: - case SyntaxKind.IfStatement: - case SyntaxKind.LabeledStatement: - case SyntaxKind.ReturnStatement: - case SyntaxKind.SwitchStatement: - case SyntaxKind.ThrowKeyword: - case SyntaxKind.TryStatement: - case SyntaxKind.VariableStatement: - case SyntaxKind.WhileStatement: - case SyntaxKind.WithStatement: - case SyntaxKind.ExportAssignment: - return true; - default: return false; - } - } + } - // True if the given identifier, string literal, or number literal is the name of a declaration node - export function isDeclarationOrFunctionExpressionOrCatchVariableName(name: Node): boolean { - if (name.kind !== SyntaxKind.Identifier && name.kind !== SyntaxKind.StringLiteral && name.kind !== SyntaxKind.NumericLiteral) { - return false; - } + function ensureDirectoriesExist(directoryPath: string) { + if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) { + var parentDirectory = getDirectoryPath(directoryPath); + ensureDirectoriesExist(parentDirectory); + sys.createDirectory(directoryPath); + } + } - var parent = name.parent; - if (isDeclaration(parent) || parent.kind === SyntaxKind.FunctionExpression) { - return (parent).name === name; - } - - if (parent.kind === SyntaxKind.CatchClause) { - return (parent).name === name; - } - - return false; - } - - export function getClassBaseTypeNode(node: ClassDeclaration) { - var heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ExtendsKeyword); - return heritageClause && heritageClause.types.length > 0 ? heritageClause.types[0] : undefined; - } - - export function getClassImplementedTypeNodes(node: ClassDeclaration) { - var heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ImplementsKeyword); - return heritageClause ? heritageClause.types : undefined; - } - - export function getInterfaceBaseTypeNodes(node: InterfaceDeclaration) { - var heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ExtendsKeyword); - return heritageClause ? heritageClause.types : undefined; - } - - export function getHeritageClause(clauses: NodeArray, kind: SyntaxKind) { - if (clauses) { - for (var i = 0, n = clauses.length; i < n; i++) { - if (clauses[i].token === kind) { - return clauses[i]; + try { + ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName))); + sys.writeFile(fileName, data, writeByteOrderMark); + } + catch (e) { + if (onError) { + onError(e.message); } } } - return undefined; + return { + getSourceFile, + getDefaultLibFilename: options => combinePaths(getDirectoryPath(normalizePath(sys.getExecutingFilePath())), options.target === ScriptTarget.ES6 ? "lib.es6.d.ts" : "lib.d.ts"), + writeFile, + getCurrentDirectory: () => currentDirectory || (currentDirectory = sys.getCurrentDirectory()), + useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames, + getCanonicalFileName, + getNewLine: () => sys.newLine + }; } - export function tryResolveScriptReference(program: Program, sourceFile: SourceFile, reference: FileReference) { - if (!program.getCompilerOptions().noResolve) { - var referenceFileName = isRootedDiskPath(reference.filename) ? reference.filename : combinePaths(getDirectoryPath(sourceFile.filename), reference.filename); - referenceFileName = getNormalizedAbsolutePath(referenceFileName, program.getCompilerHost().getCurrentDirectory()); - return program.getSourceFile(referenceFileName); - } - } - - export function getAncestor(node: Node, kind: SyntaxKind): Node { - switch (kind) { - // special-cases that can be come first - case SyntaxKind.ClassDeclaration: - while (node) { - switch (node.kind) { - case SyntaxKind.ClassDeclaration: - return node; - case SyntaxKind.EnumDeclaration: - case SyntaxKind.InterfaceDeclaration: - case SyntaxKind.TypeAliasDeclaration: - case SyntaxKind.ModuleDeclaration: - case SyntaxKind.ImportDeclaration: - // early exit cases - declarations cannot be nested in classes - return undefined; - default: - node = node.parent; - continue; - } - } - break; - default: - while (node) { - if (node.kind === kind) { - return node; - } - node = node.parent; - } - break; - } - - return undefined; - } const enum ParsingContext { SourceElements, // Elements in source file @@ -943,68 +390,6 @@ module ts { } }; - export interface ReferencePathMatchResult { - fileReference?: FileReference - diagnosticMessage?: DiagnosticMessage - isNoDefaultLib?: boolean - } - - export function getFileReferenceFromReferencePath(comment: string, commentRange: CommentRange): ReferencePathMatchResult { - var simpleReferenceRegEx = /^\/\/\/\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; - return { - fileReference: { - pos: start, - end: end, - filename: matchResult[3] - }, - isNoDefaultLib: false - }; - } - else { - return { - diagnosticMessage: Diagnostics.Invalid_reference_directive_syntax, - isNoDefaultLib: false - }; - } - } - } - return undefined; - } - - export function isKeyword(token: SyntaxKind): boolean { - return SyntaxKind.FirstKeyword <= token && token <= SyntaxKind.LastKeyword; - } - - export function isTrivia(token: SyntaxKind) { - return SyntaxKind.FirstTriviaToken <= token && token <= SyntaxKind.LastTriviaToken; - } - - export function isModifier(token: SyntaxKind): boolean { - switch (token) { - case SyntaxKind.PublicKeyword: - case SyntaxKind.PrivateKeyword: - case SyntaxKind.ProtectedKeyword: - case SyntaxKind.StaticKeyword: - case SyntaxKind.ExportKeyword: - case SyntaxKind.DeclareKeyword: - case SyntaxKind.ConstKeyword: - return true; - } - return false; - } - function modifierToFlag(token: SyntaxKind): NodeFlags { switch (token) { case SyntaxKind.StaticKeyword: return NodeFlags.Static; @@ -1018,7 +403,41 @@ module ts { return 0; } - export function createSourceFile(filename: string, sourceText: string, languageVersion: ScriptTarget, version: string, isOpen: boolean = false): SourceFile { + function fixupParentReferences(sourceFile: SourceFile) { + // normally parent references are set during binding. + // however here SourceFile data is used only for syntactic features so running the whole binding process is an overhead. + // walk over the nodes and set parent references + var parent: Node = sourceFile; + function walk(n: Node): void { + // walk down setting parents that differ from the parent we think it should be. This + // allows us to quickly bail out of setting parents for subtrees during incremental + // parsing + if (n.parent !== parent) { + n.parent = parent; + + var saveParent = parent; + parent = n; + forEachChild(n, walk); + parent = saveParent; + } + } + + forEachChild(sourceFile, walk); + } + + function isEvalOrArgumentsIdentifier(node: Node): boolean { + return node.kind === SyntaxKind.Identifier && + ((node).text === "eval" || (node).text === "arguments"); + } + + /// Should be called only on prologue directives (isPrologueDirective(node) should be true) + function isUseStrictPrologueDirective(sourceFile: SourceFile, node: Node): boolean { + Debug.assert(isPrologueDirective(node)); + var nodeText = getSourceTextOfNodeFromSourceFile(sourceFile,(node).expression); + return nodeText === '"use strict"' || nodeText === "'use strict'"; + } + + export function createSourceFile(filename: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes = false): SourceFile { var parsingContext: ParsingContext; var identifiers: Map = {}; var identifierCount = 0; @@ -1134,10 +553,13 @@ module ts { sourceFile.nodeCount = nodeCount; sourceFile.identifierCount = identifierCount; - sourceFile.version = version; - sourceFile.isOpen = isOpen; sourceFile.languageVersion = languageVersion; sourceFile.identifiers = identifiers; + + if (setParentNodes) { + fixupParentReferences(sourceFile); + } + return sourceFile; function setContextFlag(val: Boolean, flag: ParserContextFlags) { @@ -1436,7 +858,7 @@ module ts { // flag so that we don't mark any subsequent nodes. if (parseErrorBeforeNextFinishedNode) { parseErrorBeforeNextFinishedNode = false; - node.parserContextFlags |= ParserContextFlags.ContainsError; + node.parserContextFlags |= ParserContextFlags.ThisNodeHasError; } return node; @@ -1718,7 +1140,7 @@ module ts { // test elements only if we are not already in strict mode if (checkForStrictMode && !inStrictModeContext()) { if (isPrologueDirective(element)) { - if (isUseStrictPrologueDirective(element)) { + if (isUseStrictPrologueDirective(sourceFile, element)) { setStrictModeContext(true); checkForStrictMode = false; } @@ -5079,7 +4501,7 @@ module ts { function checkForGenerator(node: FunctionLikeDeclaration) { if (node.asteriskToken) { - return grammarErrorOnNode(node.asteriskToken, Diagnostics.generators_are_not_currently_supported); + return grammarErrorOnNode(node.asteriskToken, Diagnostics.Generators_are_not_currently_supported); } } @@ -5572,6 +4994,10 @@ module ts { } function checkComputedPropertyName(node: ComputedPropertyName) { + // Since computed properties are not supported in the type checker, disallow them in TypeScript 1.4 + // Once full support is added, remove this error. + return grammarErrorOnNode(node, Diagnostics.Computed_property_names_are_not_currently_supported); + if (languageVersion < ScriptTarget.ES6) { return grammarErrorOnNode(node, Diagnostics.Computed_property_names_are_only_available_when_targeting_ECMAScript_6_and_higher); } diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index c80a6f68d02..9853e22d9f1 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -333,10 +333,14 @@ module ts { var ch = text.charCodeAt(pos); switch (ch) { case CharacterCodes.carriageReturn: - if (text.charCodeAt(pos + 1) === CharacterCodes.lineFeed) pos++; + if (text.charCodeAt(pos + 1) === CharacterCodes.lineFeed) { + pos++; + } case CharacterCodes.lineFeed: pos++; - if (stopAfterLineBreak) return pos; + if (stopAfterLineBreak) { + return pos; + } continue; case CharacterCodes.tab: case CharacterCodes.verticalTab: @@ -367,6 +371,16 @@ module ts { continue; } break; + + case CharacterCodes.lessThan: + case CharacterCodes.equals: + case CharacterCodes.greaterThan: + if (isConflictMarkerTrivia(text, pos)) { + pos = scanConflictMarkerTrivia(text, pos); + continue; + } + break; + default: if (ch > CharacterCodes.maxAsciiCharacter && (isWhiteSpace(ch) || isLineBreak(ch))) { pos++; @@ -378,6 +392,39 @@ module ts { } } + function isConflictMarkerTrivia(text: string, pos: number) { + // Conflict markers must be at the start of a line. + if (pos > 0 && isLineBreak(text.charCodeAt(pos - 1))) { + var ch = text.charCodeAt(pos); + + // All conflict markers consist of the same character repeated seven times. If it is + // a <<<<<<< or >>>>>>> marker then it is also followd by a space. + var markerLength = "<<<<<<<".length; + + if ((pos + markerLength) < text.length) { + for (var i = 0, n = markerLength; i < n; i++) { + if (text.charCodeAt(pos + i) !== ch) { + return false; + } + } + + return ch === CharacterCodes.equals || + text.charCodeAt(pos + markerLength) === CharacterCodes.space; + } + } + + return false; + } + + function scanConflictMarkerTrivia(text: string, pos: number) { + var len = text.length; + while (pos < len && !isLineBreak(text.charCodeAt(pos))) { + pos++; + } + + return pos; + } + // Extract comments from the given source text starting at the given position. If trailing is false, whitespace is skipped until // the first line break and comments between that location and the next token are returned. If trailing is true, comments occurring // between the given position and the next line break are returned. The return value is an array containing a TextRange for each @@ -640,14 +687,14 @@ module ts { // Speculated ECMAScript 6 Spec 11.8.6.1: // and LineTerminatorSequences are normalized to for Template Values - // An explicit EscapeSequence is needed to include a or sequence. if (currChar === CharacterCodes.carriageReturn) { contents += text.substring(start, pos); + pos++; - if (pos + 1 < len && text.charCodeAt(pos + 1) === CharacterCodes.lineFeed) { + if (pos < len && text.charCodeAt(pos) === CharacterCodes.lineFeed) { pos++; } - pos++; + contents += "\n"; start = pos; continue; @@ -1010,6 +1057,17 @@ module ts { case CharacterCodes.semicolon: return pos++, token = SyntaxKind.SemicolonToken; case CharacterCodes.lessThan: + if (isConflictMarkerTrivia(text, pos)) { + error(Diagnostics.Merge_conflict_marker_encountered); + pos = scanConflictMarkerTrivia(text, pos); + if (skipTrivia) { + continue; + } + else { + return token = SyntaxKind.ConflictMarkerTrivia; + } + } + if (text.charCodeAt(pos + 1) === CharacterCodes.lessThan) { if (text.charCodeAt(pos + 2) === CharacterCodes.equals) { return pos += 3, token = SyntaxKind.LessThanLessThanEqualsToken; @@ -1021,6 +1079,17 @@ module ts { } return pos++, token = SyntaxKind.LessThanToken; case CharacterCodes.equals: + if (isConflictMarkerTrivia(text, pos)) { + error(Diagnostics.Merge_conflict_marker_encountered); + pos = scanConflictMarkerTrivia(text, pos); + if (skipTrivia) { + continue; + } + else { + return token = SyntaxKind.ConflictMarkerTrivia; + } + } + if (text.charCodeAt(pos + 1) === CharacterCodes.equals) { if (text.charCodeAt(pos + 2) === CharacterCodes.equals) { return pos += 3, token = SyntaxKind.EqualsEqualsEqualsToken; @@ -1032,6 +1101,17 @@ module ts { } return pos++, token = SyntaxKind.EqualsToken; case CharacterCodes.greaterThan: + if (isConflictMarkerTrivia(text, pos)) { + error(Diagnostics.Merge_conflict_marker_encountered); + pos = scanConflictMarkerTrivia(text, pos); + if (skipTrivia) { + continue; + } + else { + return token = SyntaxKind.ConflictMarkerTrivia; + } + } + return pos++, token = SyntaxKind.GreaterThanToken; case CharacterCodes.question: return pos++, token = SyntaxKind.QuestionToken; diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index e58d08589ba..27a8c305c4b 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -1,252 +1,255 @@ -interface System { - args: string[]; - newLine: string; - useCaseSensitiveFileNames: boolean; - write(s: string): void; - readFile(fileName: string, encoding?: string): string; - writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void; - watchFile?(fileName: string, callback: (fileName: string) => void): FileWatcher; - resolvePath(path: string): string; - fileExists(path: string): boolean; - directoryExists(path: string): boolean; - createDirectory(directoryName: string): void; - getExecutingFilePath(): string; - getCurrentDirectory(): string; - getMemoryUsage?(): number; - exit(exitCode?: number): void; -} +module ts { + export interface System { + args: string[]; + newLine: string; + useCaseSensitiveFileNames: boolean; + write(s: string): void; + readFile(fileName: string, encoding?: string): string; + writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void; + watchFile? (fileName: string, callback: (fileName: string) => void): FileWatcher; + resolvePath(path: string): string; + fileExists(path: string): boolean; + directoryExists(path: string): boolean; + createDirectory(directoryName: string): void; + getExecutingFilePath(): string; + getCurrentDirectory(): string; + getMemoryUsage? (): number; + exit(exitCode?: number): void; + } -interface FileWatcher { - close(): void; -} + export interface FileWatcher { + close(): void; + } -declare var require: any; -declare var module: any; -declare var process: any; -declare var global: any; + declare var require: any; + declare var module: any; + declare var process: any; + declare var global: any; + declare var __filename: string; -var sys: System = (function () { + export var sys: System = (function () { - function getWScriptSystem(): System { + function getWScriptSystem(): System { - var fso = new ActiveXObject("Scripting.FileSystemObject"); + var fso = new ActiveXObject("Scripting.FileSystemObject"); - var fileStream = new ActiveXObject("ADODB.Stream"); - fileStream.Type = 2 /*text*/; + var fileStream = new ActiveXObject("ADODB.Stream"); + fileStream.Type = 2 /*text*/; - var binaryStream = new ActiveXObject("ADODB.Stream"); - binaryStream.Type = 1 /*binary*/; + var binaryStream = new ActiveXObject("ADODB.Stream"); + binaryStream.Type = 1 /*binary*/; - var args: string[] = []; - for (var i = 0; i < WScript.Arguments.length; i++) { - args[i] = WScript.Arguments.Item(i); - } - - function readFile(fileName: string, encoding?: string): string { - if (!fso.FileExists(fileName)) { - return undefined; + var args: string[] = []; + for (var i = 0; i < WScript.Arguments.length; i++) { + args[i] = WScript.Arguments.Item(i); } - fileStream.Open(); - try { - if (encoding) { - fileStream.Charset = encoding; - fileStream.LoadFromFile(fileName); + + function readFile(fileName: string, encoding?: string): string { + if (!fso.FileExists(fileName)) { + return undefined; } - else { - // Load file and read the first two bytes into a string with no interpretation - fileStream.Charset = "x-ansi"; - fileStream.LoadFromFile(fileName); - var bom = fileStream.ReadText(2) || ""; - // Position must be at 0 before encoding can be changed - fileStream.Position = 0; - // [0xFF,0xFE] and [0xFE,0xFF] mean utf-16 (little or big endian), otherwise default to utf-8 - fileStream.Charset = bom.length >= 2 && (bom.charCodeAt(0) === 0xFF && bom.charCodeAt(1) === 0xFE || bom.charCodeAt(0) === 0xFE && bom.charCodeAt(1) === 0xFF) ? "unicode" : "utf-8"; - } - // ReadText method always strips byte order mark from resulting string - return fileStream.ReadText(); - } - catch (e) { - throw e; - } - finally { - fileStream.Close(); - } - } - - function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void { - fileStream.Open(); - binaryStream.Open(); - try { - // Write characters in UTF-8 encoding - fileStream.Charset = "utf-8"; - fileStream.WriteText(data); - // If we don't want the BOM, then skip it by setting the starting location to 3 (size of BOM). - // If not, start from position 0, as the BOM will be added automatically when charset==utf8. - if (writeByteOrderMark) { - fileStream.Position = 0; - } - else { - fileStream.Position = 3; - } - fileStream.CopyTo(binaryStream); - binaryStream.SaveToFile(fileName, 2 /*overwrite*/); - } - finally { - binaryStream.Close(); - fileStream.Close(); - } - } - - return { - args, - newLine: "\r\n", - useCaseSensitiveFileNames: false, - write(s: string): void { - WScript.StdOut.Write(s); - }, - readFile, - writeFile, - resolvePath(path: string): string { - return fso.GetAbsolutePathName(path); - }, - fileExists(path: string): boolean { - return fso.FileExists(path); - }, - directoryExists(path: string) { - return fso.FolderExists(path); - }, - createDirectory(directoryName: string) { - if (!this.directoryExists(directoryName)) { - fso.CreateFolder(directoryName); - } - }, - getExecutingFilePath() { - return WScript.ScriptFullName; - }, - getCurrentDirectory() { - return new ActiveXObject("WScript.Shell").CurrentDirectory; - }, - exit(exitCode?: number): void { + fileStream.Open(); try { - WScript.Quit(exitCode); + if (encoding) { + fileStream.Charset = encoding; + fileStream.LoadFromFile(fileName); + } + else { + // Load file and read the first two bytes into a string with no interpretation + fileStream.Charset = "x-ansi"; + fileStream.LoadFromFile(fileName); + var bom = fileStream.ReadText(2) || ""; + // Position must be at 0 before encoding can be changed + fileStream.Position = 0; + // [0xFF,0xFE] and [0xFE,0xFF] mean utf-16 (little or big endian), otherwise default to utf-8 + fileStream.Charset = bom.length >= 2 && (bom.charCodeAt(0) === 0xFF && bom.charCodeAt(1) === 0xFE || bom.charCodeAt(0) === 0xFE && bom.charCodeAt(1) === 0xFF) ? "unicode" : "utf-8"; + } + // ReadText method always strips byte order mark from resulting string + return fileStream.ReadText(); } catch (e) { + throw e; + } + finally { + fileStream.Close(); } } - }; - } - function getNodeSystem(): System { - var _fs = require("fs"); - var _path = require("path"); - var _os = require('os'); - var platform: string = _os.platform(); - // win32\win64 are case insensitive platforms, MacOS (darwin) by default is also case insensitive - var useCaseSensitiveFileNames = platform !== "win32" && platform !== "win64" && platform !== "darwin"; - - function readFile(fileName: string, encoding?: string): string { - if (!_fs.existsSync(fileName)) { - return undefined; - } - var buffer = _fs.readFileSync(fileName); - var len = buffer.length; - if (len >= 2 && buffer[0] === 0xFE && buffer[1] === 0xFF) { - // Big endian UTF-16 byte order mark detected. Since big endian is not supported by node.js, - // flip all byte pairs and treat as little endian. - len &= ~1; - for (var i = 0; i < len; i += 2) { - var temp = buffer[i]; - buffer[i] = buffer[i + 1]; - buffer[i + 1] = temp; - } - return buffer.toString("utf16le", 2); - } - if (len >= 2 && buffer[0] === 0xFF && buffer[1] === 0xFE) { - // Little endian UTF-16 byte order mark detected - return buffer.toString("utf16le", 2); - } - if (len >= 3 && buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) { - // UTF-8 byte order mark detected - return buffer.toString("utf8", 3); - } - // Default is UTF-8 with no byte order mark - return buffer.toString("utf8"); - } - - function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void { - // If a BOM is required, emit one - if (writeByteOrderMark) { - data = '\uFEFF' + data; - } - - _fs.writeFileSync(fileName, data, "utf8"); - } - - return { - args: process.argv.slice(2), - newLine: _os.EOL, - useCaseSensitiveFileNames: useCaseSensitiveFileNames, - write(s: string): void { - // 1 is a standard descriptor for stdout - _fs.writeSync(1, s); - }, - readFile, - writeFile, - watchFile: (fileName, callback) => { - // watchFile polls a file every 250ms, picking up file notifications. - _fs.watchFile(fileName, { persistent: true, interval: 250 }, fileChanged); - - return { - close() { _fs.unwatchFile(fileName, fileChanged); } - }; - - function fileChanged(curr: any, prev: any) { - if (+curr.mtime <= +prev.mtime) { - return; + function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void { + fileStream.Open(); + binaryStream.Open(); + try { + // Write characters in UTF-8 encoding + fileStream.Charset = "utf-8"; + fileStream.WriteText(data); + // If we don't want the BOM, then skip it by setting the starting location to 3 (size of BOM). + // If not, start from position 0, as the BOM will be added automatically when charset==utf8. + if (writeByteOrderMark) { + fileStream.Position = 0; } - - callback(fileName); - }; - }, - resolvePath: function (path: string): string { - return _path.resolve(path); - }, - fileExists(path: string): boolean { - return _fs.existsSync(path); - }, - directoryExists(path: string) { - return _fs.existsSync(path) && _fs.statSync(path).isDirectory(); - }, - createDirectory(directoryName: string) { - if (!this.directoryExists(directoryName)) { - _fs.mkdirSync(directoryName); + else { + fileStream.Position = 3; + } + fileStream.CopyTo(binaryStream); + binaryStream.SaveToFile(fileName, 2 /*overwrite*/); } - }, - getExecutingFilePath() { - return process.mainModule.filename; - }, - getCurrentDirectory() { - return (process).cwd(); - }, - getMemoryUsage() { - if (global.gc) { - global.gc(); + finally { + binaryStream.Close(); + fileStream.Close(); } - return process.memoryUsage().heapUsed; - }, - exit(exitCode?: number): void { - process.exit(exitCode); } - }; - } - if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") { - return getWScriptSystem(); - } - else if (typeof module !== "undefined" && module.exports) { - return getNodeSystem(); - } - else { - return undefined; // Unsupported host - } -})(); + + return { + args, + newLine: "\r\n", + useCaseSensitiveFileNames: false, + write(s: string): void { + WScript.StdOut.Write(s); + }, + readFile, + writeFile, + resolvePath(path: string): string { + return fso.GetAbsolutePathName(path); + }, + fileExists(path: string): boolean { + return fso.FileExists(path); + }, + directoryExists(path: string) { + return fso.FolderExists(path); + }, + createDirectory(directoryName: string) { + if (!this.directoryExists(directoryName)) { + fso.CreateFolder(directoryName); + } + }, + getExecutingFilePath() { + return WScript.ScriptFullName; + }, + getCurrentDirectory() { + return new ActiveXObject("WScript.Shell").CurrentDirectory; + }, + exit(exitCode?: number): void { + try { + WScript.Quit(exitCode); + } + catch (e) { + } + } + }; + } + function getNodeSystem(): System { + var _fs = require("fs"); + var _path = require("path"); + var _os = require('os'); + + var platform: string = _os.platform(); + // win32\win64 are case insensitive platforms, MacOS (darwin) by default is also case insensitive + var useCaseSensitiveFileNames = platform !== "win32" && platform !== "win64" && platform !== "darwin"; + + function readFile(fileName: string, encoding?: string): string { + if (!_fs.existsSync(fileName)) { + return undefined; + } + var buffer = _fs.readFileSync(fileName); + var len = buffer.length; + if (len >= 2 && buffer[0] === 0xFE && buffer[1] === 0xFF) { + // Big endian UTF-16 byte order mark detected. Since big endian is not supported by node.js, + // flip all byte pairs and treat as little endian. + len &= ~1; + for (var i = 0; i < len; i += 2) { + var temp = buffer[i]; + buffer[i] = buffer[i + 1]; + buffer[i + 1] = temp; + } + return buffer.toString("utf16le", 2); + } + if (len >= 2 && buffer[0] === 0xFF && buffer[1] === 0xFE) { + // Little endian UTF-16 byte order mark detected + return buffer.toString("utf16le", 2); + } + if (len >= 3 && buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) { + // UTF-8 byte order mark detected + return buffer.toString("utf8", 3); + } + // Default is UTF-8 with no byte order mark + return buffer.toString("utf8"); + } + + function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void { + // If a BOM is required, emit one + if (writeByteOrderMark) { + data = '\uFEFF' + data; + } + + _fs.writeFileSync(fileName, data, "utf8"); + } + + return { + args: process.argv.slice(2), + newLine: _os.EOL, + useCaseSensitiveFileNames: useCaseSensitiveFileNames, + write(s: string): void { + // 1 is a standard descriptor for stdout + _fs.writeSync(1, s); + }, + readFile, + writeFile, + watchFile: (fileName, callback) => { + // watchFile polls a file every 250ms, picking up file notifications. + _fs.watchFile(fileName, { persistent: true, interval: 250 }, fileChanged); + + return { + close() { _fs.unwatchFile(fileName, fileChanged); } + }; + + function fileChanged(curr: any, prev: any) { + if (+curr.mtime <= +prev.mtime) { + return; + } + + callback(fileName); + }; + }, + resolvePath: function (path: string): string { + return _path.resolve(path); + }, + fileExists(path: string): boolean { + return _fs.existsSync(path); + }, + directoryExists(path: string) { + return _fs.existsSync(path) && _fs.statSync(path).isDirectory(); + }, + createDirectory(directoryName: string) { + if (!this.directoryExists(directoryName)) { + _fs.mkdirSync(directoryName); + } + }, + getExecutingFilePath() { + return __filename; + }, + getCurrentDirectory() { + return process.cwd(); + }, + getMemoryUsage() { + if (global.gc) { + global.gc(); + } + return process.memoryUsage().heapUsed; + }, + exit(exitCode?: number): void { + process.exit(exitCode); + } + }; + } + if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") { + return getWScriptSystem(); + } + else if (typeof module !== "undefined" && module.exports) { + return getNodeSystem(); + } + else { + return undefined; // Unsupported host + } + })(); +} \ No newline at end of file diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index fbe596ee0f7..bc4d48b7513 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -133,75 +133,6 @@ module ts { reportStatisticalValue(name, (time / 1000).toFixed(2) + "s"); } - function createCompilerHost(options: CompilerOptions): CompilerHost { - var currentDirectory: string; - var existingDirectories: Map = {}; - - function getCanonicalFileName(fileName: string): string { - // if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form. - // otherwise use toLowerCase as a canonical form. - return sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); - } - - // returned by CScript sys environment - var unsupportedFileEncodingErrorCode = -2147024809; - - function getSourceFile(filename: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile { - try { - var text = sys.readFile(filename, options.charset); - } - catch (e) { - if (onError) { - onError(e.number === unsupportedFileEncodingErrorCode ? - getDiagnosticText(Diagnostics.Unsupported_file_encoding) : - e.message); - } - text = ""; - } - return text !== undefined ? createSourceFile(filename, text, languageVersion, /*version:*/ "0") : undefined; - } - - function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) { - - function directoryExists(directoryPath: string): boolean { - if (hasProperty(existingDirectories, directoryPath)) { - return true; - } - if (sys.directoryExists(directoryPath)) { - existingDirectories[directoryPath] = true; - return true; - } - return false; - } - - function ensureDirectoriesExist(directoryPath: string) { - if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) { - var parentDirectory = getDirectoryPath(directoryPath); - ensureDirectoriesExist(parentDirectory); - sys.createDirectory(directoryPath); - } - } - - try { - ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName))); - sys.writeFile(fileName, data, writeByteOrderMark); - } - catch (e) { - if (onError) onError(e.message); - } - } - - return { - getSourceFile, - getDefaultLibFilename: options => combinePaths(getDirectoryPath(normalizePath(sys.getExecutingFilePath())), options.target === ScriptTarget.ES6 ? "lib.es6.d.ts" : "lib.d.ts"), - writeFile, - getCurrentDirectory: () => currentDirectory || (currentDirectory = sys.getCurrentDirectory()), - useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames, - getCanonicalFileName, - getNewLine: () => sys.newLine - }; - } - export function executeCommandLine(args: string[]): void { var commandLine = parseCommandLine(args); var compilerOptions = commandLine.options; @@ -447,12 +378,12 @@ module ts { var usageText = " "; if (option.shortName) { usageText += "-" + option.shortName; - usageText += getParamName(option); + usageText += getParamType(option); usageText += ", "; } usageText += "--" + option.name; - usageText += getParamName(option); + usageText += getParamType(option); usageColumn.push(usageText); descriptionColumn.push(getDiagnosticText(option.description)); @@ -477,9 +408,9 @@ module ts { sys.write(output); return; - function getParamName(option: CommandLineOption) { - if (option.paramName !== undefined) { - return " " + getDiagnosticText(option.paramName); + function getParamType(option: CommandLineOption) { + if (option.paramType !== undefined) { + return " " + getDiagnosticText(option.paramType); } return ""; } @@ -490,4 +421,4 @@ module ts { } } -ts.executeCommandLine(sys.args); +ts.executeCommandLine(ts.sys.args); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 72514a622d1..8facb81e5cb 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1,6 +1,9 @@ /// module ts { + export interface Map { + [index: string]: T; + } export interface TextRange { pos: number; @@ -15,6 +18,7 @@ module ts { MultiLineCommentTrivia, NewLineTrivia, WhitespaceTrivia, + ConflictMarkerTrivia, // Literals NumericLiteral, StringLiteral, @@ -267,7 +271,7 @@ module ts { FirstToken = Unknown, LastToken = TypeKeyword, FirstTriviaToken = SingleLineCommentTrivia, - LastTriviaToken = WhitespaceTrivia, + LastTriviaToken = ConflictMarkerTrivia, FirstLiteralToken = NumericLiteral, LastLiteralToken = NoSubstitutionTemplateLiteral, FirstTemplateToken = NoSubstitutionTemplateLiteral, @@ -314,14 +318,22 @@ module ts { // If the parser encountered an error when parsing the code that created this node. Note // the parser only sets this directly on the node it creates right after encountering the - // error. We then propagate that flag upwards to parent nodes during incremental parsing. - ContainsError = 1 << 4, + // error. + ThisNodeHasError = 1 << 4, + + // Context flags set directly by the parser. + ParserGeneratedFlags = StrictMode | DisallowIn | Yield | GeneratorParameter | ThisNodeHasError, + + // Context flags computed by aggregating child flags upwards. + + // If this node, or any of it's children (transitively) contain an error. + ThisNodeOrAnySubNodesHasError = 1 << 5, // Used during incremental parsing to determine if we need to visit this node to see if // any of its children had an error. Once we compute that once, we can set this bit on the // node to know that we never have to do it again. From that point on, we can just check // the node directly for 'ContainsError'. - HasPropagatedChildContainsErrorFlag = 1 << 5 + HasComputedThisNodeOrAnySubNodesHasError = 1 << 6 } export interface Node extends TextRange { @@ -900,8 +912,6 @@ module ts { nodeCount: number; identifierCount: number; symbolCount: number; - isOpen: boolean; - version: string; languageVersion: ScriptTarget; identifiers: Map; } @@ -1245,7 +1255,6 @@ module ts { StringLike = String | StringLiteral, NumberLike = Number | Enum, ObjectType = Class | Interface | Reference | Tuple | Anonymous, - Structured = Any | ObjectType | Union | TypeParameter } // Properties common to all types @@ -1400,6 +1409,7 @@ module ts { } export interface CompilerOptions { + allowNonTsExtensions?: boolean; charset?: string; codepage?: number; declaration?: boolean; @@ -1417,21 +1427,21 @@ module ts { noResolve?: boolean; out?: string; outDir?: string; + preserveConstEnums?: boolean; removeComments?: boolean; sourceMap?: boolean; sourceRoot?: string; + suppressImplicitAnyIndexErrors?: boolean; target?: ScriptTarget; version?: boolean; watch?: boolean; - preserveConstEnums?: boolean; - allowNonTsExtensions?: boolean; [option: string]: string | number | boolean; } export const enum ModuleKind { - None, - CommonJS, - AMD, + None = 0, + CommonJS = 1, + AMD = 2, } export interface LineAndCharacter { @@ -1444,9 +1454,9 @@ module ts { export const enum ScriptTarget { - ES3, - ES5, - ES6, + ES3 = 0, + ES5 = 1, + ES6 = 2, Latest = ES6, } @@ -1461,7 +1471,7 @@ module ts { type: string | Map; // "string", "number", "boolean", or an object literal mapping named values to actual values shortName?: string; // A short mnemonic for convenience - for instance, 'h' can be used in place of 'help'. description?: DiagnosticMessage; // The message describing what the command line switch does - paramName?: DiagnosticMessage; // The name to be used for a non-boolean option's parameter. + paramType?: DiagnosticMessage; // The name to be used for a non-boolean option's parameter. error?: DiagnosticMessage; // The error given when the argument does not fit a customized 'type'. } @@ -1599,7 +1609,7 @@ module ts { tab = 0x09, // \t verticalTab = 0x0B, // \v } - + export interface CancellationToken { isCancellationRequested(): boolean; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts new file mode 100644 index 00000000000..5f9859eba9b --- /dev/null +++ b/src/compiler/utilities.ts @@ -0,0 +1,735 @@ +/// + +module ts { + export interface ReferencePathMatchResult { + fileReference?: FileReference + diagnosticMessage?: DiagnosticMessage + isNoDefaultLib?: boolean + } + + export function getDeclarationOfKind(symbol: Symbol, kind: SyntaxKind): Declaration { + var declarations = symbol.declarations; + for (var i = 0; i < declarations.length; i++) { + var declaration = declarations[i]; + if (declaration.kind === kind) { + return declaration; + } + } + + return undefined; + } + + export interface StringSymbolWriter extends SymbolWriter { + string(): string; + } + + // Pool writers to avoid needing to allocate them for every symbol we write. + var stringWriters: StringSymbolWriter[] = []; + export function getSingleLineStringWriter(): StringSymbolWriter { + if (stringWriters.length == 0) { + var str = ""; + + var writeText: (text: string) => void = text => str += text; + return { + string: () => str, + writeKeyword: writeText, + writeOperator: writeText, + writePunctuation: writeText, + writeSpace: writeText, + writeStringLiteral: writeText, + writeParameter: writeText, + writeSymbol: writeText, + + // Completely ignore indentation for string writers. And map newlines to + // a single space. + writeLine: () => str += " ", + increaseIndent: () => { }, + decreaseIndent: () => { }, + clear: () => str = "", + trackSymbol: () => { } + }; + } + + return stringWriters.pop(); + } + + export function releaseStringWriter(writer: StringSymbolWriter) { + writer.clear() + stringWriters.push(writer); + } + + export function getFullWidth(node: Node) { + return node.end - node.pos; + } + + export function hasFlag(val: number, flag: number): boolean { + return (val & flag) !== 0; + } + + // Returns true if this node contains a parse error anywhere underneath it. + export function containsParseError(node: Node): boolean { + if (!hasFlag(node.parserContextFlags, ParserContextFlags.HasComputedThisNodeOrAnySubNodesHasError)) { + // A node is considered to contain a parse error if: + // a) the parser explicitly marked that it had an error + // b) any of it's children reported that it had an error. + var val = hasFlag(node.parserContextFlags, ParserContextFlags.ThisNodeHasError) || + forEachChild(node, containsParseError); + + // If so, mark ourselves accordingly. + if (val) { + node.parserContextFlags |= ParserContextFlags.ThisNodeOrAnySubNodesHasError; + } + + // Also mark that we've propogated the child information to this node. This way we can + // always consult the bit directly on this node without needing to check its children + // again. + node.parserContextFlags |= ParserContextFlags.HasComputedThisNodeOrAnySubNodesHasError; + } + + return hasFlag(node.parserContextFlags, ParserContextFlags.ThisNodeOrAnySubNodesHasError); + } + + export function getSourceFileOfNode(node: Node): SourceFile { + while (node && node.kind !== SyntaxKind.SourceFile) { + node = node.parent; + } + return node; + } + + // This is a useful function for debugging purposes. + export function nodePosToString(node: Node): string { + var file = getSourceFileOfNode(node); + var loc = file.getLineAndCharacterFromPosition(node.pos); + return file.filename + "(" + loc.line + "," + loc.character + ")"; + } + + export function getStartPosOfNode(node: Node): number { + return node.pos; + } + + export function isMissingNode(node: Node) { + return node.pos === node.end && node.kind !== SyntaxKind.EndOfFileToken; + } + + export function getTokenPosOfNode(node: Node, sourceFile?: SourceFile): number { + // With nodes that have no width (i.e. 'Missing' nodes), we actually *don't* + // want to skip trivia because this will launch us forward to the next token. + if (isMissingNode(node)) { + return node.pos; + } + + return skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.pos); + } + + export function getSourceTextOfNodeFromSourceFile(sourceFile: SourceFile, node: Node): string { + if (isMissingNode(node)) { + return ""; + } + + var text = sourceFile.text; + return text.substring(skipTrivia(text, node.pos), node.end); + } + + export function getTextOfNodeFromSourceText(sourceText: string, node: Node): string { + if (isMissingNode(node)) { + return ""; + } + + return sourceText.substring(skipTrivia(sourceText, node.pos), node.end); + } + + export function getTextOfNode(node: Node): string { + return getSourceTextOfNodeFromSourceFile(getSourceFileOfNode(node), node); + } + + // Add an extra underscore to identifiers that start with two underscores to avoid issues with magic names like '__proto__' + export function escapeIdentifier(identifier: string): string { + return identifier.length >= 2 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ ? "_" + identifier : identifier; + } + + // Remove extra underscore from escaped identifier + export function unescapeIdentifier(identifier: string): string { + return identifier.length >= 3 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ && identifier.charCodeAt(2) === CharacterCodes._ ? identifier.substr(1) : identifier; + } + + // Return display name of an identifier + // Computed property names will just be emitted as "[]", where is the source + // text of the expression in the computed property. + export function declarationNameToString(name: DeclarationName) { + return getFullWidth(name) === 0 ? "(Missing)" : getTextOfNode(name); + } + + export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): Diagnostic { + node = getErrorSpanForNode(node); + var file = getSourceFileOfNode(node); + + var start = getTokenPosOfNode(node, file); + var length = node.end - start; + + return createFileDiagnostic(file, start, length, message, arg0, arg1, arg2); + } + + export function createDiagnosticForNodeFromMessageChain(node: Node, messageChain: DiagnosticMessageChain, newLine: string): Diagnostic { + node = getErrorSpanForNode(node); + var file = getSourceFileOfNode(node); + var start = skipTrivia(file.text, node.pos); + var length = node.end - start; + return flattenDiagnosticChain(file, start, length, messageChain, newLine); + } + + export function getErrorSpanForNode(node: Node): Node { + var errorSpan: Node; + switch (node.kind) { + // This list is a work in progress. Add missing node kinds to improve their error + // spans. + case SyntaxKind.VariableDeclaration: + case SyntaxKind.BindingElement: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.EnumMember: + errorSpan = (node).name; + break; + } + + // We now have the ideal error span, but it may be a node that is optional and absent + // (e.g. the name of a function expression), in which case errorSpan will be undefined. + // Alternatively, it might be required and missing (e.g. the name of a module), in which + // case its pos will equal its end (length 0). In either of these cases, we should fall + // back to the original node that the error was issued on. + return errorSpan && errorSpan.pos < errorSpan.end ? errorSpan : node; + } + + export function isExternalModule(file: SourceFile): boolean { + return file.externalModuleIndicator !== undefined; + } + + export function isDeclarationFile(file: SourceFile): boolean { + return (file.flags & NodeFlags.DeclarationFile) !== 0; + } + + export function isConstEnumDeclaration(node: Node): boolean { + return node.kind === SyntaxKind.EnumDeclaration && isConst(node); + } + + export function isConst(node: Node): boolean { + return !!(node.flags & NodeFlags.Const); + } + + export function isLet(node: Node): boolean { + return !!(node.flags & NodeFlags.Let); + } + + export function isPrologueDirective(node: Node): boolean { + return node.kind === SyntaxKind.ExpressionStatement && (node).expression.kind === SyntaxKind.StringLiteral; + } + + export function getLeadingCommentRangesOfNode(node: Node, sourceFileOfNode?: SourceFile) { + sourceFileOfNode = sourceFileOfNode || getSourceFileOfNode(node); + + // If parameter/type parameter, the prev token trailing comments are part of this node too + if (node.kind === SyntaxKind.Parameter || node.kind === SyntaxKind.TypeParameter) { + // e.g. (/** blah */ a, /** blah */ b); + return concatenate(getTrailingCommentRanges(sourceFileOfNode.text, node.pos), + // e.g.: ( + // /** blah */ a, + // /** blah */ b); + getLeadingCommentRanges(sourceFileOfNode.text, node.pos)); + } + else { + return getLeadingCommentRanges(sourceFileOfNode.text, node.pos); + } + } + + export function getJsDocComments(node: Node, sourceFileOfNode: SourceFile) { + return filter(getLeadingCommentRangesOfNode(node, sourceFileOfNode), isJsDocComment); + + function isJsDocComment(comment: CommentRange) { + // True if the comment starts with '/**' but not if it is '/**/' + return sourceFileOfNode.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk && + sourceFileOfNode.text.charCodeAt(comment.pos + 2) === CharacterCodes.asterisk && + sourceFileOfNode.text.charCodeAt(comment.pos + 3) !== CharacterCodes.slash; + } + } + + export var fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*/ + + + // Warning: This has the same semantics as the forEach family of functions, + // in that traversal terminates in the event that 'visitor' supplies a truthy value. + export function forEachReturnStatement(body: Block, visitor: (stmt: ReturnStatement) => T): T { + + return traverse(body); + + function traverse(node: Node): T { + switch (node.kind) { + case SyntaxKind.ReturnStatement: + return visitor(node); + case SyntaxKind.Block: + case SyntaxKind.IfStatement: + case SyntaxKind.DoStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.WithStatement: + case SyntaxKind.SwitchStatement: + case SyntaxKind.CaseClause: + case SyntaxKind.DefaultClause: + case SyntaxKind.LabeledStatement: + case SyntaxKind.TryStatement: + case SyntaxKind.TryBlock: + case SyntaxKind.CatchClause: + case SyntaxKind.FinallyBlock: + return forEachChild(node, traverse); + } + } + } + + export function isAnyFunction(node: Node): boolean { + if (node) { + switch (node.kind) { + case SyntaxKind.Constructor: + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ArrowFunction: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.IndexSignature: + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionDeclaration: + return true; + } + } + + return false; + } + + export function isFunctionBlock(node: Node) { + return node && node.kind === SyntaxKind.Block && isAnyFunction(node.parent); + } + + export function isObjectLiteralMethod(node: Node) { + return node && node.kind === SyntaxKind.MethodDeclaration && node.parent.kind === SyntaxKind.ObjectLiteralExpression; + } + + export function getContainingFunction(node: Node): FunctionLikeDeclaration { + while (true) { + node = node.parent; + if (!node || isAnyFunction(node)) { + return node; + } + } + } + + export function getThisContainer(node: Node, includeArrowFunctions: boolean): Node { + while (true) { + node = node.parent; + if (!node) { + return undefined; + } + switch (node.kind) { + case SyntaxKind.ArrowFunction: + if (!includeArrowFunctions) { + continue; + } + // Fall through + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.SourceFile: + return node; + } + } + } + + export function getSuperContainer(node: Node): Node { + while (true) { + node = node.parent; + if (!node) { + return undefined; + } + switch (node.kind) { + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return node; + } + } + } + + export function getInvokedExpression(node: CallLikeExpression): Expression { + if (node.kind === SyntaxKind.TaggedTemplateExpression) { + return (node).tag; + } + + // Will either be a CallExpression or NewExpression. + return (node).expression; + } + + 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.ArrayLiteralExpression: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.VoidExpression: + case SyntaxKind.DeleteExpression: + case SyntaxKind.TypeOfExpression: + case SyntaxKind.PrefixUnaryExpression: + case SyntaxKind.PostfixUnaryExpression: + case SyntaxKind.BinaryExpression: + case SyntaxKind.ConditionalExpression: + case SyntaxKind.SpreadElementExpression: + 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.PropertyDeclaration: + case SyntaxKind.PropertySignature: + case SyntaxKind.EnumMember: + case SyntaxKind.PropertyAssignment: + case SyntaxKind.BindingElement: + return (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 (parent).expression === node; + case SyntaxKind.ForStatement: + return (parent).initializer === node || + (parent).condition === node || + (parent).iterator === node; + case SyntaxKind.ForInStatement: + return (parent).variable === node || + (parent).expression === node; + case SyntaxKind.TypeAssertionExpression: + return node === (parent).expression; + case SyntaxKind.TemplateSpan: + return node === (parent).expression; + default: + if (isExpression(parent)) { + return true; + } + } + } + return false; + } + + export function isExternalModuleImportDeclaration(node: Node) { + return node.kind === SyntaxKind.ImportDeclaration && (node).moduleReference.kind === SyntaxKind.ExternalModuleReference; + } + + export function getExternalModuleImportDeclarationExpression(node: Node) { + Debug.assert(isExternalModuleImportDeclaration(node)); + return ((node).moduleReference).expression; + } + + export function isInternalModuleImportDeclaration(node: Node) { + return node.kind === SyntaxKind.ImportDeclaration && (node).moduleReference.kind !== SyntaxKind.ExternalModuleReference; + } + + export function hasDotDotDotToken(node: Node) { + return node && node.kind === SyntaxKind.Parameter && (node).dotDotDotToken !== undefined; + } + + export function hasQuestionToken(node: Node) { + if (node) { + switch (node.kind) { + case SyntaxKind.Parameter: + return (node).questionToken !== undefined; + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + return (node).questionToken !== undefined; + case SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.PropertyAssignment: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + return (node).questionToken !== undefined; + } + } + + return false; + } + + export function hasRestParameters(s: SignatureDeclaration): boolean { + return s.parameters.length > 0 && s.parameters[s.parameters.length - 1].dotDotDotToken !== undefined; + } + + 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 isBindingPattern(node: Node) { + return node.kind === SyntaxKind.ArrayBindingPattern || node.kind === SyntaxKind.ObjectBindingPattern; + } + + export function isInAmbientContext(node: Node): boolean { + while (node) { + if (node.flags & (NodeFlags.Ambient | NodeFlags.DeclarationFile)) return true; + node = node.parent; + } + return false; + } + + export function isDeclaration(node: Node): boolean { + switch (node.kind) { + case SyntaxKind.TypeParameter: + case SyntaxKind.Parameter: + case SyntaxKind.VariableDeclaration: + case SyntaxKind.BindingElement: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + case SyntaxKind.PropertyAssignment: + case SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.EnumMember: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.Constructor: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.ImportDeclaration: + return true; + } + return false; + } + + export function isStatement(n: Node): boolean { + switch (n.kind) { + case SyntaxKind.BreakStatement: + case SyntaxKind.ContinueStatement: + case SyntaxKind.DebuggerStatement: + case SyntaxKind.DoStatement: + case SyntaxKind.ExpressionStatement: + case SyntaxKind.EmptyStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.IfStatement: + case SyntaxKind.LabeledStatement: + case SyntaxKind.ReturnStatement: + case SyntaxKind.SwitchStatement: + case SyntaxKind.ThrowKeyword: + case SyntaxKind.TryStatement: + case SyntaxKind.VariableStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.WithStatement: + case SyntaxKind.ExportAssignment: + return true; + default: + return false; + } + } + + // True if the given identifier, string literal, or number literal is the name of a declaration node + export function isDeclarationOrFunctionExpressionOrCatchVariableName(name: Node): boolean { + if (name.kind !== SyntaxKind.Identifier && name.kind !== SyntaxKind.StringLiteral && name.kind !== SyntaxKind.NumericLiteral) { + return false; + } + + var parent = name.parent; + if (isDeclaration(parent) || parent.kind === SyntaxKind.FunctionExpression) { + return (parent).name === name; + } + + if (parent.kind === SyntaxKind.CatchClause) { + return (parent).name === name; + } + + return false; + } + + export function getClassBaseTypeNode(node: ClassDeclaration) { + var heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ExtendsKeyword); + return heritageClause && heritageClause.types.length > 0 ? heritageClause.types[0] : undefined; + } + + export function getClassImplementedTypeNodes(node: ClassDeclaration) { + var heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ImplementsKeyword); + return heritageClause ? heritageClause.types : undefined; + } + + export function getInterfaceBaseTypeNodes(node: InterfaceDeclaration) { + var heritageClause = getHeritageClause(node.heritageClauses, SyntaxKind.ExtendsKeyword); + return heritageClause ? heritageClause.types : undefined; + } + + export function getHeritageClause(clauses: NodeArray, kind: SyntaxKind) { + if (clauses) { + for (var i = 0, n = clauses.length; i < n; i++) { + if (clauses[i].token === kind) { + return clauses[i]; + } + } + } + + return undefined; + } + + export function tryResolveScriptReference(program: Program, sourceFile: SourceFile, reference: FileReference) { + if (!program.getCompilerOptions().noResolve) { + var referenceFileName = isRootedDiskPath(reference.filename) ? reference.filename : combinePaths(getDirectoryPath(sourceFile.filename), reference.filename); + referenceFileName = getNormalizedAbsolutePath(referenceFileName, program.getCompilerHost().getCurrentDirectory()); + return program.getSourceFile(referenceFileName); + } + } + + export function getAncestor(node: Node, kind: SyntaxKind): Node { + switch (kind) { + // special-cases that can be come first + case SyntaxKind.ClassDeclaration: + while (node) { + switch (node.kind) { + case SyntaxKind.ClassDeclaration: + return node; + case SyntaxKind.EnumDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.ImportDeclaration: + // early exit cases - declarations cannot be nested in classes + return undefined; + default: + node = node.parent; + continue; + } + } + break; + default: + while (node) { + if (node.kind === kind) { + return node; + } + node = node.parent; + } + break; + } + + return undefined; + } + + export function getFileReferenceFromReferencePath(comment: string, commentRange: CommentRange): ReferencePathMatchResult { + var simpleReferenceRegEx = /^\/\/\/\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; + return { + fileReference: { + pos: start, + end: end, + filename: matchResult[3] + }, + isNoDefaultLib: false + }; + } + else { + return { + diagnosticMessage: Diagnostics.Invalid_reference_directive_syntax, + isNoDefaultLib: false + }; + } + } + } + return undefined; + } + + export function isKeyword(token: SyntaxKind): boolean { + return SyntaxKind.FirstKeyword <= token && token <= SyntaxKind.LastKeyword; + } + + export function isTrivia(token: SyntaxKind) { + return SyntaxKind.FirstTriviaToken <= token && token <= SyntaxKind.LastTriviaToken; + } + + export function isModifier(token: SyntaxKind): boolean { + switch (token) { + case SyntaxKind.PublicKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.StaticKeyword: + case SyntaxKind.ExportKeyword: + case SyntaxKind.DeclareKeyword: + case SyntaxKind.ConstKeyword: + return true; + } + return false; + } + +} \ No newline at end of file diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 0114d213398..e253f7b575b 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -145,14 +145,14 @@ module FourSlash { testOptMetadataNames.mapRoot, testOptMetadataNames.module, testOptMetadataNames.out, testOptMetadataNames.outDir, testOptMetadataNames.sourceMap, testOptMetadataNames.sourceRoot] - function convertGlobalOptionsToCompilationSettings(globalOptions: { [idx: string]: string }): ts.CompilationSettings { - var settings: ts.CompilationSettings = {}; + function convertGlobalOptionsToCompilerOptions(globalOptions: { [idx: string]: string }): ts.CompilerOptions { + var settings: ts.CompilerOptions = {}; // Convert all property in globalOptions into ts.CompilationSettings for (var prop in globalOptions) { if (globalOptions.hasOwnProperty(prop)) { switch (prop) { case testOptMetadataNames.declaration: - settings.generateDeclarationFiles = true; + settings.declaration = true; break; case testOptMetadataNames.mapRoot: settings.mapRoot = globalOptions[prop]; @@ -161,24 +161,25 @@ module FourSlash { // create appropriate external module target for CompilationSettings switch (globalOptions[prop]) { case "AMD": - settings.moduleGenTarget = ts.ModuleGenTarget.Asynchronous; + settings.module = ts.ModuleKind.AMD; break; case "CommonJS": - settings.moduleGenTarget = ts.ModuleGenTarget.Synchronous; + settings.module = ts.ModuleKind.CommonJS; break; default: - settings.moduleGenTarget = ts.ModuleGenTarget.Unspecified; + ts.Debug.assert(globalOptions[prop] === undefined || globalOptions[prop] === "None"); + settings.module = ts.ModuleKind.None; break; } break; case testOptMetadataNames.out: - settings.outFileOption = globalOptions[prop]; + settings.out = globalOptions[prop]; break; case testOptMetadataNames.outDir: - settings.outDirOption = globalOptions[prop]; + settings.outDir = globalOptions[prop]; break; case testOptMetadataNames.sourceMap: - settings.mapSourceFiles = true; + settings.sourceMap = true; break; case testOptMetadataNames.sourceRoot: settings.sourceRoot = globalOptions[prop]; @@ -300,7 +301,7 @@ module FourSlash { this.cancellationToken = new TestCancellationToken(); this.languageServiceShimHost = new Harness.LanguageService.TypeScriptLS(this.cancellationToken); - var compilationSettings = convertGlobalOptionsToCompilationSettings(this.testData.globalOptions); + var compilationSettings = convertGlobalOptionsToCompilerOptions(this.testData.globalOptions); this.languageServiceShimHost.setCompilationSettings(compilationSettings); var startResolveFileRef: FourSlashFile = undefined; @@ -363,7 +364,7 @@ module FourSlash { this.formatCodeOptions = { IndentSize: 4, TabSize: 4, - NewLineCharacter: sys.newLine, + NewLineCharacter: ts.sys.newLine, ConvertTabsToSpaces: true, InsertSpaceAfterCommaDelimiter: true, InsertSpaceAfterSemicolonInForStatements: true, @@ -750,11 +751,11 @@ module FourSlash { } private getMemberListAtCaret() { - return this.languageService.getCompletionsAtPosition(this.activeFile.fileName, this.currentCaretPosition, true); + return this.languageService.getCompletionsAtPosition(this.activeFile.fileName, this.currentCaretPosition); } private getCompletionListAtCaret() { - return this.languageService.getCompletionsAtPosition(this.activeFile.fileName, this.currentCaretPosition, false); + return this.languageService.getCompletionsAtPosition(this.activeFile.fileName, this.currentCaretPosition); } private getCompletionEntryDetails(entryName: string) { @@ -1364,7 +1365,7 @@ module FourSlash { this.languageService.getSignatureHelpItems(this.activeFile.fileName, offset); } else if (prevChar === ' ' && /A-Za-z_/.test(ch)) { /* Completions */ - this.languageService.getCompletionsAtPosition(this.activeFile.fileName, offset, false); + this.languageService.getCompletionsAtPosition(this.activeFile.fileName, offset); } if (i % errorCadence === 0) { @@ -1747,9 +1748,9 @@ module FourSlash { } function jsonMismatchString() { - return sys.newLine + - "expected: '" + sys.newLine + JSON.stringify(expected, (k,v) => v, 2) + "'" + sys.newLine + - "actual: '" + sys.newLine + JSON.stringify(actual, (k, v) => v, 2) + "'"; + return ts.sys.newLine + + "expected: '" + ts.sys.newLine + JSON.stringify(expected, (k,v) => v, 2) + "'" + ts.sys.newLine + + "actual: '" + ts.sys.newLine + JSON.stringify(actual, (k, v) => v, 2) + "'"; } } @@ -2246,9 +2247,9 @@ module FourSlash { { unitName: fileName, content: content }], (fn, contents) => result = contents, ts.ScriptTarget.Latest, - sys.useCaseSensitiveFileNames); + ts.sys.useCaseSensitiveFileNames); // TODO (drosen): We need to enforce checking on these tests. - var program = ts.createProgram([Harness.Compiler.fourslashFilename, fileName], { out: "fourslashTestOutput.js", noResolve: true }, host); + var program = ts.createProgram([Harness.Compiler.fourslashFilename, fileName], { out: "fourslashTestOutput.js", noResolve: true, target: ts.ScriptTarget.ES3 }, host); var checker = ts.createTypeChecker(program, /*fullTypeCheckMode*/ true); var errors = program.getDiagnostics().concat(checker.getDiagnostics()); diff --git a/src/harness/harness.ts b/src/harness/harness.ts index c0d3ddedce3..5a4837949a5 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -22,10 +22,13 @@ /// /// +declare var require: any; +declare var process: any; + // this will work in the browser via browserify var _chai: typeof chai = require('chai'); var assert: typeof _chai.assert = _chai.assert; -declare var __dirname: any; // Node-specific +declare var __dirname: string; // Node-specific var global = Function("return this").call(null); module Utils { @@ -41,7 +44,7 @@ module Utils { export function getExecutionEnvironment() { if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") { return ExecutionEnvironment.CScript; - } else if (process && (process).execPath && (process).execPath.indexOf("node") !== -1) { + } else if (process && process.execPath && process.execPath.indexOf("node") !== -1) { return ExecutionEnvironment.Node; } else { return ExecutionEnvironment.Browser; @@ -70,14 +73,18 @@ module Utils { } } - /** Splits the given string on \r\n or on only \n if that fails */ + /** Splits the given string on \r\n, or on only \n if that fails, or on only \r if *that* fails. */ export function splitContentByNewlines(content: string) { // Split up the input file by line // Note: IE JS engine incorrectly handles consecutive delimiters here when using RegExp split, so - // we have to string-based splitting instead and try to figure out the delimiting chars + // we have to use string-based splitting instead and try to figure out the delimiting chars var lines = content.split('\r\n'); if (lines.length === 1) { lines = content.split('\n'); + + if (lines.length === 1) { + lines = content.split("\r"); + } } return lines; } @@ -89,7 +96,7 @@ module Utils { } try { - var content = sys.readFile(Harness.userSpecifiedroot + path); + var content = ts.sys.readFile(Harness.userSpecifiedroot + path); } catch (err) { return undefined; @@ -111,6 +118,63 @@ module Utils { } }); } + + export function assertInvariants(node: ts.Node, parent: ts.Node): void { + if (node) { + assert.isFalse(node.pos < 0, "node.pos < 0"); + assert.isFalse(node.end < 0, "node.end < 0"); + assert.isFalse(node.end < node.pos, "node.end < node.pos"); + assert.equal(node.parent, parent, "node.parent !== parent"); + + if (parent) { + // Make sure each child is contained within the parent. + assert.isFalse(node.pos < parent.pos, "node.pos < parent.pos"); + assert.isFalse(node.end > parent.end, "node.end > parent.end"); + } + + ts.forEachChild(node, child => { + assertInvariants(child, node); + }); + + // Make sure each of the children is in order. + var currentPos = 0; + ts.forEachChild(node, + child => { + assert.isFalse(child.pos < currentPos, "child.pos < currentPos"); + currentPos = child.end; + }, + (array: ts.NodeArray) => { + assert.isFalse(array.pos < node.pos, "array.pos < node.pos"); + assert.isFalse(array.end > node.end, "array.end > node.end"); + assert.isFalse(array.pos < currentPos, "array.pos < currentPos"); + + for (var i = 0, n = array.length; i < n; i++) { + assert.isFalse(array[i].pos < currentPos, "array[i].pos < currentPos"); + currentPos = array[i].end + } + + currentPos = array.end; + }); + + var childNodesAndArrays: any[] = []; + ts.forEachChild(node, child => { childNodesAndArrays.push(child) }, array => { childNodesAndArrays.push(array) }); + + for (var childName in node) { + if (childName === "parent" || childName === "nextContainer" || childName === "modifiers" || childName === "externalModuleIndicator") { + continue; + } + var child = (node)[childName]; + if (isNodeOrArray(child)) { + assert.isFalse(childNodesAndArrays.indexOf(child) < 0, + "Missing child when forEach'ing over node: " + (ts).SyntaxKind[node.kind] + "-" + childName); + } + } + } + } + + function isNodeOrArray(a: any): boolean { + return a !== undefined && typeof a.pos === "number"; + } } module Harness.Path { @@ -156,8 +220,8 @@ module Harness { fso = {}; } - export var readFile: typeof IO.readFile = sys.readFile; - export var writeFile: typeof IO.writeFile = sys.writeFile; + export var readFile: typeof IO.readFile = ts.sys.readFile; + export var writeFile: typeof IO.writeFile = ts.sys.writeFile; export var directoryName: typeof IO.directoryName = fso.GetParentFolderName; export var directoryExists: typeof IO.directoryExists = fso.FolderExists; export var fileExists: typeof IO.fileExists = fso.FileExists; @@ -218,8 +282,8 @@ module Harness { fs = pathModule = {}; } - export var readFile: typeof IO.readFile = sys.readFile; - export var writeFile: typeof IO.writeFile = sys.writeFile; + export var readFile: typeof IO.readFile = ts.sys.readFile; + export var writeFile: typeof IO.writeFile = ts.sys.writeFile; export var fileExists: typeof IO.fileExists = fs.existsSync; export var log: typeof IO.log = console.log; @@ -538,8 +602,8 @@ module Harness { } export var defaultLibFileName = 'lib.d.ts'; - export var defaultLibSourceFile = ts.createSourceFile(defaultLibFileName, IO.readFile(libFolder + 'lib.core.d.ts'), /*languageVersion*/ ts.ScriptTarget.Latest, /*version:*/ "0"); - export var defaultES6LibSourceFile = ts.createSourceFile(defaultLibFileName, IO.readFile(libFolder + 'lib.core.es6.d.ts'), /*languageVersion*/ ts.ScriptTarget.Latest, /*version:*/ "0"); + export var defaultLibSourceFile = ts.createSourceFile(defaultLibFileName, IO.readFile(libFolder + 'lib.core.d.ts'), /*languageVersion*/ ts.ScriptTarget.Latest); + export var defaultES6LibSourceFile = ts.createSourceFile(defaultLibFileName, IO.readFile(libFolder + 'lib.core.es6.d.ts'), /*languageVersion*/ ts.ScriptTarget.Latest); // Cache these between executions so we don't have to re-parse them for every test @@ -547,7 +611,7 @@ module Harness { export var fourslashSourceFile: ts.SourceFile; export function getCanonicalFileName(fileName: string): string { - return sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); + return ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); } export function createCompilerHost(inputFiles: { unitName: string; content: string; }[], @@ -565,21 +629,20 @@ module Harness { function register(file: { unitName: string; content: string; }) { if (file.content !== undefined) { var filename = ts.normalizeSlashes(file.unitName); - filemap[getCanonicalFileName(filename)] = ts.createSourceFile(filename, file.content, scriptTarget, /*version:*/ "0"); + filemap[getCanonicalFileName(filename)] = ts.createSourceFile(filename, file.content, scriptTarget); } }; inputFiles.forEach(register); return { - getCurrentDirectory: sys.getCurrentDirectory, - getCancellationToken: (): any => undefined, + getCurrentDirectory: ts.sys.getCurrentDirectory, getSourceFile: (fn, languageVersion) => { if (Object.prototype.hasOwnProperty.call(filemap, getCanonicalFileName(fn))) { return filemap[getCanonicalFileName(fn)]; } else if (fn === fourslashFilename) { var tsFn = 'tests/cases/fourslash/' + fourslashFilename; - fourslashSourceFile = fourslashSourceFile || ts.createSourceFile(tsFn, Harness.IO.readFile(tsFn), scriptTarget, /*version*/ "0", /*isOpen*/ false); + fourslashSourceFile = fourslashSourceFile || ts.createSourceFile(tsFn, Harness.IO.readFile(tsFn), scriptTarget); return fourslashSourceFile; } else { @@ -594,7 +657,7 @@ module Harness { writeFile, getCanonicalFileName, useCaseSensitiveFileNames: () => useCaseSensitiveFileNames, - getNewLine: ()=> sys.newLine + getNewLine: ()=> ts.sys.newLine }; } @@ -664,7 +727,7 @@ module Harness { settingsCallback(null); } - var useCaseSensitiveFileNames = sys.useCaseSensitiveFileNames; + var useCaseSensitiveFileNames = ts.sys.useCaseSensitiveFileNames; this.settings.forEach(setting => { switch (setting.flag.toLowerCase()) { // "filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outdir", "noimplicitany", "noresolve" @@ -742,7 +805,7 @@ module Harness { case 'newline': case 'newlines': - sys.newLine = setting.value; + ts.sys.newLine = setting.value; break; case 'comments': @@ -774,9 +837,19 @@ module Harness { case 'errortruncation': options.noErrorTruncation = setting.value === 'false'; break; + case 'preserveconstenums': options.preserveConstEnums = setting.value === 'true'; break; + + case 'suppressimplicitanyindexerrors': + options.suppressImplicitAnyIndexErrors = setting.value === 'true'; + break; + + case 'includebuiltfile': + inputFiles.push({ unitName: setting.value, content: IO.readFile(libFolder + setting.value)}); + break; + default: throw new Error('Unsupported compiler setting ' + setting.flag); } @@ -786,7 +859,7 @@ module Harness { var register = (file: { unitName: string; content: string; }) => { if (file.content !== undefined) { var filename = ts.normalizeSlashes(file.unitName); - filemap[getCanonicalFileName(filename)] = ts.createSourceFile(filename, file.content, options.target, /*version:*/ "0"); + filemap[getCanonicalFileName(filename)] = ts.createSourceFile(filename, file.content, options.target); } }; inputFiles.forEach(register); @@ -817,11 +890,11 @@ module Harness { }); this.lastErrors = errors; - var result = new CompilerResult(fileOutputs, errors, program, sys.getCurrentDirectory(), emitResult ? emitResult.sourceMaps : undefined); + var result = new CompilerResult(fileOutputs, errors, program, ts.sys.getCurrentDirectory(), emitResult ? emitResult.sourceMaps : undefined); onComplete(result, checker); // reset what newline means in case the last test changed it - sys.newLine = '\r\n'; + ts.sys.newLine = '\r\n'; return options; } @@ -916,7 +989,7 @@ module Harness { errorOutput += diagnotic.filename + "(" + diagnotic.line + "," + diagnotic.character + "): "; } - errorOutput += diagnotic.category + " TS" + diagnotic.code + ": " + diagnotic.message + sys.newLine; + errorOutput += diagnotic.category + " TS" + diagnotic.code + ": " + diagnotic.message + ts.sys.newLine; }); return errorOutput; @@ -963,6 +1036,10 @@ module Harness { var lineStarts = ts.computeLineStarts(inputFile.content); var lines = inputFile.content.split('\n'); + if (lines.length === 1) { + lines = lines[0].split("\r"); + } + lines.forEach((line, lineIndex) => { if (line.length > 0 && line.charAt(line.length - 1) === '\r') { line = line.substr(0, line.length - 1); @@ -1014,7 +1091,7 @@ module Harness { assert.equal(totalErrorsReported + numLibraryDiagnostics, diagnostics.length, 'total number of errors'); return minimalDiagnosticsToString(diagnostics) + - sys.newLine + sys.newLine + outputLines.join('\r\n'); + ts.sys.newLine + ts.sys.newLine + outputLines.join('\r\n'); } export function collateOutputs(outputFiles: Harness.Compiler.GeneratedFile[], clean?: (s: string) => string) { @@ -1162,7 +1239,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", "noemitonerror","noimplicitany", "noresolve", "newline", "newlines", "emitbom", "errortruncation", "usecasesensitivefilenames", "preserveconstenums"]; + var fileMetadataNames = ["filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outdir", "noemitonerror", "noimplicitany", "noresolve", "newline", "newlines", "emitbom", "errortruncation", "usecasesensitivefilenames", "preserveconstenums", "includebuiltfile", "suppressimplicitanyindexerrors"]; function extractCompilerSettings(content: string): CompilerSetting[] { diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index d3082a17ba2..0aa1415cc99 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -111,7 +111,10 @@ module Harness.LanguageService { scriptSnapshot: ts.IScriptSnapshot, version: string, isOpen: boolean): ts.SourceFile { - return ts.createSourceFile(fileName, scriptSnapshot.getText(0, scriptSnapshot.getLength()), compilationSettings.target, version, isOpen); + var sourceFile = ts.createSourceFile(fileName, scriptSnapshot.getText(0, scriptSnapshot.getLength()), compilationSettings.target); + sourceFile.version = version; + sourceFile.isOpen = isOpen; + return sourceFile; } public updateDocument( @@ -134,11 +137,14 @@ module Harness.LanguageService { private ls: ts.LanguageServiceShim = null; private fileNameToScript: ts.Map = {}; - private settings: ts.CompilationSettings = {}; + private settings: ts.CompilerOptions = {}; constructor(private cancellationToken: ts.CancellationToken = CancellationToken.None) { } + public trace(s: string) { + } + public addDefaultLibrary() { this.addScript(Harness.Compiler.defaultLibFileName, Harness.Compiler.defaultLibSourceFile.text); } @@ -245,7 +251,7 @@ module Harness.LanguageService { return this.ls; } - public setCompilationSettings(settings: ts.CompilationSettings) { + public setCompilationSettings(settings: ts.CompilerOptions) { for (var key in settings) { if (settings.hasOwnProperty(key)) { this.settings[key] = settings[key]; @@ -264,7 +270,10 @@ module Harness.LanguageService { /** Parse file given its source text */ public parseSourceText(fileName: string, sourceText: ts.IScriptSnapshot): ts.SourceFile { - return ts.createSourceFile(fileName, sourceText.getText(0, sourceText.getLength()), ts.ScriptTarget.Latest, "1", true); + var result = ts.createSourceFile(fileName, sourceText.getText(0, sourceText.getLength()), ts.ScriptTarget.Latest); + result.version = "1"; + result.isOpen = true; + return result; } /** Parse a file on disk given its fileName */ diff --git a/src/harness/loggedIO.ts b/src/harness/loggedIO.ts index c6305c50c10..c6d15c34a84 100644 --- a/src/harness/loggedIO.ts +++ b/src/harness/loggedIO.ts @@ -91,7 +91,7 @@ module Playback { return run; } - export interface PlaybackSystem extends System, PlaybackControl { } + export interface PlaybackSystem extends ts.System, PlaybackControl { } function createEmptyLog(): IOLog { return { @@ -221,7 +221,7 @@ module Playback { //console.log("Swallowed write operation during replay: " + name); } - export function wrapSystem(underlying: System): PlaybackSystem { + export function wrapSystem(underlying: ts.System): PlaybackSystem { var wrapper: PlaybackSystem = {}; initWrapper(wrapper, underlying); diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts index f46f9ae3698..81791c099d3 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -60,7 +60,7 @@ class ProjectRunner extends RunnerBase { var testCase: ProjectRunnerTestCase; try { - var testFileText = sys.readFile(testCaseFileName); + var testFileText = ts.sys.readFile(testCaseFileName); } catch (e) { assert(false, "Unable to open testcase file: " + testCaseFileName + ": " + e.message); @@ -96,7 +96,7 @@ class ProjectRunner extends RunnerBase { } function cleanProjectUrl(url: string) { - var diskProjectPath = ts.normalizeSlashes(sys.resolvePath(testCase.projectRoot)); + var diskProjectPath = ts.normalizeSlashes(ts.sys.resolvePath(testCase.projectRoot)); var projectRootUrl = "file:///" + diskProjectPath; var normalizedProjectRoot = ts.normalizeSlashes(testCase.projectRoot); diskProjectPath = diskProjectPath.substr(0, diskProjectPath.lastIndexOf(normalizedProjectRoot)); @@ -119,7 +119,7 @@ class ProjectRunner extends RunnerBase { } function getCurrentDirectory() { - return sys.resolvePath(testCase.projectRoot); + return ts.sys.resolvePath(testCase.projectRoot); } function compileProjectFiles(moduleKind: ts.ModuleKind, getInputFiles: ()=> string[], @@ -161,8 +161,8 @@ class ProjectRunner extends RunnerBase { sourceMap: !!testCase.sourceMap, out: testCase.out, outDir: testCase.outDir, - mapRoot: testCase.resolveMapRoot && testCase.mapRoot ? sys.resolvePath(testCase.mapRoot) : testCase.mapRoot, - sourceRoot: testCase.resolveSourceRoot && testCase.sourceRoot ? sys.resolvePath(testCase.sourceRoot) : testCase.sourceRoot, + mapRoot: testCase.resolveMapRoot && testCase.mapRoot ? ts.sys.resolvePath(testCase.mapRoot) : testCase.mapRoot, + sourceRoot: testCase.resolveSourceRoot && testCase.sourceRoot ? ts.sys.resolvePath(testCase.sourceRoot) : testCase.sourceRoot, module: moduleKind, noResolve: testCase.noResolve }; @@ -176,7 +176,7 @@ class ProjectRunner extends RunnerBase { else { var text = getSourceFileText(filename); if (text !== undefined) { - sourceFile = ts.createSourceFile(filename, text, languageVersion, /*version:*/ "0"); + sourceFile = ts.createSourceFile(filename, text, languageVersion); } } @@ -190,8 +190,8 @@ class ProjectRunner extends RunnerBase { writeFile, getCurrentDirectory, getCanonicalFileName: Harness.Compiler.getCanonicalFileName, - useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames, - getNewLine: () => sys.newLine + useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames, + getNewLine: () => ts.sys.newLine }; } } @@ -213,7 +213,7 @@ class ProjectRunner extends RunnerBase { function getSourceFileText(filename: string): string { try { - var text = sys.readFile(ts.isRootedDiskPath(filename) + var text = ts.sys.readFile(ts.isRootedDiskPath(filename) ? filename : ts.normalizeSlashes(testCase.projectRoot) + "/" + ts.normalizeSlashes(filename)); } @@ -260,14 +260,14 @@ class ProjectRunner extends RunnerBase { // Actual writing of file as in tc.ts function ensureDirectoryStructure(directoryname: string) { if (directoryname) { - if (!sys.directoryExists(directoryname)) { + if (!ts.sys.directoryExists(directoryname)) { ensureDirectoryStructure(ts.getDirectoryPath(directoryname)); - sys.createDirectory(directoryname); + ts.sys.createDirectory(directoryname); } } } ensureDirectoryStructure(ts.getDirectoryPath(ts.normalizePath(outputFilePath))); - sys.writeFile(outputFilePath, data, writeByteOrderMark); + ts.sys.writeFile(outputFilePath, data, writeByteOrderMark); outputFiles.push({ emittedFileName: filename, code: data, fileName: diskRelativeName, writeByteOrderMark: writeByteOrderMark }); } @@ -374,7 +374,7 @@ class ProjectRunner extends RunnerBase { it('Baseline of emitted result (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, () => { Harness.Baseline.runBaseline('Baseline of emitted result (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + outputFile.fileName, () => { try { - return sys.readFile(getProjectOutputFolder(outputFile.fileName, compilerResult.moduleKind)); + return ts.sys.readFile(getProjectOutputFolder(outputFile.fileName, compilerResult.moduleKind)); } catch (e) { return undefined; diff --git a/src/harness/runner.ts b/src/harness/runner.ts index da37c02e224..24349ada3fd 100644 --- a/src/harness/runner.ts +++ b/src/harness/runner.ts @@ -94,6 +94,6 @@ if (runners.length === 0) { //runners.push(new GeneratedFourslashRunner()); } -sys.newLine = '\r\n'; +ts.sys.newLine = '\r\n'; runTests(runners); diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts index b8bc2a80a52..8d22b1da1d8 100644 --- a/src/harness/rwcRunner.ts +++ b/src/harness/rwcRunner.ts @@ -6,17 +6,17 @@ module RWC { function runWithIOLog(ioLog: IOLog, fn: () => void) { - var oldSys = sys; + var oldSys = ts.sys; - var wrappedSys = Playback.wrapSystem(sys); + var wrappedSys = Playback.wrapSystem(ts.sys); wrappedSys.startReplayFromData(ioLog); - sys = wrappedSys; + ts.sys = wrappedSys; try { fn(); } finally { wrappedSys.endReplay(); - sys = oldSys; + ts.sys = oldSys; } } @@ -74,7 +74,7 @@ module RWC { } ts.forEach(ioLog.filesRead, fileRead => { - var resolvedPath = ts.normalizeSlashes(sys.resolvePath(fileRead.path)); + var resolvedPath = ts.normalizeSlashes(ts.sys.resolvePath(fileRead.path)); var inInputList = ts.forEach(inputFiles, inputFile=> inputFile.unitName === resolvedPath); if (!inInputList) { // Add the file to other files @@ -92,9 +92,9 @@ module RWC { }); function getHarnessCompilerInputUnit(fileName: string) { - var unitName = ts.normalizeSlashes(sys.resolvePath(fileName)); + var unitName = ts.normalizeSlashes(ts.sys.resolvePath(fileName)); try { - var content = sys.readFile(unitName); + var content = ts.sys.readFile(unitName); } catch (e) { // Leave content undefined. @@ -160,7 +160,7 @@ module RWC { } return Harness.Compiler.minimalDiagnosticsToString(declFileCompilationResult.declResult.errors) + - sys.newLine + sys.newLine + + ts.sys.newLine + ts.sys.newLine + Harness.Compiler.getErrorBaseline(declFileCompilationResult.declInputFiles.concat(declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.errors); }, false, baselineOpts); } diff --git a/src/harness/test262Runner.ts b/src/harness/test262Runner.ts index a29c6ac8619..2b5c2353095 100644 --- a/src/harness/test262Runner.ts +++ b/src/harness/test262Runner.ts @@ -21,81 +21,6 @@ class Test262BaselineRunner extends RunnerBase { return Test262BaselineRunner.basePath + "/" + filename; } - private static checkInvariants(node: ts.Node, parent: ts.Node): void { - if (node) { - if (node.pos < 0) { - throw new Error("node.pos < 0"); - } - if (node.end < 0) { - throw new Error("node.end < 0"); - } - if (node.end < node.pos) { - throw new Error("node.end < node.pos"); - } - if (node.parent !== parent) { - throw new Error("node.parent !== parent"); - } - if (parent) { - // Make sure each child is contained within the parent. - if (node.pos < parent.pos) { - throw new Error("node.pos < parent.pos"); - } - if (node.end > parent.end) { - throw new Error("node.end > parent.end"); - } - } - - ts.forEachChild(node, child => { - Test262BaselineRunner.checkInvariants(child, node); - }); - - // Make sure each of the children is in order. - var currentPos = 0; - ts.forEachChild(node, - child => { - if (child.pos < currentPos) { - throw new Error("child.pos < currentPos"); - } - currentPos = child.end; - }, - (array: ts.NodeArray) => { - if (array.pos < node.pos) { - throw new Error("array.pos < node.pos"); - } - if (array.end > node.end) { - throw new Error("array.end > node.end"); - } - - if (array.pos < currentPos) { - throw new Error("array.pos < currentPos"); - } - for (var i = 0, n = array.length; i < n; i++) { - if (array[i].pos < currentPos) { - throw new Error("array[i].pos < currentPos"); - } - currentPos = array[i].end - } - - currentPos = array.end; - }); - - var childNodesAndArrays: any[] = []; - ts.forEachChild(node, child => { childNodesAndArrays.push(child) }, array => { childNodesAndArrays.push(array) }); - - for (var childName in node) { - if (childName === "parent" || childName === "nextContainer" || childName === "modifiers" || childName === "externalModuleIndicator") { - continue; - } - var child = (node)[childName]; - if (Test262BaselineRunner.isNodeOrArray(child)) { - if (childNodesAndArrays.indexOf(child) < 0) { - throw new Error("Child when forEach'ing over node. " + (ts).SyntaxKind[node.kind] + "-" + childName); - } - } - } - } - } - private static serializeSourceFile(file: ts.SourceFile): string { function getKindName(k: number): string { return (ts).SyntaxKind[k] @@ -126,7 +51,12 @@ class Test262BaselineRunner extends RunnerBase { } function getNodeFlagName(f: number) { return getFlagName((ts).NodeFlags, f); } - function getParserContextFlagName(f: number) { return getFlagName((ts).ParserContextFlags, f); } + function getParserContextFlagName(f: number) { + // Clear the flag that are produced by aggregating child values.. That is ephemeral + // data we don't care about in the dump. We only care what the parser set directly + // on the ast. + return getFlagName((ts).ParserContextFlags, f & ts.ParserContextFlags.ParserGeneratedFlags); + } function convertDiagnostics(diagnostics: ts.Diagnostic[]) { return diagnostics.map(convertDiagnostic); } @@ -143,6 +73,9 @@ class Test262BaselineRunner extends RunnerBase { function serializeNode(n: ts.Node): any { var o: any = { kind: getKindName(n.kind) }; + if (ts.containsParseError(n)) { + o.containsParseError = true; + } ts.forEach(Object.getOwnPropertyNames(n), propertyName => { switch (propertyName) { @@ -264,7 +197,7 @@ class Test262BaselineRunner extends RunnerBase { it('satisfies invariants', () => { var sourceFile = testState.checker.getProgram().getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); - Test262BaselineRunner.checkInvariants(sourceFile, /*parent:*/ undefined); + Utils.assertInvariants(sourceFile, /*parent:*/ undefined); }); it('has the expected AST',() => { diff --git a/src/services/findReferenceHelpers.ts b/src/services/findReferenceHelpers.ts deleted file mode 100644 index 68131a41115..00000000000 --- a/src/services/findReferenceHelpers.ts +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0. -// See LICENSE.txt in the project root for complete license information. - -/// - -module TypeScript.Services { - export class FindReferenceHelpers { - public static compareSymbolsForLexicalIdentity(firstSymbol: TypeScript.PullSymbol, secondSymbol: TypeScript.PullSymbol): boolean { - // Unwrap modules so that we're always referring to the variable. - if (!firstSymbol.isAlias() && firstSymbol.isContainer()) { - var containerForFirstSymbol = (firstSymbol); - if (containerForFirstSymbol.getInstanceSymbol()) { - firstSymbol = containerForFirstSymbol.getInstanceSymbol(); - } - } - - if (!secondSymbol.isAlias() && secondSymbol.isContainer()) { - var containerForSecondSymbol = (secondSymbol); - if (containerForSecondSymbol.getInstanceSymbol()) { - secondSymbol = containerForSecondSymbol.getInstanceSymbol(); - } - } - - if (firstSymbol.kind === secondSymbol.kind) { - if (firstSymbol === secondSymbol) { - return true; - } - - // If we have two variables and they have the same name and the same parent, then - // they are the same symbol. - if (firstSymbol.kind === TypeScript.PullElementKind.Variable && - firstSymbol.name === secondSymbol.name && - firstSymbol.getDeclarations() && firstSymbol.getDeclarations().length >= 1 && - secondSymbol.getDeclarations() && secondSymbol.getDeclarations().length >= 1) { - - var firstSymbolDecl = firstSymbol.getDeclarations()[0]; - var secondSymbolDecl = secondSymbol.getDeclarations()[0]; - - return firstSymbolDecl.getParentDecl() === secondSymbolDecl.getParentDecl(); - } - - // If we have two properties that belong to an object literal, then we need ot see - // if they came from teh same object literal ast. - if (firstSymbol.kind === TypeScript.PullElementKind.Property && - firstSymbol.name === secondSymbol.name && - firstSymbol.getDeclarations() && firstSymbol.getDeclarations().length >= 1 && - secondSymbol.getDeclarations() && secondSymbol.getDeclarations().length >= 1) { - - var firstSymbolDecl = firstSymbol.getDeclarations()[0]; - var secondSymbolDecl = secondSymbol.getDeclarations()[0]; - - var firstParentDecl = firstSymbolDecl.getParentDecl(); - var secondParentDecl = secondSymbolDecl.getParentDecl(); - - if (firstParentDecl.kind === TypeScript.PullElementKind.ObjectLiteral && - secondParentDecl.kind === TypeScript.PullElementKind.ObjectLiteral) { - - return firstParentDecl.ast() === secondParentDecl.ast(); - } - } - - // check if we are dealing with the implementation of interface method or a method override - if (firstSymbol.name === secondSymbol.name) { - // at this point firstSymbol.kind === secondSymbol.kind so we can pick any of those - switch (firstSymbol.kind) { - case PullElementKind.Property: - case PullElementKind.Method: - case PullElementKind.GetAccessor: - case PullElementKind.SetAccessor: - // these kinds can only be defined in types - var t1 = firstSymbol.getContainer(); - var t2 = secondSymbol.getContainer(); - t1._resolveDeclaredSymbol(); - t2._resolveDeclaredSymbol(); - - return t1.hasBase(t2) || t2.hasBase(t1); - break; - } - } - - return false; - } - else { - switch (firstSymbol.kind) { - case TypeScript.PullElementKind.Class: { - return this.checkSymbolsForDeclarationEquality(firstSymbol, secondSymbol); - } - case TypeScript.PullElementKind.Property: { - if (firstSymbol.isAccessor()) { - var getterSymbol = (firstSymbol).getGetter(); - var setterSymbol = (firstSymbol).getSetter(); - - if (getterSymbol && getterSymbol === secondSymbol) { - return true; - } - - if (setterSymbol && setterSymbol === secondSymbol) { - return true; - } - } - return false; - } - case TypeScript.PullElementKind.Function: { - if (secondSymbol.isAccessor()) { - var getterSymbol = (secondSymbol).getGetter(); - var setterSymbol = (secondSymbol).getSetter(); - - if (getterSymbol && getterSymbol === firstSymbol) { - return true; - } - - if (setterSymbol && setterSymbol === firstSymbol) { - return true; - } - } - return false; - } - case TypeScript.PullElementKind.ConstructorMethod: { - return this.checkSymbolsForDeclarationEquality(firstSymbol, secondSymbol); - } - } - } - - return firstSymbol === secondSymbol; - } - - private static checkSymbolsForDeclarationEquality(firstSymbol: TypeScript.PullSymbol, secondSymbol: TypeScript.PullSymbol): boolean { - var firstSymbolDeclarations: TypeScript.PullDecl[] = firstSymbol.getDeclarations(); - var secondSymbolDeclarations: TypeScript.PullDecl[] = secondSymbol.getDeclarations(); - for (var i = 0, iLen = firstSymbolDeclarations.length; i < iLen; i++) { - for (var j = 0, jLen = secondSymbolDeclarations.length; j < jLen; j++) { - if (this.declarationsAreSameOrParents(firstSymbolDeclarations[i], secondSymbolDeclarations[j])) { - return true; - } - } - } - return false; - } - - private static declarationsAreSameOrParents(firstDecl: TypeScript.PullDecl, secondDecl: TypeScript.PullDecl): boolean { - var firstParent: TypeScript.PullDecl = firstDecl.getParentDecl(); - var secondParent: TypeScript.PullDecl = secondDecl.getParentDecl(); - if (firstDecl === secondDecl || - firstDecl === secondParent || - firstParent === secondDecl || - firstParent === secondParent) { - return true; - } - return false; - } - } -} \ No newline at end of file diff --git a/src/services/formatting.ts b/src/services/formatting/formatting.ts similarity index 92% rename from src/services/formatting.ts rename to src/services/formatting/formatting.ts index 0c2dd4c51dc..823a5ff4e00 100644 --- a/src/services/formatting.ts +++ b/src/services/formatting/formatting.ts @@ -1,7 +1,7 @@ -/// -/// -/// -/// +/// +/// +/// +/// module ts.formatting { @@ -622,14 +622,21 @@ module ts.formatting { var tokenStart = sourceFile.getLineAndCharacterFromPosition(currentTokenInfo.token.pos); if (isTokenInRange) { + var rangeHasError = rangeContainsError(currentTokenInfo.token); // save prevStartLine since processRange will overwrite this value with current ones var prevStartLine = previousRangeStartLine; lineAdded = processRange(currentTokenInfo.token, tokenStart, parent, childContextNode, dynamicIndentation); - if (lineAdded !== undefined) { - indentToken = lineAdded; + if (rangeHasError) { + // do not indent comments\token if token range overlaps with some error + indentToken = false; } else { - indentToken = lastTriviaWasNewLine && tokenStart.line !== prevStartLine; + if (lineAdded !== undefined) { + indentToken = lineAdded; + } + else { + indentToken = lastTriviaWasNewLine && tokenStart.line !== prevStartLine; + } } } @@ -984,4 +991,56 @@ module ts.formatting { return SyntaxKind.Unknown; } + + var internedTabsIndentation: string[]; + var internedSpacesIndentation: string[]; + + export function getIndentationString(indentation: number, options: FormatCodeOptions): string { + if (!options.ConvertTabsToSpaces) { + var tabs = Math.floor(indentation / options.TabSize); + var spaces = indentation - tabs * options.TabSize; + + var tabString: string; + if (!internedTabsIndentation) { + internedTabsIndentation = []; + } + + if (internedTabsIndentation[tabs] === undefined) { + internedTabsIndentation[tabs] = tabString = repeat('\t', tabs); + } + else { + tabString = internedTabsIndentation[tabs]; + } + + return spaces ? tabString + repeat(" ", spaces) : tabString; + } + else { + var spacesString: string; + var quotient = Math.floor(indentation / options.IndentSize); + var remainder = indentation % options.IndentSize; + if (!internedSpacesIndentation) { + internedSpacesIndentation = []; + } + + if (internedSpacesIndentation[quotient] === undefined) { + spacesString = repeat(" ", options.IndentSize * quotient); + internedSpacesIndentation[quotient] = spacesString; + } + else { + spacesString = internedSpacesIndentation[quotient]; + } + + + return remainder ? spacesString + repeat(" ", remainder) : spacesString; + } + + function repeat(value: string, count: number): string { + var s = ""; + for (var i = 0; i < count; ++i) { + s += value; + } + + return s; + } + } } \ No newline at end of file diff --git a/src/services/formatting/formattingScanner.ts b/src/services/formatting/formattingScanner.ts index 710881bf80b..7ddfecc17f2 100644 --- a/src/services/formatting/formattingScanner.ts +++ b/src/services/formatting/formattingScanner.ts @@ -1,4 +1,4 @@ -/// +/// /// module ts.formatting { diff --git a/src/services/formatting/references.ts b/src/services/formatting/references.ts index 9f4b7e37436..b421424a61b 100644 --- a/src/services/formatting/references.ts +++ b/src/services/formatting/references.ts @@ -13,7 +13,6 @@ // limitations under the License. // -/// /// /// /// @@ -25,5 +24,4 @@ /// /// /// -/// -/// \ No newline at end of file +/// \ No newline at end of file diff --git a/src/services/smartIndenter.ts b/src/services/formatting/smartIndenter.ts similarity index 97% rename from src/services/smartIndenter.ts rename to src/services/formatting/smartIndenter.ts index cafd92a7551..f6f5031d60e 100644 --- a/src/services/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -1,4 +1,4 @@ -/// +/// module ts.formatting { export module SmartIndenter { @@ -342,6 +342,7 @@ module ts.formatting { case SyntaxKind.VariableDeclaration: case SyntaxKind.ExportAssignment: case SyntaxKind.ReturnStatement: + case SyntaxKind.ConditionalExpression: return true; } return false; diff --git a/src/services/formatting/tokenSpan.ts b/src/services/formatting/tokenSpan.ts deleted file mode 100644 index 1d8173a8227..00000000000 --- a/src/services/formatting/tokenSpan.ts +++ /dev/null @@ -1,24 +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 ts.formatting { - export class TokenSpan extends TextSpan { - constructor(public kind: SyntaxKind, start: number, length: number) { - super(start, length); - } - } -} \ No newline at end of file diff --git a/src/services/outliningElementsCollector.ts b/src/services/outliningElementsCollector.ts index 83eef2f4378..5af69cd3626 100644 --- a/src/services/outliningElementsCollector.ts +++ b/src/services/outliningElementsCollector.ts @@ -14,22 +14,6 @@ // module ts { - - export interface OutliningSpan { - /** - * @param textSpan The span of the document to actually collapse. - * @param hintSpan The span of the document to display when the user hovers over the - * collapsed span. - * @param bannerText The text to display in the editor for the collapsed region. - * @param autoCollapse Whether or not this region should be automatically collapsed when - * the 'Collapse to Definitions' command is invoked. - */ - textSpan: TextSpan; - hintSpan: TextSpan; - bannerText: string; - autoCollapse: boolean; - } - export module OutliningElementsCollector { export function collectElements(sourceFile: SourceFile): OutliningSpan[] { var elements: OutliningSpan[] = []; diff --git a/src/services/services.ts b/src/services/services.ts index 759d2bac2c5..4f9dcaf1051 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -4,16 +4,18 @@ /// /// -/// +/// /// /// -/// /// /// -/// -/// +/// +/// module ts { + + export var servicesVersion = "0.4" + export interface Node { getSourceFile(): SourceFile; getChildCount(sourceFile?: SourceFile): number; @@ -59,6 +61,9 @@ module ts { } export interface SourceFile { + isOpen: boolean; + version: string; + getScriptSnapshot(): IScriptSnapshot; getNamedDeclarations(): Declaration[]; update(scriptSnapshot: IScriptSnapshot, version: string, isOpen: boolean, textChangeRange: TextChangeRange): SourceFile; @@ -862,11 +867,13 @@ module ts { } } - return SourceFileObject.createSourceFileObject(this.filename, scriptSnapshot, this.languageVersion, version, isOpen); + return createLanguageServiceSourceFile(this.filename, scriptSnapshot, this.languageVersion, version, isOpen, /*setNodeParents:*/ true); } - public static createSourceFileObject(filename: string, scriptSnapshot: IScriptSnapshot, languageVersion: ScriptTarget, version: string, isOpen: boolean) { - var newSourceFile = createSourceFile(filename, scriptSnapshot.getText(0, scriptSnapshot.getLength()), languageVersion, version, isOpen); + public static createSourceFileObject(filename: string, scriptSnapshot: IScriptSnapshot, languageVersion: ScriptTarget, version: string, isOpen: boolean, setParentNodes: boolean) { + var newSourceFile = createSourceFile(filename, scriptSnapshot.getText(0, scriptSnapshot.getLength()), languageVersion, setParentNodes); + newSourceFile.version = version; + newSourceFile.isOpen = isOpen; newSourceFile.scriptSnapshot = scriptSnapshot; return newSourceFile; } @@ -874,6 +881,8 @@ module ts { export interface Logger { log(s: string): void; + trace(s: string): void; + error(s: string): void; } // @@ -885,8 +894,8 @@ module ts { getScriptVersion(fileName: string): string; getScriptIsOpen(fileName: string): boolean; getScriptSnapshot(fileName: string): IScriptSnapshot; - getLocalizedDiagnosticMessages(): any; - getCancellationToken(): CancellationToken; + getLocalizedDiagnosticMessages?(): any; + getCancellationToken?(): CancellationToken; getCurrentDirectory(): string; getDefaultLibFilename(options: CompilerOptions): string; } @@ -905,7 +914,7 @@ module ts { getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; - getCompletionsAtPosition(fileName: string, position: number, isMemberCompletion: boolean): CompletionInfo; + getCompletionsAtPosition(fileName: string, position: number): CompletionInfo; getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails; getQuickInfoAtPosition(fileName: string, position: number): QuickInfo; @@ -942,6 +951,301 @@ module ts { dispose(): void; } + export class TextSpan { + private _start: number; + private _length: number; + + /** + * Creates a TextSpan instance beginning with the position Start and having the Length + * specified with length. + */ + constructor(start: number, length: number) { + Debug.assert(start >= 0, "start"); + Debug.assert(length >= 0, "length"); + + this._start = start; + this._length = length; + } + + public toJSON(key: any): any { + return { start: this._start, length: this._length }; + } + + public start(): number { + return this._start; + } + + public length(): number { + return this._length; + } + + public end(): number { + return this._start + this._length; + } + + public isEmpty(): boolean { + return this._length === 0; + } + + /** + * Determines whether the position lies within the span. Returns true if the position is greater than or equal to Start and strictly less + * than End, otherwise false. + * @param position The position to check. + */ + public containsPosition(position: number): boolean { + return position >= this._start && position < this.end(); + } + + /** + * Determines whether span falls completely within this span. Returns true if the specified span falls completely within this span, otherwise false. + * @param span The span to check. + */ + public containsTextSpan(span: TextSpan): boolean { + return span._start >= this._start && span.end() <= this.end(); + } + + /** + * Determines whether the given span overlaps this span. Two spans are considered to overlap + * if they have positions in common and neither is empty. Empty spans do not overlap with any + * other span. Returns true if the spans overlap, false otherwise. + * @param span The span to check. + */ + public overlapsWith(span: TextSpan): boolean { + var overlapStart = Math.max(this._start, span._start); + var overlapEnd = Math.min(this.end(), span.end()); + + return overlapStart < overlapEnd; + } + + /** + * 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 { + var overlapStart = Math.max(this._start, span._start); + var overlapEnd = Math.min(this.end(), span.end()); + + if (overlapStart < overlapEnd) { + return TextSpan.fromBounds(overlapStart, overlapEnd); + } + + return undefined; + } + + /** + * Determines whether span intersects this span. Two spans are considered to + * intersect if they have positions in common or the end of one span + * coincides with the start of the other span. Returns true if the spans intersect, false otherwise. + * @param The span to check. + */ + public intersectsWithTextSpan(span: TextSpan): boolean { + return span._start <= this.end() && span.end() >= this._start; + } + + public intersectsWith(start: number, length: number): boolean { + var end = start + length; + return start <= this.end() && end >= this._start; + } + + /** + * Determines whether the given position intersects this span. + * A position is considered to intersect if it is between the start and + * end positions (inclusive) of this span. Returns true if the position intersects, false otherwise. + * @param position The position to check. + */ + public intersectsWithPosition(position: number): boolean { + return position <= this.end() && position >= this._start; + } + + /** + * 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 { + var intersectStart = Math.max(this._start, span._start); + var intersectEnd = Math.min(this.end(), span.end()); + + if (intersectStart <= intersectEnd) { + return TextSpan.fromBounds(intersectStart, intersectEnd); + } + + return undefined; + } + + /** + * Creates a new TextSpan from the given start and end positions + * as opposed to a position and length. + */ + public static fromBounds(start: number, end: number): TextSpan { + Debug.assert(start >= 0); + Debug.assert(end - start >= 0); + return new TextSpan(start, end - start); + } + } + + export class TextChangeRange { + public static unchanged = new TextChangeRange(new TextSpan(0, 0), 0); + + private _span: TextSpan; + private _newLength: number; + + /** + * Initializes a new instance of TextChangeRange. + */ + constructor(span: TextSpan, newLength: number) { + Debug.assert(newLength >= 0, "newLength"); + + this._span = span; + this._newLength = newLength; + } + + /** + * The span of text before the edit which is being changed + */ + public span(): TextSpan { + return this._span; + } + + /** + * Width of the span after the edit. A 0 here would represent a delete + */ + public newLength(): number { + return this._newLength; + } + + public newSpan(): TextSpan { + return new TextSpan(this.span().start(), this.newLength()); + } + + public isUnchanged(): boolean { + return this.span().isEmpty() && this.newLength() === 0; + } + + /** + * Called to merge all the changes that occurred across several versions of a script snapshot + * into a single change. i.e. if a user keeps making successive edits to a script we will + * have a text change from V1 to V2, V2 to V3, ..., Vn. + * + * This function will then merge those changes into a single change range valid between V1 and + * Vn. + */ + public static collapseChangesAcrossMultipleVersions(changes: TextChangeRange[]): TextChangeRange { + if (changes.length === 0) { + return TextChangeRange.unchanged; + } + + if (changes.length === 1) { + return changes[0]; + } + + // We change from talking about { { oldStart, oldLength }, newLength } to { oldStart, oldEnd, newEnd } + // as it makes things much easier to reason about. + var change0 = changes[0]; + + var oldStartN = change0.span().start(); + var oldEndN = change0.span().end(); + var newEndN = oldStartN + change0.newLength(); + + for (var i = 1; i < changes.length; i++) { + var nextChange = changes[i]; + + // Consider the following case: + // i.e. two edits. The first represents the text change range { { 10, 50 }, 30 }. i.e. The span starting + // at 10, with length 50 is reduced to length 30. The second represents the text change range { { 30, 30 }, 40 }. + // i.e. the span starting at 30 with length 30 is increased to length 40. + // + // 0 10 20 30 40 50 60 70 80 90 100 + // ------------------------------------------------------------------------------------------------------- + // | / + // | /---- + // T1 | /---- + // | /---- + // | /---- + // ------------------------------------------------------------------------------------------------------- + // | \ + // | \ + // T2 | \ + // | \ + // | \ + // ------------------------------------------------------------------------------------------------------- + // + // Merging these turns out to not be too difficult. First, determining the new start of the change is trivial + // it's just the min of the old and new starts. i.e.: + // + // 0 10 20 30 40 50 60 70 80 90 100 + // ------------------------------------------------------------*------------------------------------------ + // | / + // | /---- + // T1 | /---- + // | /---- + // | /---- + // ----------------------------------------$-------------------$------------------------------------------ + // . | \ + // . | \ + // T2 . | \ + // . | \ + // . | \ + // ----------------------------------------------------------------------*-------------------------------- + // + // (Note the dots represent the newly inferrred start. + // Determining the new and old end is also pretty simple. Basically it boils down to paying attention to the + // absolute positions at the asterixes, and the relative change between the dollar signs. Basically, we see + // which if the two $'s precedes the other, and we move that one forward until they line up. in this case that + // means: + // + // 0 10 20 30 40 50 60 70 80 90 100 + // --------------------------------------------------------------------------------*---------------------- + // | / + // | /---- + // T1 | /---- + // | /---- + // | /---- + // ------------------------------------------------------------$------------------------------------------ + // . | \ + // . | \ + // T2 . | \ + // . | \ + // . | \ + // ----------------------------------------------------------------------*-------------------------------- + // + // In other words (in this case), we're recognizing that the second edit happened after where the first edit + // ended with a delta of 20 characters (60 - 40). Thus, if we go back in time to where the first edit started + // that's the same as if we started at char 80 instead of 60. + // + // As it so happens, the same logic applies if the second edit precedes the first edit. In that case rahter + // than pusing the first edit forward to match the second, we'll push the second edit forward to match the + // first. + // + // In this case that means we have { oldStart: 10, oldEnd: 80, newEnd: 70 } or, in TextChangeRange + // semantics: { { start: 10, length: 70 }, newLength: 60 } + // + // The math then works out as follows. + // If we have { oldStart1, oldEnd1, newEnd1 } and { oldStart2, oldEnd2, newEnd2 } then we can compute the + // final result like so: + // + // { + // oldStart3: Min(oldStart1, oldStart2), + // oldEnd3 : Max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1)), + // newEnd3 : Max(newEnd2, newEnd2 + (newEnd1 - oldEnd2)) + // } + + var oldStart1 = oldStartN; + var oldEnd1 = oldEndN; + var newEnd1 = newEndN; + + var oldStart2 = nextChange.span().start(); + var oldEnd2 = nextChange.span().end(); + var newEnd2 = oldStart2 + nextChange.newLength(); + + oldStartN = Math.min(oldStart1, oldStart2); + oldEndN = Math.max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1)); + newEndN = Math.max(newEnd2, newEnd2 + (newEnd1 - oldEnd2)); + } + + return new TextChangeRange(TextSpan.fromBounds(oldStartN, oldEndN), /*newLength: */newEndN - oldStartN); + } + } + export interface ClassifiedSpan { textSpan: TextSpan; classificationType: string; // ClassificationTypeNames @@ -1124,6 +1428,23 @@ module ts { documentation: SymbolDisplayPart[]; } + export interface OutliningSpan { + /** The span of the document to actually collapse. */ + textSpan: TextSpan; + + /** The span of the document to display when the user hovers over the collapsed span. */ + hintSpan: TextSpan; + + /** The text to display in the editor for the collapsed region. */ + bannerText: string; + + /** + * Whether or not this region should be automatically collapsed when + * the 'Collapse to Definitions' command is invoked. + */ + autoCollapse: boolean; + } + export interface EmitOutput { outputFiles: OutputFile[]; emitOutputStatus: EmitReturnStatus; @@ -1341,6 +1662,10 @@ module ts { owners: string[]; } + export interface DisplayPartsSymbolWriter extends SymbolWriter { + displayParts(): SymbolDisplayPart[]; + } + export function displayPartsToString(displayParts: SymbolDisplayPart[]) { if (displayParts) { return map(displayParts, displayPart => displayPart.text).join(""); @@ -1349,100 +1674,6 @@ module ts { return ""; } - export interface DisplayPartsSymbolWriter extends SymbolWriter { - displayParts(): SymbolDisplayPart[]; - } - - var displayPartWriter = getDisplayPartWriter(); - function getDisplayPartWriter(): DisplayPartsSymbolWriter { - var displayParts: SymbolDisplayPart[]; - var lineStart: boolean; - var indent: number; - - resetWriter(); - return { - displayParts: () => displayParts, - writeKeyword: text => writeKind(text, SymbolDisplayPartKind.keyword), - writeOperator: text => writeKind(text, SymbolDisplayPartKind.operator), - writePunctuation: text => writeKind(text, SymbolDisplayPartKind.punctuation), - writeSpace: text => writeKind(text, SymbolDisplayPartKind.space), - writeStringLiteral: text => writeKind(text, SymbolDisplayPartKind.stringLiteral), - writeParameter: text => writeKind(text, SymbolDisplayPartKind.parameterName), - writeSymbol, - writeLine, - increaseIndent: () => { indent++; }, - decreaseIndent: () => { indent--; }, - clear: resetWriter, - trackSymbol: () => { } - }; - - function writeIndent() { - if (lineStart) { - var indentString = getIndentString(indent); - if (indentString) { - displayParts.push(displayPart(indentString, SymbolDisplayPartKind.space)); - } - lineStart = false; - } - } - - function writeKind(text: string, kind: SymbolDisplayPartKind) { - writeIndent(); - displayParts.push(displayPart(text, kind)); - } - - function writeSymbol(text: string, symbol: Symbol) { - writeIndent(); - displayParts.push(symbolPart(text, symbol)); - } - - function writeLine() { - displayParts.push(lineBreakPart()); - lineStart = true; - } - - function resetWriter() { - displayParts = [] - lineStart = true; - indent = 0; - } - } - - function displayPart(text: string, kind: SymbolDisplayPartKind, symbol?: Symbol): SymbolDisplayPart { - return { - text: text, - kind: SymbolDisplayPartKind[kind] - }; - } - - export function spacePart() { - return displayPart(" ", SymbolDisplayPartKind.space); - } - - export function keywordPart(kind: SyntaxKind) { - return displayPart(tokenToString(kind), SymbolDisplayPartKind.keyword); - } - - export function punctuationPart(kind: SyntaxKind) { - return displayPart(tokenToString(kind), SymbolDisplayPartKind.punctuation); - } - - export function operatorPart(kind: SyntaxKind) { - return displayPart(tokenToString(kind), SymbolDisplayPartKind.operator); - } - - export function textPart(text: string) { - return displayPart(text, SymbolDisplayPartKind.text); - } - - export function lineBreakPart() { - return displayPart("\n", SymbolDisplayPartKind.lineBreak); - } - - function isFirstDeclarationOfSymbolParameter(symbol: Symbol) { - return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === SyntaxKind.Parameter; - } - function isLocalVariableOrFunction(symbol: Symbol) { if (symbol.parent) { return false; // This is exported symbol @@ -1471,59 +1702,6 @@ module ts { }); } - export function symbolPart(text: string, symbol: Symbol) { - return displayPart(text, displayPartKind(symbol), symbol); - - function displayPartKind(symbol: Symbol): SymbolDisplayPartKind { - var flags = symbol.flags; - - if (flags & SymbolFlags.Variable) { - return isFirstDeclarationOfSymbolParameter(symbol) ? SymbolDisplayPartKind.parameterName : SymbolDisplayPartKind.localName; - } - else if (flags & SymbolFlags.Property) { return SymbolDisplayPartKind.propertyName; } - else if (flags & SymbolFlags.GetAccessor) { return SymbolDisplayPartKind.propertyName; } - else if (flags & SymbolFlags.SetAccessor) { return SymbolDisplayPartKind.propertyName; } - else if (flags & SymbolFlags.EnumMember) { return SymbolDisplayPartKind.enumMemberName; } - else if (flags & SymbolFlags.Function) { return SymbolDisplayPartKind.functionName; } - else if (flags & SymbolFlags.Class) { return SymbolDisplayPartKind.className; } - else if (flags & SymbolFlags.Interface) { return SymbolDisplayPartKind.interfaceName; } - else if (flags & SymbolFlags.Enum) { return SymbolDisplayPartKind.enumName; } - else if (flags & SymbolFlags.Module) { return SymbolDisplayPartKind.moduleName; } - else if (flags & SymbolFlags.Method) { return SymbolDisplayPartKind.methodName; } - else if (flags & SymbolFlags.TypeParameter) { return SymbolDisplayPartKind.typeParameterName; } - else if (flags & SymbolFlags.TypeAlias) { return SymbolDisplayPartKind.aliasName; } - else if (flags & SymbolFlags.Import) { return SymbolDisplayPartKind.aliasName; } - - - return SymbolDisplayPartKind.text; - } - } - - export function mapToDisplayParts(writeDisplayParts: (writer: DisplayPartsSymbolWriter) => void): SymbolDisplayPart[] { - writeDisplayParts(displayPartWriter); - var result = displayPartWriter.displayParts(); - displayPartWriter.clear(); - return result; - } - - export function typeToDisplayParts(typechecker: TypeChecker, type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] { - return mapToDisplayParts(writer => { - typechecker.getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags); - }); - } - - export function symbolToDisplayParts(typeChecker: TypeChecker, symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): SymbolDisplayPart[] { - return mapToDisplayParts(writer => { - typeChecker.getSymbolDisplayBuilder().buildSymbolDisplay(symbol, writer, enclosingDeclaration, meaning, flags); - }); - } - - function signatureToDisplayParts(typechecker: TypeChecker, signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[]{ - return mapToDisplayParts(writer => { - typechecker.getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags); - }); - } - export function getDefaultCompilerOptions(): CompilerOptions { // Set "ScriptTarget.Latest" target by default for language service return { @@ -1532,20 +1710,6 @@ module ts { }; } - export function compareDataObjects(dst: any, src: any): boolean { - for (var e in dst) { - if (typeof dst[e] === "object") { - if (!compareDataObjects(dst[e], src[e])) - return false; - } - else if (typeof dst[e] !== "function") { - if (dst[e] !== src[e]) - return false; - } - } - return true; - } - export class OperationCanceledException { } export class CancellationTokenObject { @@ -1674,11 +1838,10 @@ module ts { var scriptSnapshot = this.hostCache.getScriptSnapshot(filename); var start = new Date().getTime(); - sourceFile = createSourceFileFromScriptSnapshot(filename, scriptSnapshot, getDefaultCompilerOptions(), version, /*isOpen*/ true); + sourceFile = createLanguageServiceSourceFile(filename, scriptSnapshot, getDefaultCompilerOptions().target, version, /*isOpen*/ true, /*setNodeParents:*/ true); this.host.log("SyntaxTreeCache.Initialize: createSourceFile: " + (new Date().getTime() - start)); var start = new Date().getTime(); - fixupParentReferences(sourceFile); this.host.log("SyntaxTreeCache.Initialize: fixupParentRefs : " + (new Date().getTime() - start)); } else if (this.currentFileVersion !== version) { @@ -1688,12 +1851,11 @@ module ts { var start = new Date().getTime(); sourceFile = !editRange - ? createSourceFileFromScriptSnapshot(filename, scriptSnapshot, getDefaultCompilerOptions(), version, /*isOpen*/ true) + ? createLanguageServiceSourceFile(filename, scriptSnapshot, getDefaultCompilerOptions().target, version, /*isOpen*/ true, /*setNodeParents:*/ true) : this.currentSourceFile.update(scriptSnapshot, version, /*isOpen*/ true, editRange); this.host.log("SyntaxTreeCache.Initialize: updateSourceFile: " + (new Date().getTime() - start)); var start = new Date().getTime(); - fixupParentReferences(sourceFile); this.host.log("SyntaxTreeCache.Initialize: fixupParentRefs : " + (new Date().getTime() - start)); } @@ -1703,22 +1865,6 @@ module ts { this.currentFilename = filename; this.currentSourceFile = sourceFile; } - - function fixupParentReferences(sourceFile: SourceFile) { - // normally parent references are set during binding. - // however here SourceFile data is used only for syntactic features so running the whole binding process is an overhead. - // walk over the nodes and set parent references - var parent: Node = sourceFile; - function walk(n: Node): void { - n.parent = parent; - - var saveParent = parent; - parent = n; - forEachChild(n, walk); - parent = saveParent; - } - forEachChild(sourceFile, walk); - } } public getCurrentSourceFile(filename: string): SourceFile { @@ -1731,8 +1877,8 @@ module ts { } } - function createSourceFileFromScriptSnapshot(filename: string, scriptSnapshot: IScriptSnapshot, settings: CompilerOptions, version: string, isOpen: boolean) { - return SourceFileObject.createSourceFileObject(filename, scriptSnapshot, settings.target, version, isOpen); + export function createLanguageServiceSourceFile(filename: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, isOpen: boolean, setNodeParents: boolean): SourceFile { + return SourceFileObject.createSourceFileObject(filename, scriptSnapshot, scriptTarget, version, isOpen, setNodeParents); } export function createDocumentRegistry(): DocumentRegistry { @@ -1782,7 +1928,7 @@ module ts { var bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true); var entry = lookUp(bucket, filename); if (!entry) { - var sourceFile = createSourceFileFromScriptSnapshot(filename, scriptSnapshot, compilationSettings, version, isOpen); + var sourceFile = createLanguageServiceSourceFile(filename, scriptSnapshot, compilationSettings.target, version, isOpen, /*setNodeParents:*/ false); bucket[filename] = entry = { sourceFile: sourceFile, @@ -1902,20 +2048,6 @@ module ts { } /// Helpers - export function getNodeModifiers(node: Node): string { - var flags = node.flags; - var result: string[] = []; - - if (flags & NodeFlags.Private) result.push(ScriptElementKindModifier.privateMemberModifier); - if (flags & NodeFlags.Protected) result.push(ScriptElementKindModifier.protectedMemberModifier); - if (flags & NodeFlags.Public) result.push(ScriptElementKindModifier.publicMemberModifier); - if (flags & NodeFlags.Static) result.push(ScriptElementKindModifier.staticModifier); - if (flags & NodeFlags.Export) result.push(ScriptElementKindModifier.exportedModifier); - if (isInAmbientContext(node)) result.push(ScriptElementKindModifier.ambientModifier); - - return result.length > 0 ? result.join(',') : ScriptElementKindModifier.none; - } - function getTargetLabel(referenceNode: Node, labelName: string): Identifier { while (referenceNode) { if (referenceNode.kind === SyntaxKind.LabeledStatement && (referenceNode).label.text === labelName) { @@ -2095,12 +2227,12 @@ module ts { var useCaseSensitivefilenames = false; var sourceFilesByName: Map = {}; var documentRegistry = documentRegistry; - var cancellationToken = new CancellationTokenObject(host.getCancellationToken()); + var cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken()); var activeCompletionSession: CompletionSession; // The current active completion session, used to get the completion entry details var writer: (filename: string, data: string, writeByteOrderMark: boolean) => void = undefined; // Check if the localized messages json is set, otherwise query the host for it - if (!localizedDiagnosticMessages) { + if (!localizedDiagnosticMessages && host.getLocalizedDiagnosticMessages) { localizedDiagnosticMessages = host.getLocalizedDiagnosticMessages(); } @@ -2366,7 +2498,7 @@ module ts { }; } - function getCompletionsAtPosition(filename: string, position: number, isMemberCompletion: boolean) { + function getCompletionsAtPosition(filename: string, position: number) { synchronizeHostData(); filename = normalizeSlashes(filename); @@ -2441,7 +2573,7 @@ module ts { if (isRightOfDot) { // Right of dot member completion list var symbols: Symbol[] = []; - isMemberCompletion = true; + var isMemberCompletion = true; if (node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName || node.kind === SyntaxKind.PropertyAccessExpression) { var symbol = typeInfoResolver.getSymbolAtLocation(node); @@ -5788,6 +5920,7 @@ module ts { return TokenClass.StringLiteral; case SyntaxKind.RegularExpressionLiteral: return TokenClass.RegExpLiteral; + case SyntaxKind.ConflictMarkerTrivia: case SyntaxKind.MultiLineCommentTrivia: case SyntaxKind.SingleLineCommentTrivia: return TokenClass.Comment; diff --git a/src/services/shims.ts b/src/services/shims.ts index 5556743830f..8fce67025fb 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -88,7 +88,7 @@ module ts { getSyntacticClassifications(fileName: string, start: number, length: number): string; - getCompletionsAtPosition(fileName: string, position: number, isMemberCompletion: boolean): string; + getCompletionsAtPosition(fileName: string, position: number): string; getCompletionEntryDetails(fileName: string, position: number, entryName: string): string; getQuickInfoAtPosition(fileName: string, position: number): string; @@ -169,131 +169,6 @@ module ts { getDefaultCompilationSettings(): string; } - /// TODO: delete this, it is only needed until the VS interface is updated - export const enum LanguageVersion { - EcmaScript3 = 0, - EcmaScript5 = 1, - EcmaScript6 = 2, - } - - export const enum ModuleGenTarget { - Unspecified = 0, - Synchronous = 1, - Asynchronous = 2, - } - - export interface CompilationSettings { - propagateEnumConstants?: boolean; - removeComments?: boolean; - watch?: boolean; - noResolve?: boolean; - allowAutomaticSemicolonInsertion?: boolean; - noImplicitAny?: boolean; - noLib?: boolean; - codeGenTarget?: LanguageVersion; - moduleGenTarget?: ModuleGenTarget; - outFileOption?: string; - outDirOption?: string; - mapSourceFiles?: boolean; - mapRoot?: string; - sourceRoot?: string; - generateDeclarationFiles?: boolean; - useCaseSensitiveFileResolution?: boolean; - gatherDiagnostics?: boolean; - codepage?: number; - emitBOM?: boolean; - - // Declare indexer signature - [index: string]: any; - } - - function languageVersionToScriptTarget(languageVersion: LanguageVersion): ScriptTarget { - if (typeof languageVersion === "undefined") return undefined; - - switch (languageVersion) { - case LanguageVersion.EcmaScript3: return ScriptTarget.ES3 - case LanguageVersion.EcmaScript5: return ScriptTarget.ES5; - case LanguageVersion.EcmaScript6: return ScriptTarget.ES6; - default: throw Error("unsupported LanguageVersion value: " + languageVersion); - } - } - - function moduleGenTargetToModuleKind(moduleGenTarget: ModuleGenTarget): ModuleKind { - if (typeof moduleGenTarget === "undefined") return undefined; - - switch (moduleGenTarget) { - case ModuleGenTarget.Asynchronous: return ModuleKind.AMD; - case ModuleGenTarget.Synchronous: return ModuleKind.CommonJS; - case ModuleGenTarget.Unspecified: return ModuleKind.None; - default: throw Error("unsupported ModuleGenTarget value: " + moduleGenTarget); - } - } - - function scriptTargetTolanguageVersion(scriptTarget: ScriptTarget): LanguageVersion { - if (typeof scriptTarget === "undefined") return undefined; - - switch (scriptTarget) { - case ScriptTarget.ES3: return LanguageVersion.EcmaScript3; - case ScriptTarget.ES5: return LanguageVersion.EcmaScript5; - case ScriptTarget.ES6: return LanguageVersion.EcmaScript6; - default: throw Error("unsupported ScriptTarget value: " + scriptTarget); - } - } - - function moduleKindToModuleGenTarget(moduleKind: ModuleKind): ModuleGenTarget { - if (typeof moduleKind === "undefined") return undefined; - - switch (moduleKind) { - case ModuleKind.AMD: return ModuleGenTarget.Asynchronous; - case ModuleKind.CommonJS: return ModuleGenTarget.Synchronous; - case ModuleKind.None: return ModuleGenTarget.Unspecified; - default: throw Error("unsupported ModuleKind value: " + moduleKind); - } - } - - function compilationSettingsToCompilerOptions(settings: CompilationSettings): CompilerOptions { - // TODO: we should not be converting, but use options all the way - var options: CompilerOptions = {}; - //options.propagateEnumConstants = settings.propagateEnumConstants; - options.removeComments = settings.removeComments; - options.noResolve = settings.noResolve; - options.noImplicitAny = settings.noImplicitAny; - options.noLib = settings.noLib; - options.target = languageVersionToScriptTarget(settings.codeGenTarget); - options.module = moduleGenTargetToModuleKind(settings.moduleGenTarget); - options.out = settings.outFileOption; - options.outDir = settings.outDirOption; - options.sourceMap = settings.mapSourceFiles; - options.mapRoot = settings.mapRoot; - options.sourceRoot = settings.sourceRoot; - options.declaration = settings.generateDeclarationFiles; - //options.useCaseSensitiveFileResolution = settings.useCaseSensitiveFileResolution; - options.codepage = settings.codepage; - options.emitBOM = settings.emitBOM; - return options; - } - - function compilerOptionsToCompilationSettings(options: CompilerOptions): CompilationSettings { - var settings: CompilationSettings = {}; - //options.propagateEnumConstants = settings.propagateEnumConstants; - settings.removeComments = options.removeComments; - settings.noResolve = options.noResolve; - settings.noImplicitAny = options.noImplicitAny; - settings.noLib = options.noLib; - settings.codeGenTarget = scriptTargetTolanguageVersion(options.target); - settings.moduleGenTarget = moduleKindToModuleGenTarget(options.module); - settings.outFileOption = options.out; - settings.outDirOption = options.outDir; - settings.mapSourceFiles = options.sourceMap; - settings.mapRoot = options.mapRoot; - settings.sourceRoot = options.sourceRoot; - settings.generateDeclarationFiles = options.declaration; - // settings.useCaseSensitiveFileResolution = options.useCaseSensitiveFileResolution; - settings.codepage = options.codepage; - settings.emitBOM = options.emitBOM; - return settings; - } - function logInternalError(logger: Logger, err: Error) { logger.log("*INTERNAL ERROR* - Exception in typescript services: " + err.message); } @@ -341,15 +216,21 @@ module ts { this.shimHost.log(s); } + public trace(s: string): void { + this.shimHost.trace(s); + } + + public error(s: string): void { + this.shimHost.error(s); + } + public getCompilationSettings(): CompilerOptions { var settingsJson = this.shimHost.getCompilationSettings(); if (settingsJson == null || settingsJson == "") { throw Error("LanguageServiceShimHostAdapter.getCompilationSettings: empty compilationSettings"); return null; } - var options = compilationSettingsToCompilerOptions(JSON.parse(settingsJson)); - - return options; + return JSON.parse(settingsJson); } public getScriptFileNames(): string[] { @@ -686,11 +567,11 @@ module ts { * to provide at the given source position and providing a member completion * list if requested. */ - public getCompletionsAtPosition(fileName: string, position: number, isMemberCompletion: boolean) { + public getCompletionsAtPosition(fileName: string, position: number) { return this.forwardJSONCall( - "getCompletionsAtPosition('" + fileName + "', " + position + ", " + isMemberCompletion + ")", + "getCompletionsAtPosition('" + fileName + "', " + position + ")", () => { - var completion = this.languageService.getCompletionsAtPosition(fileName, position, isMemberCompletion); + var completion = this.languageService.getCompletionsAtPosition(fileName, position); return completion; }); } @@ -850,7 +731,7 @@ module ts { return this.forwardJSONCall( "getDefaultCompilationSettings()", () => { - return compilerOptionsToCompilationSettings(getDefaultCompilerOptions()); + return getDefaultCompilerOptions(); }); } } @@ -859,6 +740,13 @@ module ts { private _shims: Shim[] = []; private documentRegistry: DocumentRegistry = createDocumentRegistry(); + /* + * Returns script API version. + */ + public getServicesVersion(): string { + return servicesVersion; + } + public createLanguageServiceShim(host: LanguageServiceShimHost): LanguageServiceShim { try { var hostAdapter = new LanguageServiceShimHostAdapter(host); diff --git a/src/services/text.ts b/src/services/text.ts deleted file mode 100644 index fd768785dea..00000000000 --- a/src/services/text.ts +++ /dev/null @@ -1,296 +0,0 @@ -module ts { - export class TextSpan { - private _start: number; - private _length: number; - - /** - * Creates a TextSpan instance beginning with the position Start and having the Length - * specified with length. - */ - constructor(start: number, length: number) { - Debug.assert(start >= 0, "start"); - Debug.assert(length >= 0, "length"); - - this._start = start; - this._length = length; - } - - public toJSON(key: any): any { - return { start: this._start, length: this._length }; - } - - public start(): number { - return this._start; - } - - public length(): number { - return this._length; - } - - public end(): number { - return this._start + this._length; - } - - public isEmpty(): boolean { - return this._length === 0; - } - - /** - * Determines whether the position lies within the span. Returns true if the position is greater than or equal to Start and strictly less - * than End, otherwise false. - * @param position The position to check. - */ - public containsPosition(position: number): boolean { - return position >= this._start && position < this.end(); - } - - /** - * Determines whether span falls completely within this span. Returns true if the specified span falls completely within this span, otherwise false. - * @param span The span to check. - */ - public containsTextSpan(span: TextSpan): boolean { - return span._start >= this._start && span.end() <= this.end(); - } - - /** - * Determines whether the given span overlaps this span. Two spans are considered to overlap - * if they have positions in common and neither is empty. Empty spans do not overlap with any - * other span. Returns true if the spans overlap, false otherwise. - * @param span The span to check. - */ - public overlapsWith(span: TextSpan): boolean { - var overlapStart = Math.max(this._start, span._start); - var overlapEnd = Math.min(this.end(), span.end()); - - return overlapStart < overlapEnd; - } - - /** - * 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 { - var overlapStart = Math.max(this._start, span._start); - var overlapEnd = Math.min(this.end(), span.end()); - - if (overlapStart < overlapEnd) { - return TextSpan.fromBounds(overlapStart, overlapEnd); - } - - return undefined; - } - - /** - * Determines whether span intersects this span. Two spans are considered to - * intersect if they have positions in common or the end of one span - * coincides with the start of the other span. Returns true if the spans intersect, false otherwise. - * @param The span to check. - */ - public intersectsWithTextSpan(span: TextSpan): boolean { - return span._start <= this.end() && span.end() >= this._start; - } - - public intersectsWith(start: number, length: number): boolean { - var end = start + length; - return start <= this.end() && end >= this._start; - } - - /** - * Determines whether the given position intersects this span. - * A position is considered to intersect if it is between the start and - * end positions (inclusive) of this span. Returns true if the position intersects, false otherwise. - * @param position The position to check. - */ - public intersectsWithPosition(position: number): boolean { - return position <= this.end() && position >= this._start; - } - - /** - * 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 { - var intersectStart = Math.max(this._start, span._start); - var intersectEnd = Math.min(this.end(), span.end()); - - if (intersectStart <= intersectEnd) { - return TextSpan.fromBounds(intersectStart, intersectEnd); - } - - return undefined; - } - - /** - * Creates a new TextSpan from the given start and end positions - * as opposed to a position and length. - */ - public static fromBounds(start: number, end: number): TextSpan { - Debug.assert(start >= 0); - Debug.assert(end - start >= 0); - return new TextSpan(start, end - start); - } - } - - export class TextChangeRange { - public static unchanged = new TextChangeRange(new TextSpan(0, 0), 0); - - private _span: TextSpan; - private _newLength: number; - - /** - * Initializes a new instance of TextChangeRange. - */ - constructor(span: TextSpan, newLength: number) { - Debug.assert(newLength >= 0, "newLength"); - - this._span = span; - this._newLength = newLength; - } - - /** - * The span of text before the edit which is being changed - */ - public span(): TextSpan { - return this._span; - } - - /** - * Width of the span after the edit. A 0 here would represent a delete - */ - public newLength(): number { - return this._newLength; - } - - public newSpan(): TextSpan { - return new TextSpan(this.span().start(), this.newLength()); - } - - public isUnchanged(): boolean { - return this.span().isEmpty() && this.newLength() === 0; - } - - /** - * Called to merge all the changes that occurred across several versions of a script snapshot - * into a single change. i.e. if a user keeps making successive edits to a script we will - * have a text change from V1 to V2, V2 to V3, ..., Vn. - * - * This function will then merge those changes into a single change range valid between V1 and - * Vn. - */ - public static collapseChangesAcrossMultipleVersions(changes: TextChangeRange[]): TextChangeRange { - if (changes.length === 0) { - return TextChangeRange.unchanged; - } - - if (changes.length === 1) { - return changes[0]; - } - - // We change from talking about { { oldStart, oldLength }, newLength } to { oldStart, oldEnd, newEnd } - // as it makes things much easier to reason about. - var change0 = changes[0]; - - var oldStartN = change0.span().start(); - var oldEndN = change0.span().end(); - var newEndN = oldStartN + change0.newLength(); - - for (var i = 1; i < changes.length; i++) { - var nextChange = changes[i]; - - // Consider the following case: - // i.e. two edits. The first represents the text change range { { 10, 50 }, 30 }. i.e. The span starting - // at 10, with length 50 is reduced to length 30. The second represents the text change range { { 30, 30 }, 40 }. - // i.e. the span starting at 30 with length 30 is increased to length 40. - // - // 0 10 20 30 40 50 60 70 80 90 100 - // ------------------------------------------------------------------------------------------------------- - // | / - // | /---- - // T1 | /---- - // | /---- - // | /---- - // ------------------------------------------------------------------------------------------------------- - // | \ - // | \ - // T2 | \ - // | \ - // | \ - // ------------------------------------------------------------------------------------------------------- - // - // Merging these turns out to not be too difficult. First, determining the new start of the change is trivial - // it's just the min of the old and new starts. i.e.: - // - // 0 10 20 30 40 50 60 70 80 90 100 - // ------------------------------------------------------------*------------------------------------------ - // | / - // | /---- - // T1 | /---- - // | /---- - // | /---- - // ----------------------------------------$-------------------$------------------------------------------ - // . | \ - // . | \ - // T2 . | \ - // . | \ - // . | \ - // ----------------------------------------------------------------------*-------------------------------- - // - // (Note the dots represent the newly inferrred start. - // Determining the new and old end is also pretty simple. Basically it boils down to paying attention to the - // absolute positions at the asterixes, and the relative change between the dollar signs. Basically, we see - // which if the two $'s precedes the other, and we move that one forward until they line up. in this case that - // means: - // - // 0 10 20 30 40 50 60 70 80 90 100 - // --------------------------------------------------------------------------------*---------------------- - // | / - // | /---- - // T1 | /---- - // | /---- - // | /---- - // ------------------------------------------------------------$------------------------------------------ - // . | \ - // . | \ - // T2 . | \ - // . | \ - // . | \ - // ----------------------------------------------------------------------*-------------------------------- - // - // In other words (in this case), we're recognizing that the second edit happened after where the first edit - // ended with a delta of 20 characters (60 - 40). Thus, if we go back in time to where the first edit started - // that's the same as if we started at char 80 instead of 60. - // - // As it so happens, the same logic applies if the second edit precedes the first edit. In that case rahter - // than pusing the first edit forward to match the second, we'll push the second edit forward to match the - // first. - // - // In this case that means we have { oldStart: 10, oldEnd: 80, newEnd: 70 } or, in TextChangeRange - // semantics: { { start: 10, length: 70 }, newLength: 60 } - // - // The math then works out as follows. - // If we have { oldStart1, oldEnd1, newEnd1 } and { oldStart2, oldEnd2, newEnd2 } then we can compute the - // final result like so: - // - // { - // oldStart3: Min(oldStart1, oldStart2), - // oldEnd3 : Max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1)), - // newEnd3 : Max(newEnd2, newEnd2 + (newEnd1 - oldEnd2)) - // } - - var oldStart1 = oldStartN; - var oldEnd1 = oldEndN; - var newEnd1 = newEndN; - - var oldStart2 = nextChange.span().start(); - var oldEnd2 = nextChange.span().end(); - var newEnd2 = oldStart2 + nextChange.newLength(); - - oldStartN = Math.min(oldStart1, oldStart2); - oldEndN = Math.max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1)); - newEndN = Math.max(newEnd2, newEnd2 + (newEnd1 - oldEnd2)); - } - - return new TextChangeRange(TextSpan.fromBounds(oldStartN, oldEndN), /*newLength: */newEndN - oldStartN); - } - } -} \ No newline at end of file diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 32551d9737b..146ea141d76 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -270,7 +270,21 @@ module ts { return n.getWidth() !== 0; } - export function getTypeArgumentOrTypeParameterList(node: Node): NodeArray { + export function getNodeModifiers(node: Node): string { + var flags = node.flags; + var result: string[] = []; + + if (flags & NodeFlags.Private) result.push(ScriptElementKindModifier.privateMemberModifier); + if (flags & NodeFlags.Protected) result.push(ScriptElementKindModifier.protectedMemberModifier); + if (flags & NodeFlags.Public) result.push(ScriptElementKindModifier.publicMemberModifier); + if (flags & NodeFlags.Static) result.push(ScriptElementKindModifier.staticModifier); + if (flags & NodeFlags.Export) result.push(ScriptElementKindModifier.exportedModifier); + if (isInAmbientContext(node)) result.push(ScriptElementKindModifier.ambientModifier); + + return result.length > 0 ? result.join(',') : ScriptElementKindModifier.none; + } + + export function getTypeArgumentOrTypeParameterList(node: Node): NodeArray { if (node.kind === SyntaxKind.TypeReference || node.kind === SyntaxKind.CallExpression) { return (node).typeArguments; } @@ -306,4 +320,166 @@ module ts { return isTemplateLiteralKind(node.kind) && (node.getStart() < position && position < node.getEnd()) || (!!node.isUnterminated && position === node.getEnd()); } + + export function compareDataObjects(dst: any, src: any): boolean { + for (var e in dst) { + if (typeof dst[e] === "object") { + if (!compareDataObjects(dst[e], src[e])) { + return false; + } + } + else if (typeof dst[e] !== "function") { + if (dst[e] !== src[e]) { + return false; + } + } + } + return true; + } +} + +// Display-part writer helpers +module ts { + export function isFirstDeclarationOfSymbolParameter(symbol: Symbol) { + return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === SyntaxKind.Parameter; + } + + var displayPartWriter = getDisplayPartWriter(); + function getDisplayPartWriter(): DisplayPartsSymbolWriter { + var displayParts: SymbolDisplayPart[]; + var lineStart: boolean; + var indent: number; + + resetWriter(); + return { + displayParts: () => displayParts, + writeKeyword: text => writeKind(text, SymbolDisplayPartKind.keyword), + writeOperator: text => writeKind(text, SymbolDisplayPartKind.operator), + writePunctuation: text => writeKind(text, SymbolDisplayPartKind.punctuation), + writeSpace: text => writeKind(text, SymbolDisplayPartKind.space), + writeStringLiteral: text => writeKind(text, SymbolDisplayPartKind.stringLiteral), + writeParameter: text => writeKind(text, SymbolDisplayPartKind.parameterName), + writeSymbol, + writeLine, + increaseIndent: () => { indent++; }, + decreaseIndent: () => { indent--; }, + clear: resetWriter, + trackSymbol: () => { } + }; + + function writeIndent() { + if (lineStart) { + var indentString = getIndentString(indent); + if (indentString) { + displayParts.push(displayPart(indentString, SymbolDisplayPartKind.space)); + } + lineStart = false; + } + } + + function writeKind(text: string, kind: SymbolDisplayPartKind) { + writeIndent(); + displayParts.push(displayPart(text, kind)); + } + + function writeSymbol(text: string, symbol: Symbol) { + writeIndent(); + displayParts.push(symbolPart(text, symbol)); + } + + function writeLine() { + displayParts.push(lineBreakPart()); + lineStart = true; + } + + function resetWriter() { + displayParts = [] + lineStart = true; + indent = 0; + } + } + + export function symbolPart(text: string, symbol: Symbol) { + return displayPart(text, displayPartKind(symbol), symbol); + + function displayPartKind(symbol: Symbol): SymbolDisplayPartKind { + var flags = symbol.flags; + + if (flags & SymbolFlags.Variable) { + return isFirstDeclarationOfSymbolParameter(symbol) ? SymbolDisplayPartKind.parameterName : SymbolDisplayPartKind.localName; + } + else if (flags & SymbolFlags.Property) { return SymbolDisplayPartKind.propertyName; } + else if (flags & SymbolFlags.GetAccessor) { return SymbolDisplayPartKind.propertyName; } + else if (flags & SymbolFlags.SetAccessor) { return SymbolDisplayPartKind.propertyName; } + else if (flags & SymbolFlags.EnumMember) { return SymbolDisplayPartKind.enumMemberName; } + else if (flags & SymbolFlags.Function) { return SymbolDisplayPartKind.functionName; } + else if (flags & SymbolFlags.Class) { return SymbolDisplayPartKind.className; } + else if (flags & SymbolFlags.Interface) { return SymbolDisplayPartKind.interfaceName; } + else if (flags & SymbolFlags.Enum) { return SymbolDisplayPartKind.enumName; } + else if (flags & SymbolFlags.Module) { return SymbolDisplayPartKind.moduleName; } + else if (flags & SymbolFlags.Method) { return SymbolDisplayPartKind.methodName; } + else if (flags & SymbolFlags.TypeParameter) { return SymbolDisplayPartKind.typeParameterName; } + else if (flags & SymbolFlags.TypeAlias) { return SymbolDisplayPartKind.aliasName; } + else if (flags & SymbolFlags.Import) { return SymbolDisplayPartKind.aliasName; } + + + return SymbolDisplayPartKind.text; + } + } + + export function displayPart(text: string, kind: SymbolDisplayPartKind, symbol?: Symbol): SymbolDisplayPart { + return { + text: text, + kind: SymbolDisplayPartKind[kind] + }; + } + + export function spacePart() { + return displayPart(" ", SymbolDisplayPartKind.space); + } + + export function keywordPart(kind: SyntaxKind) { + return displayPart(tokenToString(kind), SymbolDisplayPartKind.keyword); + } + + export function punctuationPart(kind: SyntaxKind) { + return displayPart(tokenToString(kind), SymbolDisplayPartKind.punctuation); + } + + export function operatorPart(kind: SyntaxKind) { + return displayPart(tokenToString(kind), SymbolDisplayPartKind.operator); + } + + export function textPart(text: string) { + return displayPart(text, SymbolDisplayPartKind.text); + } + + export function lineBreakPart() { + return displayPart("\n", SymbolDisplayPartKind.lineBreak); + } + + export function mapToDisplayParts(writeDisplayParts: (writer: DisplayPartsSymbolWriter) => void): SymbolDisplayPart[] { + writeDisplayParts(displayPartWriter); + var result = displayPartWriter.displayParts(); + displayPartWriter.clear(); + return result; + } + + export function typeToDisplayParts(typechecker: TypeChecker, type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] { + return mapToDisplayParts(writer => { + typechecker.getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags); + }); + } + + export function symbolToDisplayParts(typeChecker: TypeChecker, symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): SymbolDisplayPart[] { + return mapToDisplayParts(writer => { + typeChecker.getSymbolDisplayBuilder().buildSymbolDisplay(symbol, writer, enclosingDeclaration, meaning, flags); + }); + } + + export function signatureToDisplayParts(typechecker: TypeChecker, signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] { + return mapToDisplayParts(writer => { + typechecker.getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags); + }); + } } \ No newline at end of file diff --git a/tests/baselines/reference/FunctionDeclaration10_es6.errors.txt b/tests/baselines/reference/FunctionDeclaration10_es6.errors.txt index 8c1585c2ec6..8c6b09c82d6 100644 --- a/tests/baselines/reference/FunctionDeclaration10_es6.errors.txt +++ b/tests/baselines/reference/FunctionDeclaration10_es6.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration10_es6.ts(1,10): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration10_es6.ts(1,10): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration10_es6.ts (1 errors) ==== function * foo(a = yield => yield) { ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. } \ No newline at end of file diff --git a/tests/baselines/reference/FunctionDeclaration11_es6.errors.txt b/tests/baselines/reference/FunctionDeclaration11_es6.errors.txt index ae307281b75..1dd8c3f6a1b 100644 --- a/tests/baselines/reference/FunctionDeclaration11_es6.errors.txt +++ b/tests/baselines/reference/FunctionDeclaration11_es6.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration11_es6.ts(1,10): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration11_es6.ts(1,10): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration11_es6.ts (1 errors) ==== function * yield() { ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. } \ No newline at end of file diff --git a/tests/baselines/reference/FunctionDeclaration13_es6.errors.txt b/tests/baselines/reference/FunctionDeclaration13_es6.errors.txt index 50b6b15d708..a46097e8a1a 100644 --- a/tests/baselines/reference/FunctionDeclaration13_es6.errors.txt +++ b/tests/baselines/reference/FunctionDeclaration13_es6.errors.txt @@ -1,11 +1,11 @@ -tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration13_es6.ts(1,10): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration13_es6.ts(1,10): error TS9001: Generators are not currently supported. tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration13_es6.ts(3,11): error TS2304: Cannot find name 'yield'. ==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration13_es6.ts (2 errors) ==== function * foo() { ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. // Legal to use 'yield' in a type context. var v: yield; ~~~~~ diff --git a/tests/baselines/reference/FunctionDeclaration1_es6.errors.txt b/tests/baselines/reference/FunctionDeclaration1_es6.errors.txt index b2fdfba350a..71b09983939 100644 --- a/tests/baselines/reference/FunctionDeclaration1_es6.errors.txt +++ b/tests/baselines/reference/FunctionDeclaration1_es6.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration1_es6.ts(1,10): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration1_es6.ts(1,10): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration1_es6.ts (1 errors) ==== function * foo() { ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. } \ No newline at end of file diff --git a/tests/baselines/reference/FunctionDeclaration6_es6.errors.txt b/tests/baselines/reference/FunctionDeclaration6_es6.errors.txt index 657a227822d..b5ea3f494a7 100644 --- a/tests/baselines/reference/FunctionDeclaration6_es6.errors.txt +++ b/tests/baselines/reference/FunctionDeclaration6_es6.errors.txt @@ -1,11 +1,11 @@ -tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration6_es6.ts(1,9): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration6_es6.ts(1,9): error TS9001: Generators are not currently supported. tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration6_es6.ts(1,18): error TS2304: Cannot find name 'yield'. ==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration6_es6.ts (2 errors) ==== function*foo(a = yield) { ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. ~~~~~ !!! error TS2304: Cannot find name 'yield'. } \ No newline at end of file diff --git a/tests/baselines/reference/FunctionDeclaration7_es6.errors.txt b/tests/baselines/reference/FunctionDeclaration7_es6.errors.txt index f81fd628eb7..71aff1e2488 100644 --- a/tests/baselines/reference/FunctionDeclaration7_es6.errors.txt +++ b/tests/baselines/reference/FunctionDeclaration7_es6.errors.txt @@ -1,11 +1,11 @@ -tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration7_es6.ts(1,9): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration7_es6.ts(1,9): error TS9001: Generators are not currently supported. tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration7_es6.ts(3,20): error TS2304: Cannot find name 'yield'. ==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration7_es6.ts (2 errors) ==== function*bar() { ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. // 'yield' here is an identifier, and not a yield expression. function*foo(a = yield) { ~~~~~ diff --git a/tests/baselines/reference/FunctionDeclaration8_es6.errors.txt b/tests/baselines/reference/FunctionDeclaration8_es6.errors.txt index 5232c8f1608..08d151203c9 100644 --- a/tests/baselines/reference/FunctionDeclaration8_es6.errors.txt +++ b/tests/baselines/reference/FunctionDeclaration8_es6.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration8_es6.ts(1,11): error TS1167: Computed property names are only available when targeting ECMAScript 6 and higher. +tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration8_es6.ts(1,11): error TS9002: Computed property names are not currently supported. ==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration8_es6.ts (1 errors) ==== var v = { [yield]: foo } ~~~~~~~ -!!! error TS1167: Computed property names are only available when targeting ECMAScript 6 and higher. \ No newline at end of file +!!! error TS9002: Computed property names are not currently supported. \ No newline at end of file diff --git a/tests/baselines/reference/FunctionDeclaration9_es6.errors.txt b/tests/baselines/reference/FunctionDeclaration9_es6.errors.txt index 7d51bf56ca4..8de32cf0a00 100644 --- a/tests/baselines/reference/FunctionDeclaration9_es6.errors.txt +++ b/tests/baselines/reference/FunctionDeclaration9_es6.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration9_es6.ts(1,10): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration9_es6.ts(1,10): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration9_es6.ts (1 errors) ==== function * foo() { ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. var v = { [yield]: foo } } \ No newline at end of file diff --git a/tests/baselines/reference/FunctionExpression1_es6.errors.txt b/tests/baselines/reference/FunctionExpression1_es6.errors.txt index 10ac3379228..979178fd4b7 100644 --- a/tests/baselines/reference/FunctionExpression1_es6.errors.txt +++ b/tests/baselines/reference/FunctionExpression1_es6.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/es6/functionExpressions/FunctionExpression1_es6.ts(1,18): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/functionExpressions/FunctionExpression1_es6.ts(1,18): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/functionExpressions/FunctionExpression1_es6.ts (1 errors) ==== var v = function * () { } ~ -!!! error TS9001: 'generators' are not currently supported. \ No newline at end of file +!!! error TS9001: Generators are not currently supported. \ No newline at end of file diff --git a/tests/baselines/reference/FunctionExpression2_es6.errors.txt b/tests/baselines/reference/FunctionExpression2_es6.errors.txt index a95cffcdbeb..ab27947d7c5 100644 --- a/tests/baselines/reference/FunctionExpression2_es6.errors.txt +++ b/tests/baselines/reference/FunctionExpression2_es6.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/es6/functionExpressions/FunctionExpression2_es6.ts(1,18): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/functionExpressions/FunctionExpression2_es6.ts(1,18): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/functionExpressions/FunctionExpression2_es6.ts (1 errors) ==== var v = function * foo() { } ~ -!!! error TS9001: 'generators' are not currently supported. \ No newline at end of file +!!! error TS9001: Generators are not currently supported. \ No newline at end of file diff --git a/tests/baselines/reference/FunctionPropertyAssignments1_es6.errors.txt b/tests/baselines/reference/FunctionPropertyAssignments1_es6.errors.txt index 53b2a016317..bbabbc97463 100644 --- a/tests/baselines/reference/FunctionPropertyAssignments1_es6.errors.txt +++ b/tests/baselines/reference/FunctionPropertyAssignments1_es6.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/es6/functionPropertyAssignments/FunctionPropertyAssignments1_es6.ts(1,11): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/functionPropertyAssignments/FunctionPropertyAssignments1_es6.ts(1,11): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/functionPropertyAssignments/FunctionPropertyAssignments1_es6.ts (1 errors) ==== var v = { *foo() { } } ~ -!!! error TS9001: 'generators' are not currently supported. \ No newline at end of file +!!! error TS9001: Generators are not currently supported. \ No newline at end of file diff --git a/tests/baselines/reference/FunctionPropertyAssignments5_es6.errors.txt b/tests/baselines/reference/FunctionPropertyAssignments5_es6.errors.txt index b3415c27f29..393ede66a60 100644 --- a/tests/baselines/reference/FunctionPropertyAssignments5_es6.errors.txt +++ b/tests/baselines/reference/FunctionPropertyAssignments5_es6.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/es6/functionPropertyAssignments/FunctionPropertyAssignments5_es6.ts(1,11): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/functionPropertyAssignments/FunctionPropertyAssignments5_es6.ts(1,11): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/functionPropertyAssignments/FunctionPropertyAssignments5_es6.ts (1 errors) ==== var v = { *[foo()]() { } } ~ -!!! error TS9001: 'generators' are not currently supported. \ No newline at end of file +!!! error TS9001: Generators are not currently supported. \ No newline at end of file diff --git a/tests/baselines/reference/MemberFunctionDeclaration1_es6.errors.txt b/tests/baselines/reference/MemberFunctionDeclaration1_es6.errors.txt index f50934ea705..9d4e312ed22 100644 --- a/tests/baselines/reference/MemberFunctionDeclaration1_es6.errors.txt +++ b/tests/baselines/reference/MemberFunctionDeclaration1_es6.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration1_es6.ts(2,4): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration1_es6.ts(2,4): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration1_es6.ts (1 errors) ==== class C { *foo() { } ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. } \ No newline at end of file diff --git a/tests/baselines/reference/MemberFunctionDeclaration2_es6.errors.txt b/tests/baselines/reference/MemberFunctionDeclaration2_es6.errors.txt index 667e0e5e58d..6373c800994 100644 --- a/tests/baselines/reference/MemberFunctionDeclaration2_es6.errors.txt +++ b/tests/baselines/reference/MemberFunctionDeclaration2_es6.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration2_es6.ts(2,11): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration2_es6.ts(2,11): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration2_es6.ts (1 errors) ==== class C { public * foo() { } ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. } \ No newline at end of file diff --git a/tests/baselines/reference/MemberFunctionDeclaration3_es6.errors.txt b/tests/baselines/reference/MemberFunctionDeclaration3_es6.errors.txt index b61137f1f3d..b43e266e2a5 100644 --- a/tests/baselines/reference/MemberFunctionDeclaration3_es6.errors.txt +++ b/tests/baselines/reference/MemberFunctionDeclaration3_es6.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration3_es6.ts(2,4): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration3_es6.ts(2,4): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration3_es6.ts (1 errors) ==== class C { *[foo]() { } ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. } \ No newline at end of file diff --git a/tests/baselines/reference/MemberFunctionDeclaration7_es6.errors.txt b/tests/baselines/reference/MemberFunctionDeclaration7_es6.errors.txt index 40afaf5bc65..ea87da50ed3 100644 --- a/tests/baselines/reference/MemberFunctionDeclaration7_es6.errors.txt +++ b/tests/baselines/reference/MemberFunctionDeclaration7_es6.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration7_es6.ts(2,4): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration7_es6.ts(2,4): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration7_es6.ts (1 errors) ==== class C { *foo() { } ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. } \ No newline at end of file diff --git a/tests/baselines/reference/YieldExpression10_es6.errors.txt b/tests/baselines/reference/YieldExpression10_es6.errors.txt index e2e52a0c5be..41d6bb5bf24 100644 --- a/tests/baselines/reference/YieldExpression10_es6.errors.txt +++ b/tests/baselines/reference/YieldExpression10_es6.errors.txt @@ -1,10 +1,10 @@ -tests/cases/conformance/es6/yieldExpressions/YieldExpression10_es6.ts(1,11): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/yieldExpressions/YieldExpression10_es6.ts(1,11): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/yieldExpressions/YieldExpression10_es6.ts (1 errors) ==== var v = { * foo() { ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. yield(foo); } } diff --git a/tests/baselines/reference/YieldExpression11_es6.errors.txt b/tests/baselines/reference/YieldExpression11_es6.errors.txt index 534d8b17bf2..eea108619bc 100644 --- a/tests/baselines/reference/YieldExpression11_es6.errors.txt +++ b/tests/baselines/reference/YieldExpression11_es6.errors.txt @@ -1,11 +1,11 @@ -tests/cases/conformance/es6/yieldExpressions/YieldExpression11_es6.ts(2,3): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/yieldExpressions/YieldExpression11_es6.ts(2,3): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/yieldExpressions/YieldExpression11_es6.ts (1 errors) ==== class C { *foo() { ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. yield(foo); } } \ No newline at end of file diff --git a/tests/baselines/reference/YieldExpression13_es6.errors.txt b/tests/baselines/reference/YieldExpression13_es6.errors.txt index 1d2cd4e3c25..185fb2f6193 100644 --- a/tests/baselines/reference/YieldExpression13_es6.errors.txt +++ b/tests/baselines/reference/YieldExpression13_es6.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/es6/yieldExpressions/YieldExpression13_es6.ts(1,9): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/yieldExpressions/YieldExpression13_es6.ts(1,9): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/yieldExpressions/YieldExpression13_es6.ts (1 errors) ==== function* foo() { yield } ~ -!!! error TS9001: 'generators' are not currently supported. \ No newline at end of file +!!! error TS9001: Generators are not currently supported. \ No newline at end of file diff --git a/tests/baselines/reference/YieldExpression16_es6.errors.txt b/tests/baselines/reference/YieldExpression16_es6.errors.txt index 1963539d4a8..54536a7d4fe 100644 --- a/tests/baselines/reference/YieldExpression16_es6.errors.txt +++ b/tests/baselines/reference/YieldExpression16_es6.errors.txt @@ -1,10 +1,10 @@ -tests/cases/conformance/es6/yieldExpressions/YieldExpression16_es6.ts(1,9): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/yieldExpressions/YieldExpression16_es6.ts(1,9): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/yieldExpressions/YieldExpression16_es6.ts (1 errors) ==== function* foo() { ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. function bar() { yield foo; } diff --git a/tests/baselines/reference/YieldExpression19_es6.errors.txt b/tests/baselines/reference/YieldExpression19_es6.errors.txt index a427ab18f70..81cf0e2063c 100644 --- a/tests/baselines/reference/YieldExpression19_es6.errors.txt +++ b/tests/baselines/reference/YieldExpression19_es6.errors.txt @@ -1,10 +1,10 @@ -tests/cases/conformance/es6/yieldExpressions/YieldExpression19_es6.ts(1,9): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/yieldExpressions/YieldExpression19_es6.ts(1,9): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/yieldExpressions/YieldExpression19_es6.ts (1 errors) ==== function*foo() { ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. function bar() { function* quux() { yield(foo); diff --git a/tests/baselines/reference/YieldExpression3_es6.errors.txt b/tests/baselines/reference/YieldExpression3_es6.errors.txt index 9983eefc9a6..91da79fbb53 100644 --- a/tests/baselines/reference/YieldExpression3_es6.errors.txt +++ b/tests/baselines/reference/YieldExpression3_es6.errors.txt @@ -1,10 +1,10 @@ -tests/cases/conformance/es6/yieldExpressions/YieldExpression3_es6.ts(1,9): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/yieldExpressions/YieldExpression3_es6.ts(1,9): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/yieldExpressions/YieldExpression3_es6.ts (1 errors) ==== function* foo() { ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. yield yield } \ No newline at end of file diff --git a/tests/baselines/reference/YieldExpression4_es6.errors.txt b/tests/baselines/reference/YieldExpression4_es6.errors.txt index 58d1326ba59..ca7ed3d354c 100644 --- a/tests/baselines/reference/YieldExpression4_es6.errors.txt +++ b/tests/baselines/reference/YieldExpression4_es6.errors.txt @@ -1,10 +1,10 @@ -tests/cases/conformance/es6/yieldExpressions/YieldExpression4_es6.ts(1,9): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/yieldExpressions/YieldExpression4_es6.ts(1,9): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/yieldExpressions/YieldExpression4_es6.ts (1 errors) ==== function* foo() { ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. yield; yield; } \ No newline at end of file diff --git a/tests/baselines/reference/YieldExpression6_es6.errors.txt b/tests/baselines/reference/YieldExpression6_es6.errors.txt index 5ef38d249d5..d8ce78a300f 100644 --- a/tests/baselines/reference/YieldExpression6_es6.errors.txt +++ b/tests/baselines/reference/YieldExpression6_es6.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/es6/yieldExpressions/YieldExpression6_es6.ts(1,9): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/yieldExpressions/YieldExpression6_es6.ts(1,9): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/yieldExpressions/YieldExpression6_es6.ts (1 errors) ==== function* foo() { ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. yield*foo } \ No newline at end of file diff --git a/tests/baselines/reference/YieldExpression7_es6.errors.txt b/tests/baselines/reference/YieldExpression7_es6.errors.txt index 11914f6fbb4..87b15ac9f71 100644 --- a/tests/baselines/reference/YieldExpression7_es6.errors.txt +++ b/tests/baselines/reference/YieldExpression7_es6.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/es6/yieldExpressions/YieldExpression7_es6.ts(1,9): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/yieldExpressions/YieldExpression7_es6.ts(1,9): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/yieldExpressions/YieldExpression7_es6.ts (1 errors) ==== function* foo() { ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. yield foo } \ No newline at end of file diff --git a/tests/baselines/reference/YieldExpression8_es6.errors.txt b/tests/baselines/reference/YieldExpression8_es6.errors.txt index 591c1fade08..77bd03382aa 100644 --- a/tests/baselines/reference/YieldExpression8_es6.errors.txt +++ b/tests/baselines/reference/YieldExpression8_es6.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/es6/yieldExpressions/YieldExpression8_es6.ts(2,9): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/yieldExpressions/YieldExpression8_es6.ts(2,9): error TS9001: Generators are not currently supported. tests/cases/conformance/es6/yieldExpressions/YieldExpression8_es6.ts(1,1): error TS2304: Cannot find name 'yield'. @@ -8,6 +8,6 @@ tests/cases/conformance/es6/yieldExpressions/YieldExpression8_es6.ts(1,1): error !!! error TS2304: Cannot find name 'yield'. function* foo() { ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. yield(foo); } \ No newline at end of file diff --git a/tests/baselines/reference/YieldExpression9_es6.errors.txt b/tests/baselines/reference/YieldExpression9_es6.errors.txt index 108028d2282..ae1b105903a 100644 --- a/tests/baselines/reference/YieldExpression9_es6.errors.txt +++ b/tests/baselines/reference/YieldExpression9_es6.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/es6/yieldExpressions/YieldExpression9_es6.ts(1,17): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/yieldExpressions/YieldExpression9_es6.ts(1,17): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/yieldExpressions/YieldExpression9_es6.ts (1 errors) ==== var v = function*() { ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. yield(foo); } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames1.errors.txt b/tests/baselines/reference/computedPropertyNames1.errors.txt new file mode 100644 index 00000000000..02abbcd6b2d --- /dev/null +++ b/tests/baselines/reference/computedPropertyNames1.errors.txt @@ -0,0 +1,13 @@ +tests/cases/conformance/es6/computedProperties/computedPropertyNames1.ts(2,9): error TS9002: Computed property names are not currently supported. +tests/cases/conformance/es6/computedProperties/computedPropertyNames1.ts(3,9): error TS9002: Computed property names are not currently supported. + + +==== tests/cases/conformance/es6/computedProperties/computedPropertyNames1.ts (2 errors) ==== + var v = { + get [0 + 1]() { return 0 }, + ~~~~~~~ +!!! error TS9002: Computed property names are not currently supported. + set [0 + 1](v: string) { } //No error + ~~~~~~~ +!!! error TS9002: Computed property names are not currently supported. + } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames1.js b/tests/baselines/reference/computedPropertyNames1.js deleted file mode 100644 index 8f3e448d698..00000000000 --- a/tests/baselines/reference/computedPropertyNames1.js +++ /dev/null @@ -1,14 +0,0 @@ -//// [computedPropertyNames1.ts] -var v = { - get [0 + 1]() { return 0 }, - set [0 + 1](v: string) { } //No error -} - -//// [computedPropertyNames1.js] -var v = { - get [0 + 1]() { - return 0; - }, - set [0 + 1](v) { - } //No error -}; diff --git a/tests/baselines/reference/computedPropertyNames1.types b/tests/baselines/reference/computedPropertyNames1.types deleted file mode 100644 index b44aa3c69d0..00000000000 --- a/tests/baselines/reference/computedPropertyNames1.types +++ /dev/null @@ -1,12 +0,0 @@ -=== tests/cases/conformance/es6/computedProperties/computedPropertyNames1.ts === -var v = { ->v : {} ->{ get [0 + 1]() { return 0 }, set [0 + 1](v: string) { } //No error} : {} - - get [0 + 1]() { return 0 }, ->0 + 1 : number - - set [0 + 1](v: string) { } //No error ->0 + 1 : number ->v : string -} diff --git a/tests/baselines/reference/computedPropertyNames2.errors.txt b/tests/baselines/reference/computedPropertyNames2.errors.txt index d0fd1de4576..e7cc84a8f6e 100644 --- a/tests/baselines/reference/computedPropertyNames2.errors.txt +++ b/tests/baselines/reference/computedPropertyNames2.errors.txt @@ -1,19 +1,37 @@ +tests/cases/conformance/es6/computedProperties/computedPropertyNames2.ts(4,5): error TS9002: Computed property names are not currently supported. +tests/cases/conformance/es6/computedProperties/computedPropertyNames2.ts(5,12): error TS9002: Computed property names are not currently supported. +tests/cases/conformance/es6/computedProperties/computedPropertyNames2.ts(6,9): error TS9002: Computed property names are not currently supported. +tests/cases/conformance/es6/computedProperties/computedPropertyNames2.ts(7,9): error TS9002: Computed property names are not currently supported. +tests/cases/conformance/es6/computedProperties/computedPropertyNames2.ts(8,16): error TS9002: Computed property names are not currently supported. +tests/cases/conformance/es6/computedProperties/computedPropertyNames2.ts(9,16): error TS9002: Computed property names are not currently supported. tests/cases/conformance/es6/computedProperties/computedPropertyNames2.ts(6,9): error TS2378: A 'get' accessor must return a value or consist of a single 'throw' statement. tests/cases/conformance/es6/computedProperties/computedPropertyNames2.ts(8,16): error TS2378: A 'get' accessor must return a value or consist of a single 'throw' statement. -==== tests/cases/conformance/es6/computedProperties/computedPropertyNames2.ts (2 errors) ==== +==== tests/cases/conformance/es6/computedProperties/computedPropertyNames2.ts (8 errors) ==== var methodName = "method"; var accessorName = "accessor"; class C { [methodName]() { } + ~~~~~~~~~~~~ +!!! error TS9002: Computed property names are not currently supported. static [methodName]() { } + ~~~~~~~~~~~~ +!!! error TS9002: Computed property names are not currently supported. get [accessorName]() { } ~~~~~~~~~~~~~~ +!!! error TS9002: Computed property names are not currently supported. + ~~~~~~~~~~~~~~ !!! error TS2378: A 'get' accessor must return a value or consist of a single 'throw' statement. set [accessorName](v) { } + ~~~~~~~~~~~~~~ +!!! error TS9002: Computed property names are not currently supported. static get [accessorName]() { } ~~~~~~~~~~~~~~ +!!! error TS9002: Computed property names are not currently supported. + ~~~~~~~~~~~~~~ !!! error TS2378: A 'get' accessor must return a value or consist of a single 'throw' statement. static set [accessorName](v) { } + ~~~~~~~~~~~~~~ +!!! error TS9002: Computed property names are not currently supported. } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames2.js b/tests/baselines/reference/computedPropertyNames2.js deleted file mode 100644 index 78d53ef94fc..00000000000 --- a/tests/baselines/reference/computedPropertyNames2.js +++ /dev/null @@ -1,48 +0,0 @@ -//// [computedPropertyNames2.ts] -var methodName = "method"; -var accessorName = "accessor"; -class C { - [methodName]() { } - static [methodName]() { } - get [accessorName]() { } - set [accessorName](v) { } - static get [accessorName]() { } - static set [accessorName](v) { } -} - -//// [computedPropertyNames2.js] -var methodName = "method"; -var accessorName = "accessor"; -var C = (function () { - function C() { - } - C.prototype[methodName] = function () { - }; - C[methodName] = function () { - }; - Object.defineProperty(C.prototype, accessorName, { - get: function () { - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(C.prototype, accessorName, { - set: function (v) { - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(C, accessorName, { - get: function () { - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(C, accessorName, { - set: function (v) { - }, - enumerable: true, - configurable: true - }); - return C; -})(); diff --git a/tests/baselines/reference/computedPropertyNames3.errors.txt b/tests/baselines/reference/computedPropertyNames3.errors.txt index 37a4ddaf1c0..a1d6e09421b 100644 --- a/tests/baselines/reference/computedPropertyNames3.errors.txt +++ b/tests/baselines/reference/computedPropertyNames3.errors.txt @@ -1,18 +1,36 @@ +tests/cases/conformance/es6/computedProperties/computedPropertyNames3.ts(3,5): error TS9002: Computed property names are not currently supported. +tests/cases/conformance/es6/computedProperties/computedPropertyNames3.ts(4,12): error TS9002: Computed property names are not currently supported. +tests/cases/conformance/es6/computedProperties/computedPropertyNames3.ts(5,9): error TS9002: Computed property names are not currently supported. +tests/cases/conformance/es6/computedProperties/computedPropertyNames3.ts(6,9): error TS9002: Computed property names are not currently supported. +tests/cases/conformance/es6/computedProperties/computedPropertyNames3.ts(7,16): error TS9002: Computed property names are not currently supported. +tests/cases/conformance/es6/computedProperties/computedPropertyNames3.ts(8,16): error TS9002: Computed property names are not currently supported. tests/cases/conformance/es6/computedProperties/computedPropertyNames3.ts(5,9): error TS2378: A 'get' accessor must return a value or consist of a single 'throw' statement. tests/cases/conformance/es6/computedProperties/computedPropertyNames3.ts(7,16): error TS2378: A 'get' accessor must return a value or consist of a single 'throw' statement. -==== tests/cases/conformance/es6/computedProperties/computedPropertyNames3.ts (2 errors) ==== +==== tests/cases/conformance/es6/computedProperties/computedPropertyNames3.ts (8 errors) ==== var id; class C { [0 + 1]() { } + ~~~~~~~ +!!! error TS9002: Computed property names are not currently supported. static [() => { }]() { } + ~~~~~~~~~~~ +!!! error TS9002: Computed property names are not currently supported. get [delete id]() { } ~~~~~~~~~~~ +!!! error TS9002: Computed property names are not currently supported. + ~~~~~~~~~~~ !!! error TS2378: A 'get' accessor must return a value or consist of a single 'throw' statement. set [[0, 1]](v) { } + ~~~~~~~~ +!!! error TS9002: Computed property names are not currently supported. static get [""]() { } ~~~~~~~~~~~~ +!!! error TS9002: Computed property names are not currently supported. + ~~~~~~~~~~~~ !!! error TS2378: A 'get' accessor must return a value or consist of a single 'throw' statement. static set [id.toString()](v) { } + ~~~~~~~~~~~~~~~ +!!! error TS9002: Computed property names are not currently supported. } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames3.js b/tests/baselines/reference/computedPropertyNames3.js deleted file mode 100644 index fbd76bf48fc..00000000000 --- a/tests/baselines/reference/computedPropertyNames3.js +++ /dev/null @@ -1,47 +0,0 @@ -//// [computedPropertyNames3.ts] -var id; -class C { - [0 + 1]() { } - static [() => { }]() { } - get [delete id]() { } - set [[0, 1]](v) { } - static get [""]() { } - static set [id.toString()](v) { } -} - -//// [computedPropertyNames3.js] -var id; -var C = (function () { - function C() { - } - C.prototype[0 + 1] = function () { - }; - C[function () { - }] = function () { - }; - Object.defineProperty(C.prototype, delete id, { - get: function () { - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(C.prototype, [0, 1], { - set: function (v) { - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(C, "", { - get: function () { - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(C, id.toString(), { - set: function (v) { - }, - enumerable: true, - configurable: true - }); - return C; -})(); diff --git a/tests/baselines/reference/computedPropertyNamesOnOverloads.errors.txt b/tests/baselines/reference/computedPropertyNamesOnOverloads.errors.txt index b3c2957a13f..6329ab39f0f 100644 --- a/tests/baselines/reference/computedPropertyNamesOnOverloads.errors.txt +++ b/tests/baselines/reference/computedPropertyNamesOnOverloads.errors.txt @@ -1,8 +1,9 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNamesOnOverloads.ts(4,5): error TS1168: Computed property names are not allowed in method overloads. tests/cases/conformance/es6/computedProperties/computedPropertyNamesOnOverloads.ts(5,5): error TS1168: Computed property names are not allowed in method overloads. +tests/cases/conformance/es6/computedProperties/computedPropertyNamesOnOverloads.ts(6,5): error TS9002: Computed property names are not currently supported. -==== tests/cases/conformance/es6/computedProperties/computedPropertyNamesOnOverloads.ts (2 errors) ==== +==== tests/cases/conformance/es6/computedProperties/computedPropertyNamesOnOverloads.ts (3 errors) ==== var methodName = "method"; var accessorName = "accessor"; class C { @@ -13,4 +14,6 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNamesOnOverloads. ~~~~~~~~~~~~ !!! error TS1168: Computed property names are not allowed in method overloads. [methodName](v?: string) { } + ~~~~~~~~~~~~ +!!! error TS9002: Computed property names are not currently supported. } \ No newline at end of file diff --git a/tests/baselines/reference/conflictMarkerTrivia1.errors.txt b/tests/baselines/reference/conflictMarkerTrivia1.errors.txt new file mode 100644 index 00000000000..79513821a00 --- /dev/null +++ b/tests/baselines/reference/conflictMarkerTrivia1.errors.txt @@ -0,0 +1,25 @@ +tests/cases/compiler/conflictMarkerTrivia1.ts(2,1): error TS1184: Merge conflict marker encountered. +tests/cases/compiler/conflictMarkerTrivia1.ts(4,1): error TS1184: Merge conflict marker encountered. +tests/cases/compiler/conflictMarkerTrivia1.ts(6,1): error TS1184: Merge conflict marker encountered. +tests/cases/compiler/conflictMarkerTrivia1.ts(3,5): error TS2300: Duplicate identifier 'v'. +tests/cases/compiler/conflictMarkerTrivia1.ts(5,5): error TS2300: Duplicate identifier 'v'. + + +==== tests/cases/compiler/conflictMarkerTrivia1.ts (5 errors) ==== + class C { + <<<<<<< HEAD + +!!! error TS1184: Merge conflict marker encountered. + v = 1; + ~ +!!! error TS2300: Duplicate identifier 'v'. + ======= + +!!! error TS1184: Merge conflict marker encountered. + v = 2; + ~ +!!! error TS2300: Duplicate identifier 'v'. + >>>>>>> Branch-a + +!!! error TS1184: Merge conflict marker encountered. + } \ No newline at end of file diff --git a/tests/baselines/reference/declarationsAndAssignments.js b/tests/baselines/reference/declarationsAndAssignments.js index 23e1fe773da..032f4cb0e63 100644 --- a/tests/baselines/reference/declarationsAndAssignments.js +++ b/tests/baselines/reference/declarationsAndAssignments.js @@ -225,12 +225,12 @@ function f4() { var z; } function f6() { - var _a = [1, "hello"], _b = _a[0], x = _b === void0 ? 0 : _b, _c = _a[1], y = _c === void0 ? "" : _c; + var _a = [1, "hello"], _b = _a[0], x = _b === void 0 ? 0 : _b, _c = _a[1], y = _c === void 0 ? "" : _c; var x; var y; } function f7() { - var _a = [1, "hello"], _b = _a[0], x = _b === void0 ? 0 : _b, _c = _a[1], y = _c === void0 ? 1 : _c; // Error, initializer for y must be string + var _a = [1, "hello"], _b = _a[0], x = _b === void 0 ? 0 : _b, _c = _a[1], y = _c === void 0 ? 1 : _c; // Error, initializer for y must be string var x; var y; } @@ -256,7 +256,7 @@ function f11() { var b; } function f12() { - var _a = [1, ["hello", { x: 5, y: true }]], a = _a[0], _b = _a[1], _c = _b === void0 ? ["abc", { x: 10, y: false }] : _b, b = _c[0], _d = _c[1], x = _d.x, c = _d.y; + var _a = [1, ["hello", { x: 5, y: true }]], a = _a[0], _b = _a[1], _c = _b === void 0 ? ["abc", { x: 10, y: false }] : _b, b = _c[0], _d = _c[1], x = _d.x, c = _d.y; var a; var b; var x; @@ -267,7 +267,7 @@ function f13() { var _b = [[x, y], { x: x, y: y }], a = _b[0], b = _b[1]; } function f14(_a) { - var _b = _a[0], a = _b === void0 ? 1 : _b, _c = _a[1], _d = _c[0], b = _d === void0 ? "hello" : _d, _e = _c[1], x = _e.x, _f = _e.y, c = _f === void0 ? false : _f; + var _b = _a[0], a = _b === void 0 ? 1 : _b, _c = _a[1], _d = _c[0], b = _d === void 0 ? "hello" : _d, _e = _c[1], x = _e.x, _f = _e.y, c = _f === void 0 ? false : _f; var a; var b; var c; @@ -290,7 +290,7 @@ function f16() { var _a = f15(), a = _a.a, b = _a.b, c = _a.c; } function f17(_a) { - var _b = _a.a, a = _b === void0 ? "" : _b, _c = _a.b, b = _c === void0 ? 0 : _c, _d = _a.c, c = _d === void0 ? false : _d; + var _b = _a.a, a = _b === void 0 ? "" : _b, _c = _a.b, b = _c === void 0 ? 0 : _c, _d = _a.c, c = _d === void 0 ? false : _d; } f17({}); f17({ a: "hello" }); @@ -304,7 +304,7 @@ function f18() { (_b = { b: b, a: a }, a = _b.a, b = _b.b, _b); _c = [a, b], aa[0] = _c[0], b = _c[1]; _d = [b, a], a = _d[0], b = _d[1]; // Error - _e = [2, "def"], _f = _e[0], a = _f === void0 ? 1 : _f, _g = _e[1], b = _g === void0 ? "abc" : _g; + _e = [2, "def"], _f = _e[0], a = _f === void 0 ? 1 : _f, _g = _e[1], b = _g === void 0 ? "abc" : _g; var _a, _b, _c, _d, _e, _f, _g; } function f19() { @@ -312,7 +312,7 @@ function f19() { _a = [1, 2], a = _a[0], b = _a[1]; _b = [b, a], a = _b[0], b = _b[1]; (_c = { b: b, a: a }, a = _c.a, b = _c.b, _c); - _d = ([[2, 3]])[0], _e = _d === void0 ? [1, 2] : _d, a = _e[0], b = _e[1]; + _d = ([[2, 3]])[0], _e = _d === void 0 ? [1, 2] : _d, a = _e[0], b = _e[1]; var x = (_f = [1, 2], a = _f[0], b = _f[1], _f); var _a, _b, _c, _d, _e, _f; } diff --git a/tests/baselines/reference/noImplicitAnyIndexingSuppressed.js b/tests/baselines/reference/noImplicitAnyIndexingSuppressed.js new file mode 100644 index 00000000000..5185a9b8db8 --- /dev/null +++ b/tests/baselines/reference/noImplicitAnyIndexingSuppressed.js @@ -0,0 +1,81 @@ +//// [noImplicitAnyIndexingSuppressed.ts] + +enum MyEmusEnum { + emu +} + +// Should be okay; should be a string. +var strRepresentation1 = MyEmusEnum[0] + +// Should be okay; should be a string. +var strRepresentation2 = MyEmusEnum[MyEmusEnum.emu] + +// Should be okay, as we suppress implicit 'any' property access checks +var strRepresentation3 = MyEmusEnum["monehh"]; + +// Should be okay; should be a MyEmusEnum +var strRepresentation4 = MyEmusEnum["emu"]; + + +// Should be okay, as we suppress implicit 'any' property access checks +var x = {}["hi"]; + +// Should be okay, as we suppress implicit 'any' property access checks +var y = {}[10]; + +var hi: any = "hi"; + +var emptyObj = {}; + +// Should be okay, as we suppress implicit 'any' property access checks +var z1 = emptyObj[hi]; +var z2 = (emptyObj)[hi]; + +interface MyMap { + [key: string]: T; +} + +var m: MyMap = { + "0": 0, + "1": 1, + "2": 2, + "Okay that's enough for today.": NaN +}; + +var mResult1 = m[MyEmusEnum.emu]; +var mResult2 = m[MyEmusEnum[MyEmusEnum.emu]]; +var mResult3 = m[hi]; + + + +//// [noImplicitAnyIndexingSuppressed.js] +var MyEmusEnum; +(function (MyEmusEnum) { + MyEmusEnum[MyEmusEnum["emu"] = 0] = "emu"; +})(MyEmusEnum || (MyEmusEnum = {})); +// Should be okay; should be a string. +var strRepresentation1 = MyEmusEnum[0]; +// Should be okay; should be a string. +var strRepresentation2 = MyEmusEnum[0 /* emu */]; +// Should be okay, as we suppress implicit 'any' property access checks +var strRepresentation3 = MyEmusEnum["monehh"]; +// Should be okay; should be a MyEmusEnum +var strRepresentation4 = 0 /* "emu" */; +// Should be okay, as we suppress implicit 'any' property access checks +var x = {}["hi"]; +// Should be okay, as we suppress implicit 'any' property access checks +var y = {}[10]; +var hi = "hi"; +var emptyObj = {}; +// Should be okay, as we suppress implicit 'any' property access checks +var z1 = emptyObj[hi]; +var z2 = emptyObj[hi]; +var m = { + "0": 0, + "1": 1, + "2": 2, + "Okay that's enough for today.": NaN +}; +var mResult1 = m[0 /* emu */]; +var mResult2 = m[MyEmusEnum[0 /* emu */]]; +var mResult3 = m[hi]; diff --git a/tests/baselines/reference/noImplicitAnyIndexingSuppressed.types b/tests/baselines/reference/noImplicitAnyIndexingSuppressed.types new file mode 100644 index 00000000000..20be75dc29e --- /dev/null +++ b/tests/baselines/reference/noImplicitAnyIndexingSuppressed.types @@ -0,0 +1,118 @@ +=== tests/cases/compiler/noImplicitAnyIndexingSuppressed.ts === + +enum MyEmusEnum { +>MyEmusEnum : MyEmusEnum + + emu +>emu : MyEmusEnum +} + +// Should be okay; should be a string. +var strRepresentation1 = MyEmusEnum[0] +>strRepresentation1 : string +>MyEmusEnum[0] : string +>MyEmusEnum : typeof MyEmusEnum + +// Should be okay; should be a string. +var strRepresentation2 = MyEmusEnum[MyEmusEnum.emu] +>strRepresentation2 : string +>MyEmusEnum[MyEmusEnum.emu] : string +>MyEmusEnum : typeof MyEmusEnum +>MyEmusEnum.emu : MyEmusEnum +>MyEmusEnum : typeof MyEmusEnum +>emu : MyEmusEnum + +// Should be okay, as we suppress implicit 'any' property access checks +var strRepresentation3 = MyEmusEnum["monehh"]; +>strRepresentation3 : any +>MyEmusEnum["monehh"] : any +>MyEmusEnum : typeof MyEmusEnum + +// Should be okay; should be a MyEmusEnum +var strRepresentation4 = MyEmusEnum["emu"]; +>strRepresentation4 : MyEmusEnum +>MyEmusEnum["emu"] : MyEmusEnum +>MyEmusEnum : typeof MyEmusEnum + + +// Should be okay, as we suppress implicit 'any' property access checks +var x = {}["hi"]; +>x : any +>{}["hi"] : any +>{} : {} + +// Should be okay, as we suppress implicit 'any' property access checks +var y = {}[10]; +>y : any +>{}[10] : any +>{} : {} + +var hi: any = "hi"; +>hi : any + +var emptyObj = {}; +>emptyObj : {} +>{} : {} + +// Should be okay, as we suppress implicit 'any' property access checks +var z1 = emptyObj[hi]; +>z1 : any +>emptyObj[hi] : any +>emptyObj : {} +>hi : any + +var z2 = (emptyObj)[hi]; +>z2 : any +>(emptyObj)[hi] : any +>(emptyObj) : any +>emptyObj : any +>emptyObj : {} +>hi : any + +interface MyMap { +>MyMap : MyMap +>T : T + + [key: string]: T; +>key : string +>T : T +} + +var m: MyMap = { +>m : MyMap +>MyMap : MyMap +>{ "0": 0, "1": 1, "2": 2, "Okay that's enough for today.": NaN} : { [x: string]: number; "0": number; "1": number; "2": number; "Okay that's enough for today.": number; } + + "0": 0, + "1": 1, + "2": 2, + "Okay that's enough for today.": NaN +>NaN : number + +}; + +var mResult1 = m[MyEmusEnum.emu]; +>mResult1 : number +>m[MyEmusEnum.emu] : number +>m : MyMap +>MyEmusEnum.emu : MyEmusEnum +>MyEmusEnum : typeof MyEmusEnum +>emu : MyEmusEnum + +var mResult2 = m[MyEmusEnum[MyEmusEnum.emu]]; +>mResult2 : number +>m[MyEmusEnum[MyEmusEnum.emu]] : number +>m : MyMap +>MyEmusEnum[MyEmusEnum.emu] : string +>MyEmusEnum : typeof MyEmusEnum +>MyEmusEnum.emu : MyEmusEnum +>MyEmusEnum : typeof MyEmusEnum +>emu : MyEmusEnum + +var mResult3 = m[hi]; +>mResult3 : number +>m[hi] : number +>m : MyMap +>hi : any + + diff --git a/tests/baselines/reference/parserComputedPropertyName12.errors.txt b/tests/baselines/reference/parserComputedPropertyName12.errors.txt new file mode 100644 index 00000000000..c028275369d --- /dev/null +++ b/tests/baselines/reference/parserComputedPropertyName12.errors.txt @@ -0,0 +1,9 @@ +tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName12.ts(2,4): error TS9002: Computed property names are not currently supported. + + +==== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName12.ts (1 errors) ==== + class C { + [e]() { } + ~~~ +!!! error TS9002: Computed property names are not currently supported. + } \ No newline at end of file diff --git a/tests/baselines/reference/parserComputedPropertyName12.js b/tests/baselines/reference/parserComputedPropertyName12.js deleted file mode 100644 index 96e62b626e7..00000000000 --- a/tests/baselines/reference/parserComputedPropertyName12.js +++ /dev/null @@ -1,13 +0,0 @@ -//// [parserComputedPropertyName12.ts] -class C { - [e]() { } -} - -//// [parserComputedPropertyName12.js] -var C = (function () { - function C() { - } - C.prototype[e] = function () { - }; - return C; -})(); diff --git a/tests/baselines/reference/parserComputedPropertyName12.types b/tests/baselines/reference/parserComputedPropertyName12.types deleted file mode 100644 index fcc96bc4d51..00000000000 --- a/tests/baselines/reference/parserComputedPropertyName12.types +++ /dev/null @@ -1,7 +0,0 @@ -=== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName12.ts === -class C { ->C : C - - [e]() { } ->e : unknown -} diff --git a/tests/baselines/reference/parserComputedPropertyName17.errors.txt b/tests/baselines/reference/parserComputedPropertyName17.errors.txt new file mode 100644 index 00000000000..f8b1a4866e8 --- /dev/null +++ b/tests/baselines/reference/parserComputedPropertyName17.errors.txt @@ -0,0 +1,7 @@ +tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName17.ts(1,15): error TS9002: Computed property names are not currently supported. + + +==== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName17.ts (1 errors) ==== + var v = { set [e](v) { } } + ~~~ +!!! error TS9002: Computed property names are not currently supported. \ No newline at end of file diff --git a/tests/baselines/reference/parserComputedPropertyName17.js b/tests/baselines/reference/parserComputedPropertyName17.js deleted file mode 100644 index 98d61ab8bca..00000000000 --- a/tests/baselines/reference/parserComputedPropertyName17.js +++ /dev/null @@ -1,6 +0,0 @@ -//// [parserComputedPropertyName17.ts] -var v = { set [e](v) { } } - -//// [parserComputedPropertyName17.js] -var v = { set [e](v) { -} }; diff --git a/tests/baselines/reference/parserComputedPropertyName17.types b/tests/baselines/reference/parserComputedPropertyName17.types deleted file mode 100644 index 8ae109dda37..00000000000 --- a/tests/baselines/reference/parserComputedPropertyName17.types +++ /dev/null @@ -1,7 +0,0 @@ -=== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName17.ts === -var v = { set [e](v) { } } ->v : {} ->{ set [e](v) { } } : {} ->e : unknown ->v : any - diff --git a/tests/baselines/reference/parserComputedPropertyName2.errors.txt b/tests/baselines/reference/parserComputedPropertyName2.errors.txt new file mode 100644 index 00000000000..9eb6cdd6004 --- /dev/null +++ b/tests/baselines/reference/parserComputedPropertyName2.errors.txt @@ -0,0 +1,7 @@ +tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName2.ts(1,11): error TS9002: Computed property names are not currently supported. + + +==== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName2.ts (1 errors) ==== + var v = { [e]: 1 }; + ~~~ +!!! error TS9002: Computed property names are not currently supported. \ No newline at end of file diff --git a/tests/baselines/reference/parserComputedPropertyName2.js b/tests/baselines/reference/parserComputedPropertyName2.js deleted file mode 100644 index f3c41f963f5..00000000000 --- a/tests/baselines/reference/parserComputedPropertyName2.js +++ /dev/null @@ -1,5 +0,0 @@ -//// [parserComputedPropertyName2.ts] -var v = { [e]: 1 }; - -//// [parserComputedPropertyName2.js] -var v = { [e]: 1 }; diff --git a/tests/baselines/reference/parserComputedPropertyName2.types b/tests/baselines/reference/parserComputedPropertyName2.types deleted file mode 100644 index 8e533282e28..00000000000 --- a/tests/baselines/reference/parserComputedPropertyName2.types +++ /dev/null @@ -1,6 +0,0 @@ -=== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName2.ts === -var v = { [e]: 1 }; ->v : {} ->{ [e]: 1 } : {} ->e : unknown - diff --git a/tests/baselines/reference/parserComputedPropertyName24.errors.txt b/tests/baselines/reference/parserComputedPropertyName24.errors.txt new file mode 100644 index 00000000000..fa7280a93e7 --- /dev/null +++ b/tests/baselines/reference/parserComputedPropertyName24.errors.txt @@ -0,0 +1,9 @@ +tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName24.ts(2,9): error TS9002: Computed property names are not currently supported. + + +==== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName24.ts (1 errors) ==== + class C { + set [e](v) { } + ~~~ +!!! error TS9002: Computed property names are not currently supported. + } \ No newline at end of file diff --git a/tests/baselines/reference/parserComputedPropertyName24.js b/tests/baselines/reference/parserComputedPropertyName24.js deleted file mode 100644 index 0b9467fb26d..00000000000 --- a/tests/baselines/reference/parserComputedPropertyName24.js +++ /dev/null @@ -1,17 +0,0 @@ -//// [parserComputedPropertyName24.ts] -class C { - set [e](v) { } -} - -//// [parserComputedPropertyName24.js] -var C = (function () { - function C() { - } - Object.defineProperty(C.prototype, e, { - set: function (v) { - }, - enumerable: true, - configurable: true - }); - return C; -})(); diff --git a/tests/baselines/reference/parserComputedPropertyName24.types b/tests/baselines/reference/parserComputedPropertyName24.types deleted file mode 100644 index d2de5244057..00000000000 --- a/tests/baselines/reference/parserComputedPropertyName24.types +++ /dev/null @@ -1,8 +0,0 @@ -=== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName24.ts === -class C { ->C : C - - set [e](v) { } ->e : unknown ->v : any -} diff --git a/tests/baselines/reference/parserComputedPropertyName3.errors.txt b/tests/baselines/reference/parserComputedPropertyName3.errors.txt new file mode 100644 index 00000000000..b13f453cb89 --- /dev/null +++ b/tests/baselines/reference/parserComputedPropertyName3.errors.txt @@ -0,0 +1,7 @@ +tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName3.ts(1,11): error TS9002: Computed property names are not currently supported. + + +==== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName3.ts (1 errors) ==== + var v = { [e]() { } }; + ~~~ +!!! error TS9002: Computed property names are not currently supported. \ No newline at end of file diff --git a/tests/baselines/reference/parserComputedPropertyName3.js b/tests/baselines/reference/parserComputedPropertyName3.js deleted file mode 100644 index 2e73fe87d3a..00000000000 --- a/tests/baselines/reference/parserComputedPropertyName3.js +++ /dev/null @@ -1,6 +0,0 @@ -//// [parserComputedPropertyName3.ts] -var v = { [e]() { } }; - -//// [parserComputedPropertyName3.js] -var v = { [e]() { -} }; diff --git a/tests/baselines/reference/parserComputedPropertyName3.types b/tests/baselines/reference/parserComputedPropertyName3.types deleted file mode 100644 index 8a5cfafbd40..00000000000 --- a/tests/baselines/reference/parserComputedPropertyName3.types +++ /dev/null @@ -1,6 +0,0 @@ -=== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName3.ts === -var v = { [e]() { } }; ->v : {} ->{ [e]() { } } : {} ->e : unknown - diff --git a/tests/baselines/reference/parserComputedPropertyName35.errors.txt b/tests/baselines/reference/parserComputedPropertyName35.errors.txt index e603d1c73fd..d68f0eb1ec7 100644 --- a/tests/baselines/reference/parserComputedPropertyName35.errors.txt +++ b/tests/baselines/reference/parserComputedPropertyName35.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName35.ts(2,6): error TS1171: A comma expression is not allowed in a computed property name. +tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName35.ts(2,5): error TS9002: Computed property names are not currently supported. ==== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName35.ts (1 errors) ==== var x = { [0, 1]: { } - ~~~~ -!!! error TS1171: A comma expression is not allowed in a computed property name. + ~~~~~~ +!!! error TS9002: Computed property names are not currently supported. } \ No newline at end of file diff --git a/tests/baselines/reference/parserComputedPropertyName37.errors.txt b/tests/baselines/reference/parserComputedPropertyName37.errors.txt new file mode 100644 index 00000000000..fa1acd5dbe0 --- /dev/null +++ b/tests/baselines/reference/parserComputedPropertyName37.errors.txt @@ -0,0 +1,9 @@ +tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName37.ts(2,5): error TS9002: Computed property names are not currently supported. + + +==== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName37.ts (1 errors) ==== + var v = { + [public]: 0 + ~~~~~~~~ +!!! error TS9002: Computed property names are not currently supported. + }; \ No newline at end of file diff --git a/tests/baselines/reference/parserComputedPropertyName37.js b/tests/baselines/reference/parserComputedPropertyName37.js deleted file mode 100644 index eb16d5ade37..00000000000 --- a/tests/baselines/reference/parserComputedPropertyName37.js +++ /dev/null @@ -1,9 +0,0 @@ -//// [parserComputedPropertyName37.ts] -var v = { - [public]: 0 -}; - -//// [parserComputedPropertyName37.js] -var v = { - [public]: 0 -}; diff --git a/tests/baselines/reference/parserComputedPropertyName37.types b/tests/baselines/reference/parserComputedPropertyName37.types deleted file mode 100644 index ebcd0ca276c..00000000000 --- a/tests/baselines/reference/parserComputedPropertyName37.types +++ /dev/null @@ -1,9 +0,0 @@ -=== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName37.ts === -var v = { ->v : {} ->{ [public]: 0} : {} - - [public]: 0 ->public : unknown - -}; diff --git a/tests/baselines/reference/parserComputedPropertyName38.errors.txt b/tests/baselines/reference/parserComputedPropertyName38.errors.txt new file mode 100644 index 00000000000..910a907ee0f --- /dev/null +++ b/tests/baselines/reference/parserComputedPropertyName38.errors.txt @@ -0,0 +1,9 @@ +tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName38.ts(2,5): error TS9002: Computed property names are not currently supported. + + +==== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName38.ts (1 errors) ==== + class C { + [public]() { } + ~~~~~~~~ +!!! error TS9002: Computed property names are not currently supported. + } \ No newline at end of file diff --git a/tests/baselines/reference/parserComputedPropertyName38.js b/tests/baselines/reference/parserComputedPropertyName38.js deleted file mode 100644 index 487ff4078fd..00000000000 --- a/tests/baselines/reference/parserComputedPropertyName38.js +++ /dev/null @@ -1,13 +0,0 @@ -//// [parserComputedPropertyName38.ts] -class C { - [public]() { } -} - -//// [parserComputedPropertyName38.js] -var C = (function () { - function C() { - } - C.prototype[public] = function () { - }; - return C; -})(); diff --git a/tests/baselines/reference/parserComputedPropertyName38.types b/tests/baselines/reference/parserComputedPropertyName38.types deleted file mode 100644 index c77b9fcc67f..00000000000 --- a/tests/baselines/reference/parserComputedPropertyName38.types +++ /dev/null @@ -1,7 +0,0 @@ -=== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName38.ts === -class C { ->C : C - - [public]() { } ->public : unknown -} diff --git a/tests/baselines/reference/parserComputedPropertyName4.errors.txt b/tests/baselines/reference/parserComputedPropertyName4.errors.txt new file mode 100644 index 00000000000..c1137b15872 --- /dev/null +++ b/tests/baselines/reference/parserComputedPropertyName4.errors.txt @@ -0,0 +1,7 @@ +tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName4.ts(1,15): error TS9002: Computed property names are not currently supported. + + +==== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName4.ts (1 errors) ==== + var v = { get [e]() { } }; + ~~~ +!!! error TS9002: Computed property names are not currently supported. \ No newline at end of file diff --git a/tests/baselines/reference/parserComputedPropertyName4.js b/tests/baselines/reference/parserComputedPropertyName4.js deleted file mode 100644 index a88545566e6..00000000000 --- a/tests/baselines/reference/parserComputedPropertyName4.js +++ /dev/null @@ -1,6 +0,0 @@ -//// [parserComputedPropertyName4.ts] -var v = { get [e]() { } }; - -//// [parserComputedPropertyName4.js] -var v = { get [e]() { -} }; diff --git a/tests/baselines/reference/parserComputedPropertyName4.types b/tests/baselines/reference/parserComputedPropertyName4.types deleted file mode 100644 index 32a1b44efeb..00000000000 --- a/tests/baselines/reference/parserComputedPropertyName4.types +++ /dev/null @@ -1,6 +0,0 @@ -=== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName4.ts === -var v = { get [e]() { } }; ->v : {} ->{ get [e]() { } } : {} ->e : unknown - diff --git a/tests/baselines/reference/parserComputedPropertyName40.errors.txt b/tests/baselines/reference/parserComputedPropertyName40.errors.txt new file mode 100644 index 00000000000..93be0ad51b7 --- /dev/null +++ b/tests/baselines/reference/parserComputedPropertyName40.errors.txt @@ -0,0 +1,9 @@ +tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName40.ts(2,5): error TS9002: Computed property names are not currently supported. + + +==== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName40.ts (1 errors) ==== + class C { + [a ? "" : ""]() {} + ~~~~~~~~~~~~~ +!!! error TS9002: Computed property names are not currently supported. + } \ No newline at end of file diff --git a/tests/baselines/reference/parserComputedPropertyName40.js b/tests/baselines/reference/parserComputedPropertyName40.js deleted file mode 100644 index 5f6381360fc..00000000000 --- a/tests/baselines/reference/parserComputedPropertyName40.js +++ /dev/null @@ -1,13 +0,0 @@ -//// [parserComputedPropertyName40.ts] -class C { - [a ? "" : ""]() {} -} - -//// [parserComputedPropertyName40.js] -var C = (function () { - function C() { - } - C.prototype[a ? "" : ""] = function () { - }; - return C; -})(); diff --git a/tests/baselines/reference/parserComputedPropertyName40.types b/tests/baselines/reference/parserComputedPropertyName40.types deleted file mode 100644 index 1b0b3ae49f0..00000000000 --- a/tests/baselines/reference/parserComputedPropertyName40.types +++ /dev/null @@ -1,8 +0,0 @@ -=== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName40.ts === -class C { ->C : C - - [a ? "" : ""]() {} ->a ? "" : "" : string ->a : unknown -} diff --git a/tests/baselines/reference/parserComputedPropertyName41.errors.txt b/tests/baselines/reference/parserComputedPropertyName41.errors.txt new file mode 100644 index 00000000000..eb5e9a9ebbf --- /dev/null +++ b/tests/baselines/reference/parserComputedPropertyName41.errors.txt @@ -0,0 +1,9 @@ +tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName41.ts(2,5): error TS9002: Computed property names are not currently supported. + + +==== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName41.ts (1 errors) ==== + var v = { + [0 in []]: true + ~~~~~~~~~ +!!! error TS9002: Computed property names are not currently supported. + } \ No newline at end of file diff --git a/tests/baselines/reference/parserComputedPropertyName41.js b/tests/baselines/reference/parserComputedPropertyName41.js deleted file mode 100644 index b19cc3e7b3f..00000000000 --- a/tests/baselines/reference/parserComputedPropertyName41.js +++ /dev/null @@ -1,9 +0,0 @@ -//// [parserComputedPropertyName41.ts] -var v = { - [0 in []]: true -} - -//// [parserComputedPropertyName41.js] -var v = { - [0 in []]: true -}; diff --git a/tests/baselines/reference/parserComputedPropertyName41.types b/tests/baselines/reference/parserComputedPropertyName41.types deleted file mode 100644 index 468a44e6b9e..00000000000 --- a/tests/baselines/reference/parserComputedPropertyName41.types +++ /dev/null @@ -1,9 +0,0 @@ -=== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName41.ts === -var v = { ->v : {} ->{ [0 in []]: true} : {} - - [0 in []]: true ->0 in [] : boolean ->[] : undefined[] -} diff --git a/tests/baselines/reference/parserComputedPropertyName6.errors.txt b/tests/baselines/reference/parserComputedPropertyName6.errors.txt new file mode 100644 index 00000000000..893bf3da719 --- /dev/null +++ b/tests/baselines/reference/parserComputedPropertyName6.errors.txt @@ -0,0 +1,10 @@ +tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName6.ts(1,11): error TS9002: Computed property names are not currently supported. +tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName6.ts(1,19): error TS9002: Computed property names are not currently supported. + + +==== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName6.ts (2 errors) ==== + var v = { [e]: 1, [e + e]: 2 }; + ~~~ +!!! error TS9002: Computed property names are not currently supported. + ~~~~~~~ +!!! error TS9002: Computed property names are not currently supported. \ No newline at end of file diff --git a/tests/baselines/reference/parserComputedPropertyName6.js b/tests/baselines/reference/parserComputedPropertyName6.js deleted file mode 100644 index b60ad66a9d8..00000000000 --- a/tests/baselines/reference/parserComputedPropertyName6.js +++ /dev/null @@ -1,5 +0,0 @@ -//// [parserComputedPropertyName6.ts] -var v = { [e]: 1, [e + e]: 2 }; - -//// [parserComputedPropertyName6.js] -var v = { [e]: 1, [e + e]: 2 }; diff --git a/tests/baselines/reference/parserComputedPropertyName6.types b/tests/baselines/reference/parserComputedPropertyName6.types deleted file mode 100644 index 5fa7e79c32c..00000000000 --- a/tests/baselines/reference/parserComputedPropertyName6.types +++ /dev/null @@ -1,9 +0,0 @@ -=== tests/cases/conformance/parser/ecmascript6/ComputedPropertyNames/parserComputedPropertyName6.ts === -var v = { [e]: 1, [e + e]: 2 }; ->v : {} ->{ [e]: 1, [e + e]: 2 } : {} ->e : unknown ->e + e : any ->e : unknown ->e : unknown - diff --git a/tests/baselines/reference/parserES5ComputedPropertyName2.errors.txt b/tests/baselines/reference/parserES5ComputedPropertyName2.errors.txt index dc7d7e7ba30..7b6b74b8fd8 100644 --- a/tests/baselines/reference/parserES5ComputedPropertyName2.errors.txt +++ b/tests/baselines/reference/parserES5ComputedPropertyName2.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/parser/ecmascript5/ComputedPropertyNames/parserES5ComputedPropertyName2.ts(1,11): error TS1167: Computed property names are only available when targeting ECMAScript 6 and higher. +tests/cases/conformance/parser/ecmascript5/ComputedPropertyNames/parserES5ComputedPropertyName2.ts(1,11): error TS9002: Computed property names are not currently supported. ==== tests/cases/conformance/parser/ecmascript5/ComputedPropertyNames/parserES5ComputedPropertyName2.ts (1 errors) ==== var v = { [e]: 1 }; ~~~ -!!! error TS1167: Computed property names are only available when targeting ECMAScript 6 and higher. \ No newline at end of file +!!! error TS9002: Computed property names are not currently supported. \ No newline at end of file diff --git a/tests/baselines/reference/parserES5ComputedPropertyName3.errors.txt b/tests/baselines/reference/parserES5ComputedPropertyName3.errors.txt index 376c1a29ae4..669fd190265 100644 --- a/tests/baselines/reference/parserES5ComputedPropertyName3.errors.txt +++ b/tests/baselines/reference/parserES5ComputedPropertyName3.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/parser/ecmascript5/ComputedPropertyNames/parserES5ComputedPropertyName3.ts(1,11): error TS1167: Computed property names are only available when targeting ECMAScript 6 and higher. +tests/cases/conformance/parser/ecmascript5/ComputedPropertyNames/parserES5ComputedPropertyName3.ts(1,11): error TS9002: Computed property names are not currently supported. ==== tests/cases/conformance/parser/ecmascript5/ComputedPropertyNames/parserES5ComputedPropertyName3.ts (1 errors) ==== var v = { [e]() { } }; ~~~ -!!! error TS1167: Computed property names are only available when targeting ECMAScript 6 and higher. \ No newline at end of file +!!! error TS9002: Computed property names are not currently supported. \ No newline at end of file diff --git a/tests/baselines/reference/parserES5ComputedPropertyName4.errors.txt b/tests/baselines/reference/parserES5ComputedPropertyName4.errors.txt index e0b816f157c..af0c6e858ad 100644 --- a/tests/baselines/reference/parserES5ComputedPropertyName4.errors.txt +++ b/tests/baselines/reference/parserES5ComputedPropertyName4.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/parser/ecmascript5/ComputedPropertyNames/parserES5ComputedPropertyName4.ts(1,15): error TS1167: Computed property names are only available when targeting ECMAScript 6 and higher. +tests/cases/conformance/parser/ecmascript5/ComputedPropertyNames/parserES5ComputedPropertyName4.ts(1,15): error TS9002: Computed property names are not currently supported. ==== tests/cases/conformance/parser/ecmascript5/ComputedPropertyNames/parserES5ComputedPropertyName4.ts (1 errors) ==== var v = { get [e]() { } }; ~~~ -!!! error TS1167: Computed property names are only available when targeting ECMAScript 6 and higher. \ No newline at end of file +!!! error TS9002: Computed property names are not currently supported. \ No newline at end of file diff --git a/tests/baselines/reference/templateStringInYieldKeyword.errors.txt b/tests/baselines/reference/templateStringInYieldKeyword.errors.txt index b12b552d5f0..24d64d8f29e 100644 --- a/tests/baselines/reference/templateStringInYieldKeyword.errors.txt +++ b/tests/baselines/reference/templateStringInYieldKeyword.errors.txt @@ -1,10 +1,10 @@ -tests/cases/conformance/es6/templates/templateStringInYieldKeyword.ts(1,9): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/templates/templateStringInYieldKeyword.ts(1,9): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/templates/templateStringInYieldKeyword.ts (1 errors) ==== function* gen() { ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. // Once this is supported, the inner expression does not need to be parenthesized. var x = yield `abc${ x }def`; } diff --git a/tests/baselines/reference/templateStringMultiline1.js b/tests/baselines/reference/templateStringMultiline1.js new file mode 100644 index 00000000000..e81cb89926a --- /dev/null +++ b/tests/baselines/reference/templateStringMultiline1.js @@ -0,0 +1,11 @@ +//// [templateStringMultiline1.ts] + + +// newlines are +` +\ +` + +//// [templateStringMultiline1.js] +// newlines are +"\n"; diff --git a/tests/baselines/reference/templateStringMultiline1.types b/tests/baselines/reference/templateStringMultiline1.types new file mode 100644 index 00000000000..3b169c1b1cb --- /dev/null +++ b/tests/baselines/reference/templateStringMultiline1.types @@ -0,0 +1,8 @@ +=== tests/cases/conformance/es6/templates/templateStringMultiline1.ts === + +No type information for this code. +No type information for this code.// newlines are +No type information for this code.` +No type information for this code.\ +No type information for this code.` +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/templateStringMultiline1_ES6.js b/tests/baselines/reference/templateStringMultiline1_ES6.js new file mode 100644 index 00000000000..a44df4d0cc3 --- /dev/null +++ b/tests/baselines/reference/templateStringMultiline1_ES6.js @@ -0,0 +1,12 @@ +//// [templateStringMultiline1_ES6.ts] + +// newlines are +` +\ +` + +//// [templateStringMultiline1_ES6.js] +// newlines are +` +\ +`; diff --git a/tests/baselines/reference/templateStringMultiline1_ES6.types b/tests/baselines/reference/templateStringMultiline1_ES6.types new file mode 100644 index 00000000000..5e4716ac607 --- /dev/null +++ b/tests/baselines/reference/templateStringMultiline1_ES6.types @@ -0,0 +1,7 @@ +=== tests/cases/conformance/es6/templates/templateStringMultiline1_ES6.ts === + +No type information for this code.// newlines are +No type information for this code.` +No type information for this code.\ +No type information for this code.` +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/templateStringMultiline2.js b/tests/baselines/reference/templateStringMultiline2.js new file mode 100644 index 00000000000..a87e506f07d --- /dev/null +++ b/tests/baselines/reference/templateStringMultiline2.js @@ -0,0 +1,11 @@ +//// [templateStringMultiline2.ts] + + +// newlines are +` +\ +` + +//// [templateStringMultiline2.js] +// newlines are +"\n"; diff --git a/tests/baselines/reference/templateStringMultiline2.types b/tests/baselines/reference/templateStringMultiline2.types new file mode 100644 index 00000000000..b4b341416c9 --- /dev/null +++ b/tests/baselines/reference/templateStringMultiline2.types @@ -0,0 +1,8 @@ +=== tests/cases/conformance/es6/templates/templateStringMultiline2.ts === + +No type information for this code. +No type information for this code.// newlines are +No type information for this code.` +No type information for this code.\ +No type information for this code.` +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/templateStringMultiline2_ES6.js b/tests/baselines/reference/templateStringMultiline2_ES6.js new file mode 100644 index 00000000000..168c8bac39b --- /dev/null +++ b/tests/baselines/reference/templateStringMultiline2_ES6.js @@ -0,0 +1,12 @@ +//// [templateStringMultiline2_ES6.ts] + +// newlines are +` +\ +` + +//// [templateStringMultiline2_ES6.js] +// newlines are +` +\ +`; diff --git a/tests/baselines/reference/templateStringMultiline2_ES6.types b/tests/baselines/reference/templateStringMultiline2_ES6.types new file mode 100644 index 00000000000..288191d3d0f --- /dev/null +++ b/tests/baselines/reference/templateStringMultiline2_ES6.types @@ -0,0 +1,7 @@ +=== tests/cases/conformance/es6/templates/templateStringMultiline2_ES6.ts === + +No type information for this code.// newlines are +No type information for this code.` +No type information for this code.\ +No type information for this code.` +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/templateStringMultiline3.js b/tests/baselines/reference/templateStringMultiline3.js new file mode 100644 index 00000000000..bff65582515 --- /dev/null +++ b/tests/baselines/reference/templateStringMultiline3.js @@ -0,0 +1,11 @@ +//// [templateStringMultiline3.ts] + + +// newlines are +` +\ +` + +//// [templateStringMultiline3.js] +// newlines are +"\n"; diff --git a/tests/baselines/reference/templateStringMultiline3.types b/tests/baselines/reference/templateStringMultiline3.types new file mode 100644 index 00000000000..a0e1f6f8871 --- /dev/null +++ b/tests/baselines/reference/templateStringMultiline3.types @@ -0,0 +1,8 @@ +=== tests/cases/conformance/es6/templates/templateStringMultiline3.ts === + +No type information for this code. +No type information for this code.// newlines are +No type information for this code.` +No type information for this code.\ +No type information for this code.` +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/templateStringMultiline3_ES6.js b/tests/baselines/reference/templateStringMultiline3_ES6.js new file mode 100644 index 00000000000..aad544c13bb --- /dev/null +++ b/tests/baselines/reference/templateStringMultiline3_ES6.js @@ -0,0 +1,12 @@ +//// [templateStringMultiline3_ES6.ts] + +// newlines are +` +\ +` + +//// [templateStringMultiline3_ES6.js] +// newlines are +` +\ +`; diff --git a/tests/baselines/reference/templateStringMultiline3_ES6.types b/tests/baselines/reference/templateStringMultiline3_ES6.types new file mode 100644 index 00000000000..e4fa8a7edf4 --- /dev/null +++ b/tests/baselines/reference/templateStringMultiline3_ES6.types @@ -0,0 +1,7 @@ +=== tests/cases/conformance/es6/templates/templateStringMultiline3_ES6.ts === + +No type information for this code.// newlines are +No type information for this code.` +No type information for this code.\ +No type information for this code.` +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/templateStringTermination2.js b/tests/baselines/reference/templateStringTermination2.js index de7792482ee..37fd3ffd6f9 100644 --- a/tests/baselines/reference/templateStringTermination2.js +++ b/tests/baselines/reference/templateStringTermination2.js @@ -3,4 +3,4 @@ `\\` //// [templateStringTermination2.js] -"\"; +"\\"; diff --git a/tests/baselines/reference/templateStringTermination4.js b/tests/baselines/reference/templateStringTermination4.js index 7ef49703665..29bbe4e9316 100644 --- a/tests/baselines/reference/templateStringTermination4.js +++ b/tests/baselines/reference/templateStringTermination4.js @@ -3,4 +3,4 @@ `\\\\` //// [templateStringTermination4.js] -"\\"; +"\\\\"; diff --git a/tests/baselines/reference/templateStringTermination5.js b/tests/baselines/reference/templateStringTermination5.js index af7f1d6a0a6..769597f5209 100644 --- a/tests/baselines/reference/templateStringTermination5.js +++ b/tests/baselines/reference/templateStringTermination5.js @@ -3,4 +3,4 @@ `\\\\\\` //// [templateStringTermination5.js] -"\\\"; +"\\\\\\"; diff --git a/tests/baselines/reference/templateStringWhitespaceEscapes1.js b/tests/baselines/reference/templateStringWhitespaceEscapes1.js new file mode 100644 index 00000000000..1edd38c315b --- /dev/null +++ b/tests/baselines/reference/templateStringWhitespaceEscapes1.js @@ -0,0 +1,7 @@ +//// [templateStringWhitespaceEscapes1.ts] + + +`\t\n\v\f\r`; + +//// [templateStringWhitespaceEscapes1.js] +"\t\n\v\f\r"; diff --git a/tests/baselines/reference/templateStringWhitespaceEscapes1.types b/tests/baselines/reference/templateStringWhitespaceEscapes1.types new file mode 100644 index 00000000000..6c1598e0549 --- /dev/null +++ b/tests/baselines/reference/templateStringWhitespaceEscapes1.types @@ -0,0 +1,5 @@ +=== tests/cases/conformance/es6/templates/templateStringWhitespaceEscapes1.ts === + +No type information for this code. +No type information for this code.`\t\n\v\f\r`; +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/templateStringWhitespaceEscapes1_ES6.js b/tests/baselines/reference/templateStringWhitespaceEscapes1_ES6.js new file mode 100644 index 00000000000..55b93bd68a6 --- /dev/null +++ b/tests/baselines/reference/templateStringWhitespaceEscapes1_ES6.js @@ -0,0 +1,6 @@ +//// [templateStringWhitespaceEscapes1_ES6.ts] + +`\t\n\v\f\r`; + +//// [templateStringWhitespaceEscapes1_ES6.js] +`\t\n\v\f\r`; diff --git a/tests/baselines/reference/templateStringWhitespaceEscapes1_ES6.types b/tests/baselines/reference/templateStringWhitespaceEscapes1_ES6.types new file mode 100644 index 00000000000..53a6c6f9cf9 --- /dev/null +++ b/tests/baselines/reference/templateStringWhitespaceEscapes1_ES6.types @@ -0,0 +1,4 @@ +=== tests/cases/conformance/es6/templates/templateStringWhitespaceEscapes1_ES6.ts === + +No type information for this code.`\t\n\v\f\r`; +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/templateStringWhitespaceEscapes2.js b/tests/baselines/reference/templateStringWhitespaceEscapes2.js new file mode 100644 index 00000000000..144b1e78b8b --- /dev/null +++ b/tests/baselines/reference/templateStringWhitespaceEscapes2.js @@ -0,0 +1,9 @@ +//// [templateStringWhitespaceEscapes2.ts] + + +// , , , , , +`\u0009\u000B\u000C\u0020\u00A0\uFEFF`; + +//// [templateStringWhitespaceEscapes2.js] +// , , , , , +"\t\v\f  "; diff --git a/tests/baselines/reference/templateStringWhitespaceEscapes2.types b/tests/baselines/reference/templateStringWhitespaceEscapes2.types new file mode 100644 index 00000000000..7c7de875379 --- /dev/null +++ b/tests/baselines/reference/templateStringWhitespaceEscapes2.types @@ -0,0 +1,6 @@ +=== tests/cases/conformance/es6/templates/templateStringWhitespaceEscapes2.ts === + +No type information for this code. +No type information for this code.// , , , , , +No type information for this code.`\u0009\u000B\u000C\u0020\u00A0\uFEFF`; +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/templateStringWhitespaceEscapes2_ES6.js b/tests/baselines/reference/templateStringWhitespaceEscapes2_ES6.js new file mode 100644 index 00000000000..bf901c5e843 --- /dev/null +++ b/tests/baselines/reference/templateStringWhitespaceEscapes2_ES6.js @@ -0,0 +1,8 @@ +//// [templateStringWhitespaceEscapes2_ES6.ts] + +// , , , , , +`\u0009\u000B\u000C\u0020\u00A0\uFEFF`; + +//// [templateStringWhitespaceEscapes2_ES6.js] +// , , , , , +`\u0009\u000B\u000C\u0020\u00A0\uFEFF`; diff --git a/tests/baselines/reference/templateStringWhitespaceEscapes2_ES6.types b/tests/baselines/reference/templateStringWhitespaceEscapes2_ES6.types new file mode 100644 index 00000000000..834ce22cc32 --- /dev/null +++ b/tests/baselines/reference/templateStringWhitespaceEscapes2_ES6.types @@ -0,0 +1,5 @@ +=== tests/cases/conformance/es6/templates/templateStringWhitespaceEscapes2_ES6.ts === + +No type information for this code.// , , , , , +No type information for this code.`\u0009\u000B\u000C\u0020\u00A0\uFEFF`; +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/templateStringWithEmbeddedYieldKeywordES6.errors.txt b/tests/baselines/reference/templateStringWithEmbeddedYieldKeywordES6.errors.txt index 5270e79679e..20542cb12b7 100644 --- a/tests/baselines/reference/templateStringWithEmbeddedYieldKeywordES6.errors.txt +++ b/tests/baselines/reference/templateStringWithEmbeddedYieldKeywordES6.errors.txt @@ -1,10 +1,10 @@ -tests/cases/conformance/es6/templates/templateStringWithEmbeddedYieldKeywordES6.ts(1,9): error TS9001: 'generators' are not currently supported. +tests/cases/conformance/es6/templates/templateStringWithEmbeddedYieldKeywordES6.ts(1,9): error TS9001: Generators are not currently supported. ==== tests/cases/conformance/es6/templates/templateStringWithEmbeddedYieldKeywordES6.ts (1 errors) ==== function* gen() { ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. // Once this is supported, yield *must* be parenthesized. var x = `abc${ yield 10 }def`; } diff --git a/tests/baselines/reference/typeGuardsWithAny.js b/tests/baselines/reference/typeGuardsWithAny.js new file mode 100644 index 00000000000..56676fb6d68 --- /dev/null +++ b/tests/baselines/reference/typeGuardsWithAny.js @@ -0,0 +1,18 @@ +//// [typeGuardsWithAny.ts] +var x: any = { p: 0 }; +if (x instanceof Object) { + x.p; // No error, type any unaffected by type guard +} +else { + x.p; // No error, type any unaffected by type guard +} + + +//// [typeGuardsWithAny.js] +var x = { p: 0 }; +if (x instanceof Object) { + x.p; // No error, type any unaffected by type guard +} +else { + x.p; // No error, type any unaffected by type guard +} diff --git a/tests/baselines/reference/typeGuardsWithAny.types b/tests/baselines/reference/typeGuardsWithAny.types new file mode 100644 index 00000000000..ee628c9c249 --- /dev/null +++ b/tests/baselines/reference/typeGuardsWithAny.types @@ -0,0 +1,23 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts === +var x: any = { p: 0 }; +>x : any +>{ p: 0 } : { p: number; } +>p : number + +if (x instanceof Object) { +>x instanceof Object : boolean +>x : any +>Object : ObjectConstructor + + x.p; // No error, type any unaffected by type guard +>x.p : any +>x : any +>p : any +} +else { + x.p; // No error, type any unaffected by type guard +>x.p : any +>x : any +>p : any +} + diff --git a/tests/baselines/reference/yieldExpression1.errors.txt b/tests/baselines/reference/yieldExpression1.errors.txt index ecac77698c5..33d9c1bf62e 100644 --- a/tests/baselines/reference/yieldExpression1.errors.txt +++ b/tests/baselines/reference/yieldExpression1.errors.txt @@ -1,9 +1,9 @@ -tests/cases/compiler/yieldExpression1.ts(1,9): error TS9001: 'generators' are not currently supported. +tests/cases/compiler/yieldExpression1.ts(1,9): error TS9001: Generators are not currently supported. ==== tests/cases/compiler/yieldExpression1.ts (1 errors) ==== function* foo() { ~ -!!! error TS9001: 'generators' are not currently supported. +!!! error TS9001: Generators are not currently supported. yield } \ No newline at end of file diff --git a/tests/cases/compiler/conflictMarkerTrivia1.ts b/tests/cases/compiler/conflictMarkerTrivia1.ts new file mode 100644 index 00000000000..c8d14df38f7 --- /dev/null +++ b/tests/cases/compiler/conflictMarkerTrivia1.ts @@ -0,0 +1,7 @@ +class C { +<<<<<<< HEAD + v = 1; +======= + v = 2; +>>>>>>> Branch-a +} \ No newline at end of file diff --git a/tests/cases/compiler/noImplicitAnyIndexingSuppressed.ts b/tests/cases/compiler/noImplicitAnyIndexingSuppressed.ts new file mode 100644 index 00000000000..42ae529fddc --- /dev/null +++ b/tests/cases/compiler/noImplicitAnyIndexingSuppressed.ts @@ -0,0 +1,49 @@ +//@noImplicitAny: true +//@suppressImplicitAnyIndexErrors: true + +enum MyEmusEnum { + emu +} + +// Should be okay; should be a string. +var strRepresentation1 = MyEmusEnum[0] + +// Should be okay; should be a string. +var strRepresentation2 = MyEmusEnum[MyEmusEnum.emu] + +// Should be okay, as we suppress implicit 'any' property access checks +var strRepresentation3 = MyEmusEnum["monehh"]; + +// Should be okay; should be a MyEmusEnum +var strRepresentation4 = MyEmusEnum["emu"]; + + +// Should be okay, as we suppress implicit 'any' property access checks +var x = {}["hi"]; + +// Should be okay, as we suppress implicit 'any' property access checks +var y = {}[10]; + +var hi: any = "hi"; + +var emptyObj = {}; + +// Should be okay, as we suppress implicit 'any' property access checks +var z1 = emptyObj[hi]; +var z2 = (emptyObj)[hi]; + +interface MyMap { + [key: string]: T; +} + +var m: MyMap = { + "0": 0, + "1": 1, + "2": 2, + "Okay that's enough for today.": NaN +}; + +var mResult1 = m[MyEmusEnum.emu]; +var mResult2 = m[MyEmusEnum[MyEmusEnum.emu]]; +var mResult3 = m[hi]; + diff --git a/tests/cases/conformance/es6/templates/templateStringMultiline1.ts b/tests/cases/conformance/es6/templates/templateStringMultiline1.ts new file mode 100644 index 00000000000..57a62da60a5 --- /dev/null +++ b/tests/cases/conformance/es6/templates/templateStringMultiline1.ts @@ -0,0 +1,6 @@ + + +// newlines are +` +\ +` \ No newline at end of file diff --git a/tests/cases/conformance/es6/templates/templateStringMultiline1_ES6.ts b/tests/cases/conformance/es6/templates/templateStringMultiline1_ES6.ts new file mode 100644 index 00000000000..19861c5ffb4 --- /dev/null +++ b/tests/cases/conformance/es6/templates/templateStringMultiline1_ES6.ts @@ -0,0 +1,6 @@ +//@target: es6 + +// newlines are +` +\ +` \ No newline at end of file diff --git a/tests/cases/conformance/es6/templates/templateStringMultiline2.ts b/tests/cases/conformance/es6/templates/templateStringMultiline2.ts new file mode 100644 index 00000000000..1de31c36175 --- /dev/null +++ b/tests/cases/conformance/es6/templates/templateStringMultiline2.ts @@ -0,0 +1,6 @@ + + +// newlines are +` +\ +` \ No newline at end of file diff --git a/tests/cases/conformance/es6/templates/templateStringMultiline2_ES6.ts b/tests/cases/conformance/es6/templates/templateStringMultiline2_ES6.ts new file mode 100644 index 00000000000..69be653d938 --- /dev/null +++ b/tests/cases/conformance/es6/templates/templateStringMultiline2_ES6.ts @@ -0,0 +1,6 @@ +//@target: es6 + +// newlines are +` +\ +` \ No newline at end of file diff --git a/tests/cases/conformance/es6/templates/templateStringMultiline3.ts b/tests/cases/conformance/es6/templates/templateStringMultiline3.ts new file mode 100644 index 00000000000..fbde56ac230 --- /dev/null +++ b/tests/cases/conformance/es6/templates/templateStringMultiline3.ts @@ -0,0 +1 @@ + // newlines are ` \ ` \ No newline at end of file diff --git a/tests/cases/conformance/es6/templates/templateStringMultiline3_ES6.ts b/tests/cases/conformance/es6/templates/templateStringMultiline3_ES6.ts new file mode 100644 index 00000000000..4d2613f9f9f --- /dev/null +++ b/tests/cases/conformance/es6/templates/templateStringMultiline3_ES6.ts @@ -0,0 +1 @@ +//@target: es6 // newlines are ` \ ` \ No newline at end of file diff --git a/tests/cases/conformance/es6/templates/templateStringWhitespaceEscapes1.ts b/tests/cases/conformance/es6/templates/templateStringWhitespaceEscapes1.ts new file mode 100644 index 00000000000..3d1a5459a43 --- /dev/null +++ b/tests/cases/conformance/es6/templates/templateStringWhitespaceEscapes1.ts @@ -0,0 +1,3 @@ + + +`\t\n\v\f\r`; \ No newline at end of file diff --git a/tests/cases/conformance/es6/templates/templateStringWhitespaceEscapes1_ES6.ts b/tests/cases/conformance/es6/templates/templateStringWhitespaceEscapes1_ES6.ts new file mode 100644 index 00000000000..8a16e77e0b2 --- /dev/null +++ b/tests/cases/conformance/es6/templates/templateStringWhitespaceEscapes1_ES6.ts @@ -0,0 +1,3 @@ +//@target: es6 + +`\t\n\v\f\r`; \ No newline at end of file diff --git a/tests/cases/conformance/es6/templates/templateStringWhitespaceEscapes2.ts b/tests/cases/conformance/es6/templates/templateStringWhitespaceEscapes2.ts new file mode 100644 index 00000000000..6df666971ea --- /dev/null +++ b/tests/cases/conformance/es6/templates/templateStringWhitespaceEscapes2.ts @@ -0,0 +1,4 @@ + + +// , , , , , +`\u0009\u000B\u000C\u0020\u00A0\uFEFF`; \ No newline at end of file diff --git a/tests/cases/conformance/es6/templates/templateStringWhitespaceEscapes2_ES6.ts b/tests/cases/conformance/es6/templates/templateStringWhitespaceEscapes2_ES6.ts new file mode 100644 index 00000000000..5ebaf3fad5f --- /dev/null +++ b/tests/cases/conformance/es6/templates/templateStringWhitespaceEscapes2_ES6.ts @@ -0,0 +1,4 @@ +//@target: es6 + +// , , , , , +`\u0009\u000B\u000C\u0020\u00A0\uFEFF`; \ No newline at end of file diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts new file mode 100644 index 00000000000..e7e756ea8e0 --- /dev/null +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts @@ -0,0 +1,7 @@ +var x: any = { p: 0 }; +if (x instanceof Object) { + x.p; // No error, type any unaffected by type guard +} +else { + x.p; // No error, type any unaffected by type guard +} diff --git a/tests/cases/fourslash/formatConflictMarker1.ts b/tests/cases/fourslash/formatConflictMarker1.ts new file mode 100644 index 00000000000..88c97032411 --- /dev/null +++ b/tests/cases/fourslash/formatConflictMarker1.ts @@ -0,0 +1,18 @@ +/// + +////class C { +////<<<<<<< HEAD +//// v = 1; +////======= +////v = 2; +////>>>>>>> Branch - a +////} + +format.document(); +verify.currentFileContentIs("class C {\r\n\ +<<<<<<< HEAD\r\n\ + v = 1;\r\n\ +=======\r\n\ + v = 2;\r\n\ +>>>>>>> Branch - a\r\n\ +}"); \ No newline at end of file diff --git a/tests/cases/fourslash/formattingCommentsBeforeErrors.ts b/tests/cases/fourslash/formattingCommentsBeforeErrors.ts new file mode 100644 index 00000000000..bb7e616b267 --- /dev/null +++ b/tests/cases/fourslash/formattingCommentsBeforeErrors.ts @@ -0,0 +1,20 @@ +/// + +////module A { +//// interface B { +//// // a +//// // b +//// baz(); +/////*0*/ // d /*1*/asd a +//// // e +//// foo(); +//// // f asd +//// // g as +//// bar(); +//// } +////} + +goTo.marker("1"); +edit.insert("\n"); +goTo.marker("0"); +verify.currentLineContentIs(" // d "); \ No newline at end of file diff --git a/tests/cases/fourslash/formattingConditionals.ts b/tests/cases/fourslash/formattingConditionals.ts new file mode 100644 index 00000000000..cb6edfcd56b --- /dev/null +++ b/tests/cases/fourslash/formattingConditionals.ts @@ -0,0 +1,44 @@ +/// + + +////var v = +/////*0*/a === b +/////*1*/? c +/////*2*/: d; + +////var v = a === b +/////*3*/? c +/////*4*/: d; + +////var x = +/////*5*/a +/////*6*/? function(){ +/////*7*/var z = 1 +/////*8*/} +/////*9*/: function(){ +/////*10*/var z = 2 +/////*11*/} + + + + +function verifyLine(marker: string, content: string) { + goTo.marker(marker); + verify.currentLineContentIs(content); +} + +format.document(); +verifyLine("0", " a === b"); +verifyLine("1", " ? c"); +verifyLine("2", " : d;"); + +verifyLine("3", " ? c"); +verifyLine("4", " : d;"); + +verifyLine("5", " a"); +verifyLine("6", " ? function() {"); +verifyLine("7", " var z = 1"); +verifyLine("8", " }"); +verifyLine("9", " : function() {"); +verifyLine("10", " var z = 2"); +verifyLine("11", " }"); diff --git a/tests/cases/unittests/incrementalParser.ts b/tests/cases/unittests/incrementalParser.ts new file mode 100644 index 00000000000..74b67810d26 --- /dev/null +++ b/tests/cases/unittests/incrementalParser.ts @@ -0,0 +1,728 @@ +/// +/// + +module ts { + function withChange(text: IScriptSnapshot, start: number, length: number, newText: string): { text: IScriptSnapshot; textChangeRange: TextChangeRange; } { + var contents = text.getText(0, text.getLength()); + var newContents = contents.substr(0, start) + newText + contents.substring(start + length); + + return { text: ScriptSnapshot.fromString(newContents), textChangeRange: new TextChangeRange(new TextSpan(start, length), newText.length) } + } + + function withInsert(text: IScriptSnapshot, start: number, newText: string): { text: IScriptSnapshot; textChangeRange: TextChangeRange; } { + return withChange(text, start, 0, newText); + } + + function withDelete(text: IScriptSnapshot, start: number, length: number): { text: IScriptSnapshot; textChangeRange: TextChangeRange; } { + return withChange(text, start, length, ""); + } + + function createTree(text: IScriptSnapshot, version: string) { + return createLanguageServiceSourceFile(/*fileName:*/ "", text, ScriptTarget.ES5, version, /*isOpen:*/ true, /*setNodeParents:*/ true) + } + + // NOTE: 'reusedElements' is the expected count of elements reused from the old tree to the new + // tree. It may change as we tweak the parser. If the count increases then that should always + // be a good thing. If it decreases, that's not great (less reusability), but that may be + // unavoidable. If it does decrease an investigation should be done to make sure that things + // are still ok and we're still appropriately reusing most of the tree. + function compareTrees(oldText: IScriptSnapshot, newText: IScriptSnapshot, textChangeRange: TextChangeRange, expectedReusedElements: number, oldTree?: SourceFile): SourceFile { + oldTree = oldTree || createTree(oldText, /*version:*/ "."); + Utils.assertInvariants(oldTree, /*parent:*/ undefined); + + // Create a tree for the new text, in a non-incremental fashion. + var newTree = createTree(newText, oldTree.version + "."); + Utils.assertInvariants(newTree, /*parent:*/ undefined); + + // Create a tree for the new text, in an incremental fashion. + var incrementalNewTree = oldTree.update(newText, oldTree.version + ".", /*isOpen:*/ true, textChangeRange); + Utils.assertInvariants(incrementalNewTree, /*parent:*/ undefined); + + // We should get the same tree when doign a full or incremental parse. + assertStructuralEquals(newTree, incrementalNewTree); + + // There should be no reused nodes between two trees that are fully parsed. + assert.isTrue(reusedElements(oldTree, newTree) === 0); + + if (expectedReusedElements !== -1) { + var actualReusedCount = reusedElements(oldTree, incrementalNewTree); + assert.equal(actualReusedCount, expectedReusedElements, actualReusedCount + " !== " + expectedReusedElements); + } + + return incrementalNewTree; + } + + function assertStructuralEquals(node1: Node, node2: Node) { + if (node1 === node2) { + return; + } + + assert(node1, "node1"); + assert(node2, "node2"); + assert.equal(node1.pos, node2.pos, "node1.pos !== node2.pos"); + assert.equal(node1.end, node2.end, "node1.end !== node2.end"); + assert.equal(node1.kind, node2.kind, "node1.kind !== node2.kind"); + assert.equal(node1.flags, node2.flags, "node1.flags !== node2.flags"); + assert.equal(node1.parserContextFlags, node2.parserContextFlags, "node1.parserContextFlags !== node2.parserContextFlags"); + + forEachChild(node1, + child1 => { + var childName = findChildName(node1, child1); + var child2: Node = (node2)[childName]; + + assertStructuralEquals(child1, child2); + }, + (array1: NodeArray) => { + var childName = findChildName(node1, array1); + var array2: NodeArray = (node2)[childName]; + + assertArrayStructuralEquals(array1, array2); + }); + } + + function assertArrayStructuralEquals(array1: NodeArray, array2: NodeArray) { + if (array1 === array2) { + return; + } + + assert(array1, "array1"); + assert(array2, "array2"); + assert.equal(array1.pos, array2.pos, "array1.pos !== array2.pos"); + assert.equal(array1.end, array2.end, "array1.end !== array2.end"); + assert.equal(array1.length, array2.length, "array1.length !== array2.length"); + + for (var i = 0, n = array1.length; i < n; i++) { + assertStructuralEquals(array1[i], array2[i]); + } + } + + function findChildName(parent: any, child: any) { + for (var name in parent) { + if (parent.hasOwnProperty(name) && parent[name] === child) { + return name; + } + } + + throw new Error("Could not find child in parent"); + } + + function reusedElements(oldNode: SourceFile, newNode: SourceFile): number { + var allOldElements = collectElements(oldNode); + var allNewElements = collectElements(newNode); + + return filter(allOldElements, v => contains(allNewElements, v)).length; + } + + function collectElements(node: Node) { + var result: Node[] = []; + visit(node); + return result; + + function visit(node: Node) { + result.push(node); + forEachChild(node, visit); + } + } + + function deleteCode(source: string, index: number, toDelete: string) { + var repeat = toDelete.length; + var oldTree = createTree(ScriptSnapshot.fromString(source), /*version:*/ "."); + for (var i = 0; i < repeat; i++) { + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withDelete(oldText, index, 1); + var newTree = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1, oldTree); + + source = newTextAndChange.text.getText(0, newTextAndChange.text.getLength()); + oldTree = newTree; + } + } + + function insertCode(source: string, index: number, toInsert: string) { + var repeat = toInsert.length; + var oldTree = createTree(ScriptSnapshot.fromString(source), /*version:*/ "."); + for (var i = 0; i < repeat; i++) { + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withInsert(oldText, index + i, toInsert.charAt(i)); + var newTree = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1, oldTree); + + source = newTextAndChange.text.getText(0, newTextAndChange.text.getLength()); + oldTree = newTree; + } + } + + describe('Incremental',() => { + it('Inserting into method',() => { + var source = "class C {\r\n" + + " public foo1() { }\r\n" + + " public foo2() {\r\n" + + " return 1;\r\n" + + " }\r\n" + + " public foo3() { }\r\n" + + "}"; + + var oldText = ScriptSnapshot.fromString(source); + var semicolonIndex = source.indexOf(";"); + var newTextAndChange = withInsert(oldText, semicolonIndex, " + 1"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Deleting from method',() => { + var source = "class C {\r\n" + + " public foo1() { }\r\n" + + " public foo2() {\r\n" + + " return 1 + 1;\r\n" + + " }\r\n" + + " public foo3() { }\r\n" + + "}"; + + var index = source.indexOf("+ 1"); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withDelete(oldText, index, "+ 1".length); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Regular expression 1',() => { + var source = "class C { public foo1() { /; } public foo2() { return 1;} public foo3() { } }"; + + var semicolonIndex = source.indexOf(";}"); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withInsert(oldText, semicolonIndex, "/"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Regular expression 2',() => { + var source = "class C { public foo1() { ; } public foo2() { return 1/;} public foo3() { } }"; + + var semicolonIndex = source.indexOf(";"); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withInsert(oldText, semicolonIndex, "/"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Comment 1',() => { + var source = "class C { public foo1() { /; } public foo2() { return 1; } public foo3() { } }"; + + var semicolonIndex = source.indexOf(";"); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withInsert(oldText, semicolonIndex, "/"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Comment 2',() => { + var source = "class C { public foo1() { /; } public foo2() { return 1; } public foo3() { } }"; + + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withInsert(oldText, 0, "//"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Comment 3',() => { + var source = "//class C { public foo1() { /; } public foo2() { return 1; } public foo3() { } }"; + + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withDelete(oldText, 0, 2); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Comment 4',() => { + var source = "class C { public foo1() { /; } public foo2() { */ return 1; } public foo3() { } }"; + + var index = source.indexOf(";"); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withInsert(oldText, index, "*"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Parameter 1',() => { + // Should be able to reuse all the parameters. + var source = "class C {\r\n" + + " public foo2(a, b, c, d) {\r\n" + + " return 1;\r\n" + + " }\r\n" + + "}"; + + var semicolonIndex = source.indexOf(";"); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withInsert(oldText, semicolonIndex, " + 1"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Type member 1',() => { + // Should be able to reuse most of the type members. + var source = "interface I { a: number; b: string; (c): d; new (e): f; g(): h }"; + + var index = source.indexOf(": string"); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withInsert(oldText, index, "?"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Enum element 1',() => { + // Should be able to reuse most of the enum elements. + var source = "enum E { a = 1, b = 1 << 1, c = 3, e = 4, f = 5, g = 7, h = 8, i = 9, j = 10 }"; + + var index = source.indexOf("<<"); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withChange(oldText, index, 2, "+"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Strict mode 1',() => { + // In non-strict mode 'package' means nothing and can be reused. In strict mode though + // we'll have to reparse the nodes (and generate an error for 'package();' + // + // Note: in this test we don't actually add 'use strict'. This is so we can compare + // reuse with/without a strict mode change. + var source = "foo1();\r\nfoo1();\r\nfoo1();\r\package();"; + + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withInsert(oldText, 0, "'strict';\r\n"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Strict mode 2',() => { + // In non-strict mode 'package' means nothing and can be reused. In strict mode though + // we'll have to reparse the nodes (and generate an error for 'package();' + var source = "foo1();\r\nfoo1();\r\nfoo1();\r\package();"; + + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withInsert(oldText, 0, "'use strict';\r\n"); + + // Note the decreased reuse of nodes compared to 'Strict mode 1' + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Strict mode 3',() => { + // In non-strict mode 'package' means nothing and can be reused. In strict mode though + // we'll have to reparse the nodes (and generate an error for 'package();' + // + // Note: in this test we don't actually remove 'use strict'. This is so we can compare + // reuse with/without a strict mode change. + var source = "'strict';\r\nfoo1();\r\nfoo1();\r\nfoo1();\r\npackage();"; + + var index = source.indexOf('f'); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withDelete(oldText, 0, index); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Strict mode 4',() => { + // In non-strict mode 'package' means nothing and can be reused. In strict mode though + // we'll have to reparse the nodes (and generate an error for 'package();' + var source = "'use strict';\r\nfoo1();\r\nfoo1();\r\nfoo1();\r\npackage();"; + + var index = source.indexOf('f'); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withDelete(oldText, 0, index); + + // Note the decreased reuse of nodes compared to testStrictMode3 + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Strict mode 5',() => { + var source = "'use blahhh';\r\nfoo1();\r\nfoo2();\r\nfoo3();\r\nfoo4();\r\nfoo4();\r\nfoo6();\r\nfoo7();\r\nfoo8();\r\nfoo9();\r\n"; + + var index = source.indexOf('b'); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withChange(oldText, index, 6, "strict"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Strict mode 6',() => { + var source = "'use strict';\r\nfoo1();\r\nfoo2();\r\nfoo3();\r\nfoo4();\r\nfoo4();\r\nfoo6();\r\nfoo7();\r\nfoo8();\r\nfoo9();\r\n"; + + var index = source.indexOf('s'); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withChange(oldText, index, 6, "blahhh"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Strict mode 7',() => { + var source = "'use blahhh';\r\nfoo1();\r\nfoo2();\r\nfoo3();\r\nfoo4();\r\nfoo4();\r\nfoo6();\r\nfoo7();\r\nfoo8();\r\nfoo9();\r\n"; + + var index = source.indexOf('f'); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withDelete(oldText, 0, index); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Parenthesized expression to arrow function 1',() => { + var source = "var v = (a, b, c, d, e)"; + + var index = source.indexOf('a'); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withInsert(oldText, index + 1, ":"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Parenthesized expression to arrow function 2',() => { + var source = "var v = (a, b) = c"; + + var index = source.indexOf("= c") + 1; + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withInsert(oldText, index, ">"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Arrow function to parenthesized expression 1',() => { + var source = "var v = (a:, b, c, d, e)"; + + var index = source.indexOf(':'); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withDelete(oldText, index, 1); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Arrow function to parenthesized expression 2',() => { + var source = "var v = (a, b) => c"; + + var index = source.indexOf(">"); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withDelete(oldText, index, 1); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Speculative generic lookahead 1',() => { + var source = "var v = Fe"; + + var index = source.indexOf('b'); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withInsert(oldText, index + 1, ",x"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1); + }); + + it('Speculative generic lookahead 2',() => { + var source = "var v = Fe"; + + var index = source.indexOf('b'); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withInsert(oldText, index + 1, ",x"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1); + }); + + it('Speculative generic lookahead 3',() => { + var source = "var v = Fe"; + + var index = source.indexOf('b'); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withInsert(oldText, index + 1, ",x"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1); + }); + + it('Speculative generic lookahead 4',() => { + var source = "var v = Fe"; + + var index = source.indexOf('b'); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withInsert(oldText, index + 1, ",x"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1); + }); + + it('Assertion to arrow function',() => { + var source = "var v = (a);"; + + var index = source.indexOf(';'); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withInsert(oldText, index, " => 1"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Arrow function to assertion',() => { + var source = "var v = (a) => 1;"; + + var index = source.indexOf(' =>'); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withDelete(oldText, index, " => 1".length); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Contextual shift to shift-equals',() => { + var source = "var v = 1 >> = 2"; + + var index = source.indexOf('>> ='); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withDelete(oldText, index + 2, 1); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Contextual shift-equals to shift',() => { + var source = "var v = 1 >>= 2"; + + var index = source.indexOf('>>='); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withInsert(oldText, index + 2, " "); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Contextual shift to generic invocation',() => { + var source = "var v = T>>(2)"; + + var index = source.indexOf('T'); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withInsert(oldText, index, "Foo { + var source = "var v = Foo>(2)"; + + var index = source.indexOf('Foo { + var source = "var v = T>>=2;"; + + var index = source.indexOf('='); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withChange(oldText, index, "= ".length, ": Foo { + var source = "var v : Foo>=2;"; + + var index = source.indexOf(':'); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withChange(oldText, index, ": Foo0"; + + var index = source.indexOf("0"); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withChange(oldText, index, 1, "()"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Type argument list to arithmetic operator',() => { + var source = "var v = new Dictionary()"; + + var index = source.indexOf("()"); + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withDelete(oldText, index, 2); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Yield context 1',() => { + // We're changing from a non-generator to a genarator. We can't reuse statement nodes. + var source = "function foo() {\r\nyield(foo1);\r\n}"; + + var oldText = ScriptSnapshot.fromString(source); + var index = source.indexOf("foo"); + var newTextAndChange = withInsert(oldText, index, "*"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Yield context 2',() => { + // We're changing from a generator to a non-genarator. We can't reuse statement nodes. + var source = "function *foo() {\r\nyield(foo1);\r\n}"; + + var oldText = ScriptSnapshot.fromString(source); + var index = source.indexOf("*"); + var newTextAndChange = withDelete(oldText, index, "*".length); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Delete semicolon',() => { + var source = "export class Foo {\r\n}\r\n\r\nexport var foo = new Foo();\r\n\r\n export function test(foo: Foo) {\r\n return true;\r\n }\r\n"; + + var oldText = ScriptSnapshot.fromString(source); + var index = source.lastIndexOf(";"); + var newTextAndChange = withDelete(oldText, index, 1); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Edit after empty type parameter list',() => { + var source = "class Dictionary<> { }\r\nvar y;\r\n"; + + var oldText = ScriptSnapshot.fromString(source); + var index = source.length; + var newTextAndChange = withInsert(oldText, index, "var x;"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Delete parameter after comment',() => { + var source = "function fn(/* comment! */ a: number, c) { }"; + + var oldText = ScriptSnapshot.fromString(source); + var index = source.indexOf("a:"); + var newTextAndChange = withDelete(oldText, index, "a: number,".length); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Modifier added to accessor',() => { + var source = + "class C {\ + set Bar(bar:string) {}\ +}\ +var o2 = { set Foo(val:number) { } };"; + + var oldText = ScriptSnapshot.fromString(source); + var index = source.indexOf("set"); + var newTextAndChange = withInsert(oldText, index, "public "); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Insert parameter ahead of parameter',() => { + var source = + "alert(100);\ +\ +class OverloadedMonster {\ +constructor();\ +constructor(name) { }\ +}"; + + var oldText = ScriptSnapshot.fromString(source); + var index = source.indexOf("100"); + var newTextAndChange = withInsert(oldText, index, "'1', "); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Insert declare modifier before module',() => { + var source = + "module mAmbient {\ +module m3 { }\ +}"; + + var oldText = ScriptSnapshot.fromString(source); + var index = 0; + var newTextAndChange = withInsert(oldText, index, "declare "); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Insert function above arrow function with comment',() => { + var source = + "\ +() =>\ + // do something\ +0;"; + + var oldText = ScriptSnapshot.fromString(source); + var index = 0; + var newTextAndChange = withInsert(oldText, index, "function Foo() { }"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Finish incomplete regular expression',() => { + var source = "while (true) /3; return;" + + var oldText = ScriptSnapshot.fromString(source); + var index = source.length - 1; + var newTextAndChange = withInsert(oldText, index, "/"); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Regular expression to divide operation',() => { + var source = "return;\r\nwhile (true) /3/g;" + + var oldText = ScriptSnapshot.fromString(source); + var index = source.indexOf("while"); + var newTextAndChange = withDelete(oldText, index, "while ".length); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Divide operation to regular expression',() => { + var source = "return;\r\n(true) /3/g;" + + var oldText = ScriptSnapshot.fromString(source); + var index = source.indexOf("("); + var newTextAndChange = withInsert(oldText, index, "while "); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + it('Unterminated comment after keyword converted to identifier',() => { + // 'public' as a keyword should be incrementally unusable (because it has an + // unterminated comment). When we convert it to an identifier, that shouldn't + // change anything, and we should still get the same errors. + var source = "return; a.public /*" + + var oldText = ScriptSnapshot.fromString(source); + var newTextAndChange = withInsert(oldText, 0, ""); + + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + }); + + // Simulated typing tests. + + it('Type extends clause 1',() => { + var source = "interface IFoo { }\r\ninterface Array extends IFoo { }"; + + var index = source.indexOf('extends'); + deleteCode(source, index, "extends IFoo"); + }); + + it('Type after incomplete enum 1',() => { + var source = "function foo() {\r\n" + + " function getOccurrencesAtPosition() {\r\n" + + " switch (node) {\r\n" + + " enum \r\n" + + " }\r\n" + + " \r\n" + + " return undefined;\r\n" + + " \r\n" + + " function keywordToReferenceEntry() {\r\n" + + " }\r\n" + + " }\r\n" + + " \r\n" + + " return {\r\n" + + " getEmitOutput: (filename): Bar => null,\r\n" + + " };\r\n" + + " }"; + + var index = source.indexOf("enum ") + "enum ".length; + insertCode(source, index, "Fo"); + }); + }); +} \ No newline at end of file diff --git a/tests/cases/unittests/services/colorization.ts b/tests/cases/unittests/services/colorization.ts index b29f119f944..44804e4f9f5 100644 --- a/tests/cases/unittests/services/colorization.ts +++ b/tests/cases/unittests/services/colorization.ts @@ -317,7 +317,9 @@ describe('Colorization', function () { operator("<"), identifier("number"), finalEndOfLineState(ts.EndOfLineState.Start)); + }); + it("ClassifiesConflictTokens", () => { // no longer in something that looks generic. test("Foo number", ts.EndOfLineState.Start, @@ -327,6 +329,33 @@ describe('Colorization', function () { operator(">"), keyword("number"), finalEndOfLineState(ts.EndOfLineState.Start)); + + // Test conflict markers. + test( +"class C {\r\n\ +<<<<<<< HEAD\r\n\ + v = 1;\r\n\ +=======\r\n\ + v = 2;\r\n\ +>>>>>>> Branch - a\r\n\ +}", + ts.EndOfLineState.Start, + keyword("class"), + identifier("C"), + punctuation("{"), + comment("<<<<<<< HEAD"), + identifier("v"), + operator("="), + numberLiteral("1"), + punctuation(";"), + comment("======="), + identifier("v"), + operator("="), + numberLiteral("2"), + punctuation(";"), + comment(">>>>>>> Branch - a"), + punctuation("}"), + finalEndOfLineState(ts.EndOfLineState.Start)); }); }); }); \ No newline at end of file