diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4c92557b83d..8e2fa3a89f9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4948,34 +4948,34 @@ namespace ts { resolved.stringIndexType || resolved.numberIndexType || getPropertyOfType(type, name)) { return true; } - return false; } - if (type.flags & TypeFlags.UnionOrIntersection) { + else if (type.flags & TypeFlags.UnionOrIntersection) { for (let t of (type).types) { if (isKnownProperty(t, name)) { return true; } } - return false; } - return true; + return false; } function hasExcessProperties(source: FreshObjectLiteralType, target: Type, reportErrors: boolean): boolean { - for (let prop of getPropertiesOfObjectType(source)) { - if (!isKnownProperty(target, prop.name)) { - if (reportErrors) { - // We know *exactly* where things went wrong when comparing the types. - // Use this property as the error node as this will be more helpful in - // reasoning about what went wrong. - errorNode = prop.valueDeclaration; - reportError(Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1, - symbolToString(prop), - typeToString(target)); + if (someConstituentTypeHasKind(target, TypeFlags.ObjectType)) { + for (let prop of getPropertiesOfObjectType(source)) { + if (!isKnownProperty(target, prop.name)) { + if (reportErrors) { + // We know *exactly* where things went wrong when comparing the types. + // Use this property as the error node as this will be more helpful in + // reasoning about what went wrong. + errorNode = prop.valueDeclaration; + reportError(Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1, + symbolToString(prop), typeToString(target)); + } + return true; } - return true; } } + return false; } function eachTypeRelatedToSomeType(source: UnionOrIntersectionType, target: UnionOrIntersectionType): Ternary { @@ -7524,9 +7524,6 @@ namespace ts { case SyntaxKind.JsxSelfClosingElement: checkJsxSelfClosingElement(child); break; - default: - // No checks for JSX Text - Debug.assert(child.kind === SyntaxKind.JsxText); } } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 9a4f5452eed..8fd92818c46 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -775,7 +775,7 @@ namespace ts { }; export interface ObjectAllocator { - getNodeConstructor(kind: SyntaxKind): new () => Node; + getNodeConstructor(kind: SyntaxKind): new (pos?: number, end?: number) => Node; getSymbolConstructor(): new (flags: SymbolFlags, name: string) => Symbol; getTypeConstructor(): new (checker: TypeChecker, flags: TypeFlags) => Type; getSignatureConstructor(): new (checker: TypeChecker) => Signature; @@ -796,15 +796,13 @@ namespace ts { export let objectAllocator: ObjectAllocator = { getNodeConstructor: kind => { - function Node() { + function Node(pos: number, end: number) { + this.pos = pos; + this.end = end; + this.flags = NodeFlags.None; + this.parent = undefined; } - Node.prototype = { - kind: kind, - pos: -1, - end: -1, - flags: 0, - parent: undefined, - }; + Node.prototype = { kind }; return Node; }, getSymbolConstructor: () => Symbol, @@ -844,9 +842,9 @@ namespace ts { export function copyListRemovingItem(item: T, list: T[]) { let copiedList: T[] = []; - for (var i = 0, len = list.length; i < len; i++) { - if (list[i] !== item) { - copiedList.push(list[i]); + for (let e of list) { + if (e !== item) { + copiedList.push(e); } } return copiedList; diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 9327ad188f4..d54d49e7511 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1720,6 +1720,10 @@ "category": "Error", "code": 2656 }, + "JSX expressions must have one parent element": { + "category": "Error", + "code": 2657 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", "code": 4000 diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index f2468e7244d..70ab3606c6c 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1769,34 +1769,39 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write("."); } } - else if (modulekind !== ModuleKind.ES6) { - let declaration = resolver.getReferencedImportDeclaration(node); - if (declaration) { - if (declaration.kind === SyntaxKind.ImportClause) { - // Identifier references default import - write(getGeneratedNameForNode(declaration.parent)); - write(languageVersion === ScriptTarget.ES3 ? "[\"default\"]" : ".default"); - return; - } - else if (declaration.kind === SyntaxKind.ImportSpecifier) { - // Identifier references named import - write(getGeneratedNameForNode(declaration.parent.parent.parent)); - let name = (declaration).propertyName || (declaration).name; - let identifier = getSourceTextOfNodeFromSourceFile(currentSourceFile, name); - if (languageVersion === ScriptTarget.ES3 && identifier === "default") { - write(`["default"]`); + else { + if (modulekind !== ModuleKind.ES6) { + let declaration = resolver.getReferencedImportDeclaration(node); + if (declaration) { + if (declaration.kind === SyntaxKind.ImportClause) { + // Identifier references default import + write(getGeneratedNameForNode(declaration.parent)); + write(languageVersion === ScriptTarget.ES3 ? "[\"default\"]" : ".default"); + return; } - else { - write("."); - write(identifier); + else if (declaration.kind === SyntaxKind.ImportSpecifier) { + // Identifier references named import + write(getGeneratedNameForNode(declaration.parent.parent.parent)); + let name = (declaration).propertyName || (declaration).name; + let identifier = getSourceTextOfNodeFromSourceFile(currentSourceFile, name); + if (languageVersion === ScriptTarget.ES3 && identifier === "default") { + write(`["default"]`); + } + else { + write("."); + write(identifier); + } + return; } - return; } } - declaration = resolver.getReferencedNestedRedeclaration(node); - if (declaration) { - write(getGeneratedNameForNode(declaration.name)); - return; + + if (languageVersion !== ScriptTarget.ES6) { + let declaration = resolver.getReferencedNestedRedeclaration(node); + if (declaration) { + write(getGeneratedNameForNode(declaration.name)); + return; + } } } @@ -2785,7 +2790,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi /** * Emit ES7 exponentiation operator downlevel using Math.pow - * @param node a binary expression node containing exponentiationOperator (**, **=) + * @param node a binary expression node containing exponentiationOperator (**, **=) */ function emitExponentiationOperator(node: BinaryExpression) { let leftHandSideExpression = node.left; diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 1551706a337..d2344722ed5 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2,15 +2,15 @@ /// namespace ts { - let nodeConstructors = new Array Node>(SyntaxKind.Count); + let nodeConstructors = new Array Node>(SyntaxKind.Count); /* @internal */ export let parseTime = 0; - export function getNodeConstructor(kind: SyntaxKind): new () => Node { + export function getNodeConstructor(kind: SyntaxKind): new (pos?: number, end?: number) => Node { return nodeConstructors[kind] || (nodeConstructors[kind] = objectAllocator.getNodeConstructor(kind)); } - export function createNode(kind: SyntaxKind): Node { - return new (getNodeConstructor(kind))(); + export function createNode(kind: SyntaxKind, pos?: number, end?: number): Node { + return new (getNodeConstructor(kind))(pos, end); } function visitNode(cbNode: (node: Node) => T, node: Node): T { @@ -993,14 +993,10 @@ namespace ts { function createNode(kind: SyntaxKind, pos?: number): Node { nodeCount++; - let node = new (nodeConstructors[kind] || (nodeConstructors[kind] = objectAllocator.getNodeConstructor(kind)))(); if (!(pos >= 0)) { pos = scanner.getStartPos(); } - - node.pos = pos; - node.end = pos; - return node; + return new (nodeConstructors[kind] || (nodeConstructors[kind] = objectAllocator.getNodeConstructor(kind)))(pos, pos); } function finishNode(node: T, end?: number): T { @@ -3454,19 +3450,43 @@ namespace ts { function parseJsxElementOrSelfClosingElement(inExpressionContext: boolean): JsxElement | JsxSelfClosingElement { let opening = parseJsxOpeningOrSelfClosingElement(inExpressionContext); + let result: JsxElement | JsxSelfClosingElement; if (opening.kind === SyntaxKind.JsxOpeningElement) { let node = createNode(SyntaxKind.JsxElement, opening.pos); node.openingElement = opening; node.children = parseJsxChildren(node.openingElement.tagName); node.closingElement = parseJsxClosingElement(inExpressionContext); - return finishNode(node); + result = finishNode(node); } else { Debug.assert(opening.kind === SyntaxKind.JsxSelfClosingElement); // Nothing else to do for self-closing elements - return opening; + result = opening; } + + // If the user writes the invalid code '
' in an expression context (i.e. not wrapped in + // an enclosing tag), we'll naively try to parse ^ this as a 'less than' operator and the remainder of the tag + // as garbage, which will cause the formatter to badly mangle the JSX. Perform a speculative parse of a JSX + // element if we see a < token so that we can wrap it in a synthetic binary expression so the formatter + // does less damage and we can report a better error. + // Since JSX elements are invalid < operands anyway, this lookahead parse will only occur in error scenarios + // of one sort or another. + if (inExpressionContext && token === SyntaxKind.LessThanToken) { + let invalidElement = tryParse(() => parseJsxElementOrSelfClosingElement(/*inExpressionContext*/true)); + if (invalidElement) { + parseErrorAtCurrentToken(Diagnostics.JSX_expressions_must_have_one_parent_element); + let badNode = createNode(SyntaxKind.BinaryExpression, result.pos); + badNode.end = invalidElement.end; + badNode.left = result; + badNode.right = invalidElement; + badNode.operatorToken = createMissingNode(SyntaxKind.CommaToken, /*reportAtCurrentPosition*/ false, /*diagnosticMessage*/ undefined); + badNode.operatorToken.pos = badNode.operatorToken.end = badNode.right.pos; + return badNode; + } + } + + return result; } function parseJsxText(): JsxText { diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 0872a2e5ba5..3eeb126c065 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -407,7 +407,7 @@ namespace ts { // (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643) return _fs.watch( path, - { persisten: true, recursive: !!recursive }, + { persistent: true, recursive: !!recursive }, (eventName: string, relativeFileName: string) => { // In watchDirectory we only care about adding and removing files (when event name is // "rename"); changes made within files are handled by corresponding fileWatchers (when diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 9d79d435a04..e51fda074c5 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -360,7 +360,8 @@ namespace ts { let newFileNames = ts.map(parsedCommandLine.fileNames, compilerHost.getCanonicalFileName); let canonicalRootFileNames = ts.map(rootFileNames, compilerHost.getCanonicalFileName); - if (!arrayStructurallyIsEqualTo(newFileNames, canonicalRootFileNames)) { + // We check if the project file list has changed. If so, we just throw away the old program and start fresh. + if (!arrayIsEqualTo(newFileNames && newFileNames.sort(), canonicalRootFileNames && canonicalRootFileNames.sort())) { setCachedProgram(undefined); startTimerForRecompilation(); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index d79aab5fc61..ab5a9322ac2 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -361,6 +361,7 @@ namespace ts { } export const enum NodeFlags { + None = 0, Export = 1 << 1, // Declarations Ambient = 1 << 2, // Declarations Public = 1 << 3, // Property/Method @@ -381,7 +382,6 @@ namespace ts { ContainsThis = 1 << 18, // Interface contains references to "this" HasImplicitReturn = 1 << 19, // If function implicitly returns on one of codepaths (initialized by binding) HasExplicitReturn = 1 << 20, // If function has explicit reachable return on one of codepaths (initialized by binding) - Modifier = Export | Ambient | Public | Private | Protected | Static | Abstract | Default | Async, AccessibilityModifier = Public | Private | Protected, BlockScoped = Let | Const, diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 1fcbcbc842d..5cab42629e4 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -82,17 +82,17 @@ namespace ts { return node.end - node.pos; } - export function arrayIsEqualTo(arr1: T[], arr2: T[], comparer?: (a: T, b: T) => boolean): boolean { - if (!arr1 || !arr2) { - return arr1 === arr2; + export function arrayIsEqualTo(array1: T[], array2: T[], equaler?: (a: T, b: T) => boolean): boolean { + if (!array1 || !array2) { + return array1 === array2; } - if (arr1.length !== arr2.length) { + if (array1.length !== array2.length) { return false; } - for (let i = 0; i < arr1.length; ++i) { - let equals = comparer ? comparer(arr1[i], arr2[i]) : arr1[i] === arr2[i]; + for (let i = 0; i < array1.length; ++i) { + let equals = equaler ? equaler(array1[i], array2[i]) : array1[i] === array2[i]; if (!equals) { return false; } @@ -1505,7 +1505,7 @@ namespace ts { } export function createSynthesizedNode(kind: SyntaxKind, startsOnNewLine?: boolean): Node { - let node = createNode(kind); + let node = createNode(kind, /* pos */ -1, /* end */ -1); node.startsOnNewLine = startsOnNewLine; return node; } @@ -2414,16 +2414,4 @@ namespace ts { } } } - - export function arrayStructurallyIsEqualTo(array1: Array, array2: Array): boolean { - if (!array1 || !array2) { - return false; - } - - if (array1.length !== array2.length) { - return false; - } - - return arrayIsEqualTo(array1.sort(), array2.sort()); - } } diff --git a/src/harness/harness.ts b/src/harness/harness.ts index a37b647a124..806f89be04d 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -274,7 +274,9 @@ namespace Utils { case "flags": // Print out flags with their enum names. - o[propertyName] = getNodeFlagName(n.flags); + if (n.flags) { + o[propertyName] = getNodeFlagName(n.flags); + } break; case "parserContextFlags": diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 09f8a372463..efcca0e37c5 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -576,7 +576,8 @@ namespace ts.server { let newRootFiles = projectOptions.files.map((f => this.getCanonicalFileName(f))); let currentRootFiles = project.getRootFiles().map((f => this.getCanonicalFileName(f))); - if (!arrayStructurallyIsEqualTo(currentRootFiles, newRootFiles)) { + // We check if the project file list has changed. If so, we update the project. + if (!arrayIsEqualTo(currentRootFiles && currentRootFiles.sort(), newRootFiles && newRootFiles.sort())) { // For configured projects, the change is made outside the tsconfig file, and // it is not likely to affect the project for other files opened by the client. We can // just update the current project. diff --git a/src/services/formatting/formatting.ts b/src/services/formatting/formatting.ts index 4a7033c6f3e..651105e9d5c 100644 --- a/src/services/formatting/formatting.ts +++ b/src/services/formatting/formatting.ts @@ -695,8 +695,8 @@ namespace ts.formatting { let tokenStart = sourceFile.getLineAndCharacterOfPosition(currentTokenInfo.token.pos); if (isTokenInRange) { let rangeHasError = rangeContainsError(currentTokenInfo.token); - // save prevStartLine since processRange will overwrite this value with current ones - let prevStartLine = previousRangeStartLine; + // save previousRange since processRange will overwrite this value with current one + let savePreviousRange = previousRange; lineAdded = processRange(currentTokenInfo.token, tokenStart, parent, childContextNode, dynamicIndentation); if (rangeHasError) { // do not indent comments\token if token range overlaps with some error @@ -707,7 +707,9 @@ namespace ts.formatting { indentToken = lineAdded; } else { - indentToken = lastTriviaWasNewLine && tokenStart.line !== prevStartLine; + // indent token only if end line of previous range does not match start line of the token + const prevEndLine = savePreviousRange && sourceFile.getLineAndCharacterOfPosition(savePreviousRange.end).line; + indentToken = lastTriviaWasNewLine && tokenStart.line !== prevEndLine; } } } diff --git a/src/services/services.ts b/src/services/services.ts index 6179c8a169b..c9a6d609e5b 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -174,9 +174,7 @@ namespace ts { let jsDocCompletionEntries: CompletionEntry[]; function createNode(kind: SyntaxKind, pos: number, end: number, flags: NodeFlags, parent?: Node): NodeObject { - let node = new (getNodeConstructor(kind))(); - node.pos = pos; - node.end = end; + let node = new (getNodeConstructor(kind))(pos, end); node.flags = flags; node.parent = parent; return node; @@ -7965,14 +7963,14 @@ namespace ts { function initializeServices() { objectAllocator = { getNodeConstructor: kind => { - function Node() { + function Node(pos: number, end: number) { + this.pos = pos; + this.end = end; + this.flags = NodeFlags.None; + this.parent = undefined; } let proto = kind === SyntaxKind.SourceFile ? new SourceFileObject() : new NodeObject(); proto.kind = kind; - proto.pos = -1; - proto.end = -1; - proto.flags = 0; - proto.parent = undefined; Node.prototype = proto; return Node; }, diff --git a/tests/baselines/reference/jsxEsprimaFbTestSuite.errors.txt b/tests/baselines/reference/jsxEsprimaFbTestSuite.errors.txt index 5758db36960..3a6059d8d07 100644 --- a/tests/baselines/reference/jsxEsprimaFbTestSuite.errors.txt +++ b/tests/baselines/reference/jsxEsprimaFbTestSuite.errors.txt @@ -4,11 +4,10 @@ tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(39,29): error TS1005: '{' tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(39,57): error TS1109: Expression expected. tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(39,58): error TS1109: Expression expected. tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(41,1): error TS1003: Identifier expected. -tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(41,6): error TS1109: Expression expected. -tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(41,12): error TS1109: Expression expected. +tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(41,12): error TS2657: JSX expressions must have one parent element -==== tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx (8 errors) ==== +==== tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx (7 errors) ==== declare var React: any; declare var 日本語; declare var AbC_def; @@ -62,10 +61,8 @@ tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(41,12): error TS1109: Expr ; ~ !!! error TS1003: Identifier expected. - ~~ -!!! error TS1109: Expression expected. ~ -!!! error TS1109: Expression expected. +!!! error TS2657: JSX expressions must have one parent element ; diff --git a/tests/baselines/reference/jsxEsprimaFbTestSuite.js b/tests/baselines/reference/jsxEsprimaFbTestSuite.js index 1e22826f440..465d265efb2 100644 --- a/tests/baselines/reference/jsxEsprimaFbTestSuite.js +++ b/tests/baselines/reference/jsxEsprimaFbTestSuite.js @@ -72,8 +72,8 @@ baz
@test content
;

7x invalid-js-identifier
; } right={monkeys /> gorillas / > }/> - < a.b > ; -a.b > ; + , + ; ; (
) < x;
; diff --git a/tests/baselines/reference/jsxInvalidEsprimaTestSuite.errors.txt b/tests/baselines/reference/jsxInvalidEsprimaTestSuite.errors.txt index 02bc56e823e..578159dc651 100644 --- a/tests/baselines/reference/jsxInvalidEsprimaTestSuite.errors.txt +++ b/tests/baselines/reference/jsxInvalidEsprimaTestSuite.errors.txt @@ -12,17 +12,11 @@ tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(6,6): error TS2304: C tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(6,9): error TS1109: Expression expected. tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(6,10): error TS1109: Expression expected. tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(7,1): error TS1003: Identifier expected. -tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(7,2): error TS2304: Cannot find name 'a'. -tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(7,4): error TS1109: Expression expected. tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(8,4): error TS17002: Expected corresponding JSX closing tag for 'a'. tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(9,13): error TS1002: Unterminated string literal. tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(10,1): error TS1003: Identifier expected. -tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(10,2): error TS2304: Cannot find name 'a'. -tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(10,3): error TS1005: ';' expected. -tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(10,4): error TS2304: Cannot find name 'b'. -tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(10,6): error TS1109: Expression expected. -tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(10,8): error TS2304: Cannot find name 'b'. -tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(10,10): error TS1109: Expression expected. +tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(10,6): error TS17002: Expected corresponding JSX closing tag for 'a'. +tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(10,10): error TS2657: JSX expressions must have one parent element tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(11,3): error TS1003: Identifier expected. tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(11,5): error TS1003: Identifier expected. tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(11,11): error TS1005: '>' expected. @@ -71,7 +65,7 @@ tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(35,4): error TS1003: tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(35,21): error TS17002: Expected corresponding JSX closing tag for 'a'. -==== tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx (71 errors) ==== +==== tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx (65 errors) ==== declare var React: any; ; @@ -107,10 +101,6 @@ tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(35,21): error TS17002 ; ~ !!! error TS1003: Identifier expected. - ~ -!!! error TS2304: Cannot find name 'a'. - ~ -!!! error TS1109: Expression expected. ; ~~~~ !!! error TS17002: Expected corresponding JSX closing tag for 'a'. @@ -120,18 +110,10 @@ tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(35,21): error TS17002 ; ~ !!! error TS1003: Identifier expected. - ~ -!!! error TS2304: Cannot find name 'a'. - ~ -!!! error TS1005: ';' expected. - ~ -!!! error TS2304: Cannot find name 'b'. - ~~ -!!! error TS1109: Expression expected. - ~ -!!! error TS2304: Cannot find name 'b'. + ~~~~ +!!! error TS17002: Expected corresponding JSX closing tag for 'a'. ~ -!!! error TS1109: Expression expected. +!!! error TS2657: JSX expressions must have one parent element ; ~ !!! error TS1003: Identifier expected. diff --git a/tests/baselines/reference/jsxInvalidEsprimaTestSuite.js b/tests/baselines/reference/jsxInvalidEsprimaTestSuite.js index d623e127be7..7f01666bd78 100644 --- a/tests/baselines/reference/jsxInvalidEsprimaTestSuite.js +++ b/tests/baselines/reference/jsxInvalidEsprimaTestSuite.js @@ -41,12 +41,10 @@ var x =
one
/* intervening comment */
two
;; < ; a / > ;
}/> - < a > ; -; -a:b>; ; b.c > ; ; diff --git a/tests/baselines/reference/nestedRedeclarationInES6AMD.js b/tests/baselines/reference/nestedRedeclarationInES6AMD.js new file mode 100644 index 00000000000..bb90759dc8b --- /dev/null +++ b/tests/baselines/reference/nestedRedeclarationInES6AMD.js @@ -0,0 +1,15 @@ +//// [nestedRedeclarationInES6AMD.ts] +function a() { + { + let status = 1; + status = 2; + } +} + +//// [nestedRedeclarationInES6AMD.js] +function a() { + { + let status = 1; + status = 2; + } +} diff --git a/tests/baselines/reference/nestedRedeclarationInES6AMD.symbols b/tests/baselines/reference/nestedRedeclarationInES6AMD.symbols new file mode 100644 index 00000000000..65f310a7ed2 --- /dev/null +++ b/tests/baselines/reference/nestedRedeclarationInES6AMD.symbols @@ -0,0 +1,11 @@ +=== tests/cases/compiler/nestedRedeclarationInES6AMD.ts === +function a() { +>a : Symbol(a, Decl(nestedRedeclarationInES6AMD.ts, 0, 0)) + { + let status = 1; +>status : Symbol(status, Decl(nestedRedeclarationInES6AMD.ts, 2, 11)) + + status = 2; +>status : Symbol(status, Decl(nestedRedeclarationInES6AMD.ts, 2, 11)) + } +} diff --git a/tests/baselines/reference/nestedRedeclarationInES6AMD.types b/tests/baselines/reference/nestedRedeclarationInES6AMD.types new file mode 100644 index 00000000000..2b8d971e3c1 --- /dev/null +++ b/tests/baselines/reference/nestedRedeclarationInES6AMD.types @@ -0,0 +1,14 @@ +=== tests/cases/compiler/nestedRedeclarationInES6AMD.ts === +function a() { +>a : () => void + { + let status = 1; +>status : number +>1 : number + + status = 2; +>status = 2 : number +>status : number +>2 : number + } +} diff --git a/tests/baselines/reference/objectLiteralExcessProperties.errors.txt b/tests/baselines/reference/objectLiteralExcessProperties.errors.txt new file mode 100644 index 00000000000..84f635bf947 --- /dev/null +++ b/tests/baselines/reference/objectLiteralExcessProperties.errors.txt @@ -0,0 +1,66 @@ +tests/cases/compiler/objectLiteralExcessProperties.ts(9,18): error TS2322: Type '{ forword: string; }' is not assignable to type 'Book'. + Object literal may only specify known properties, and 'forword' does not exist in type 'Book'. +tests/cases/compiler/objectLiteralExcessProperties.ts(11,27): error TS2322: Type '{ foreward: string; }' is not assignable to type 'Book | string'. + Object literal may only specify known properties, and 'foreward' does not exist in type 'Book | string'. +tests/cases/compiler/objectLiteralExcessProperties.ts(13,53): error TS2322: Type '({ foreword: string; } | { forwards: string; })[]' is not assignable to type 'Book | Book[]'. + Type '({ foreword: string; } | { forwards: string; })[]' is not assignable to type 'Book[]'. + Type '{ foreword: string; } | { forwards: string; }' is not assignable to type 'Book'. + Type '{ forwards: string; }' is not assignable to type 'Book'. + Object literal may only specify known properties, and 'forwards' does not exist in type 'Book'. +tests/cases/compiler/objectLiteralExcessProperties.ts(15,42): error TS2322: Type '{ foreword: string; colour: string; }' is not assignable to type 'Book & Cover'. + Object literal may only specify known properties, and 'colour' does not exist in type 'Book & Cover'. +tests/cases/compiler/objectLiteralExcessProperties.ts(17,26): error TS2322: Type '{ foreward: string; color: string; }' is not assignable to type 'Book & Cover'. + Object literal may only specify known properties, and 'foreward' does not exist in type 'Book & Cover'. +tests/cases/compiler/objectLiteralExcessProperties.ts(19,57): error TS2322: Type '{ foreword: string; color: string; price: number; }' is not assignable to type 'Book & Cover'. + Object literal may only specify known properties, and 'price' does not exist in type 'Book & Cover'. +tests/cases/compiler/objectLiteralExcessProperties.ts(21,43): error TS2322: Type '{ foreword: string; price: number; }' is not assignable to type 'Book & number'. + Object literal may only specify known properties, and 'price' does not exist in type 'Book & number'. + + +==== tests/cases/compiler/objectLiteralExcessProperties.ts (7 errors) ==== + interface Book { + foreword: string; + } + + interface Cover { + color?: string; + } + + var b1: Book = { forword: "oops" }; + ~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ forword: string; }' is not assignable to type 'Book'. +!!! error TS2322: Object literal may only specify known properties, and 'forword' does not exist in type 'Book'. + + var b2: Book | string = { foreward: "nope" }; + ~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ foreward: string; }' is not assignable to type 'Book | string'. +!!! error TS2322: Object literal may only specify known properties, and 'foreward' does not exist in type 'Book | string'. + + var b3: Book | (Book[]) = [{ foreword: "hello" }, { forwards: "back" }]; + ~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '({ foreword: string; } | { forwards: string; })[]' is not assignable to type 'Book | Book[]'. +!!! error TS2322: Type '({ foreword: string; } | { forwards: string; })[]' is not assignable to type 'Book[]'. +!!! error TS2322: Type '{ foreword: string; } | { forwards: string; }' is not assignable to type 'Book'. +!!! error TS2322: Type '{ forwards: string; }' is not assignable to type 'Book'. +!!! error TS2322: Object literal may only specify known properties, and 'forwards' does not exist in type 'Book'. + + var b4: Book & Cover = { foreword: "hi", colour: "blue" }; + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ foreword: string; colour: string; }' is not assignable to type 'Book & Cover'. +!!! error TS2322: Object literal may only specify known properties, and 'colour' does not exist in type 'Book & Cover'. + + var b5: Book & Cover = { foreward: "hi", color: "blue" }; + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ foreward: string; color: string; }' is not assignable to type 'Book & Cover'. +!!! error TS2322: Object literal may only specify known properties, and 'foreward' does not exist in type 'Book & Cover'. + + var b6: Book & Cover = { foreword: "hi", color: "blue", price: 10.99 }; + ~~~~~~~~~~~~ +!!! error TS2322: Type '{ foreword: string; color: string; price: number; }' is not assignable to type 'Book & Cover'. +!!! error TS2322: Object literal may only specify known properties, and 'price' does not exist in type 'Book & Cover'. + + var b7: Book & number = { foreword: "hi", price: 10.99 }; + ~~~~~~~~~~~~ +!!! error TS2322: Type '{ foreword: string; price: number; }' is not assignable to type 'Book & number'. +!!! error TS2322: Object literal may only specify known properties, and 'price' does not exist in type 'Book & number'. + \ No newline at end of file diff --git a/tests/baselines/reference/objectLiteralExcessProperties.js b/tests/baselines/reference/objectLiteralExcessProperties.js new file mode 100644 index 00000000000..747928ccb20 --- /dev/null +++ b/tests/baselines/reference/objectLiteralExcessProperties.js @@ -0,0 +1,32 @@ +//// [objectLiteralExcessProperties.ts] +interface Book { + foreword: string; +} + +interface Cover { + color?: string; +} + +var b1: Book = { forword: "oops" }; + +var b2: Book | string = { foreward: "nope" }; + +var b3: Book | (Book[]) = [{ foreword: "hello" }, { forwards: "back" }]; + +var b4: Book & Cover = { foreword: "hi", colour: "blue" }; + +var b5: Book & Cover = { foreward: "hi", color: "blue" }; + +var b6: Book & Cover = { foreword: "hi", color: "blue", price: 10.99 }; + +var b7: Book & number = { foreword: "hi", price: 10.99 }; + + +//// [objectLiteralExcessProperties.js] +var b1 = { forword: "oops" }; +var b2 = { foreward: "nope" }; +var b3 = [{ foreword: "hello" }, { forwards: "back" }]; +var b4 = { foreword: "hi", colour: "blue" }; +var b5 = { foreward: "hi", color: "blue" }; +var b6 = { foreword: "hi", color: "blue", price: 10.99 }; +var b7 = { foreword: "hi", price: 10.99 }; diff --git a/tests/baselines/reference/tsxErrorRecovery2.errors.txt b/tests/baselines/reference/tsxErrorRecovery2.errors.txt new file mode 100644 index 00000000000..9a0b5790b2c --- /dev/null +++ b/tests/baselines/reference/tsxErrorRecovery2.errors.txt @@ -0,0 +1,18 @@ +tests/cases/conformance/jsx/file1.tsx(6,1): error TS2657: JSX expressions must have one parent element +tests/cases/conformance/jsx/file2.tsx(2,1): error TS2657: JSX expressions must have one parent element + + +==== tests/cases/conformance/jsx/file1.tsx (1 errors) ==== + + declare namespace JSX { interface Element { } } + +
+
+ + +!!! error TS2657: JSX expressions must have one parent element +==== tests/cases/conformance/jsx/file2.tsx (1 errors) ==== + var x =
+ + +!!! error TS2657: JSX expressions must have one parent element \ No newline at end of file diff --git a/tests/baselines/reference/tsxErrorRecovery2.js b/tests/baselines/reference/tsxErrorRecovery2.js new file mode 100644 index 00000000000..be5b6c73424 --- /dev/null +++ b/tests/baselines/reference/tsxErrorRecovery2.js @@ -0,0 +1,19 @@ +//// [tests/cases/conformance/jsx/tsxErrorRecovery2.tsx] //// + +//// [file1.tsx] + +declare namespace JSX { interface Element { } } + +
+
+ +//// [file2.tsx] +var x =
+ + +//// [file1.jsx] +
+ , +
; +//// [file2.jsx] +var x =
,
; diff --git a/tests/baselines/reference/tsxErrorRecovery3.errors.txt b/tests/baselines/reference/tsxErrorRecovery3.errors.txt new file mode 100644 index 00000000000..f7e4bc170a9 --- /dev/null +++ b/tests/baselines/reference/tsxErrorRecovery3.errors.txt @@ -0,0 +1,30 @@ +tests/cases/conformance/jsx/file1.tsx(4,2): error TS2304: Cannot find name 'React'. +tests/cases/conformance/jsx/file1.tsx(5,2): error TS2304: Cannot find name 'React'. +tests/cases/conformance/jsx/file1.tsx(6,1): error TS2657: JSX expressions must have one parent element +tests/cases/conformance/jsx/file2.tsx(1,10): error TS2304: Cannot find name 'React'. +tests/cases/conformance/jsx/file2.tsx(1,21): error TS2304: Cannot find name 'React'. +tests/cases/conformance/jsx/file2.tsx(2,1): error TS2657: JSX expressions must have one parent element + + +==== tests/cases/conformance/jsx/file1.tsx (3 errors) ==== + + declare namespace JSX { interface Element { } } + +
+ ~~~ +!!! error TS2304: Cannot find name 'React'. +
+ ~~~ +!!! error TS2304: Cannot find name 'React'. + + +!!! error TS2657: JSX expressions must have one parent element +==== tests/cases/conformance/jsx/file2.tsx (3 errors) ==== + var x =
+ ~~~ +!!! error TS2304: Cannot find name 'React'. + ~~~ +!!! error TS2304: Cannot find name 'React'. + + +!!! error TS2657: JSX expressions must have one parent element \ No newline at end of file diff --git a/tests/baselines/reference/tsxErrorRecovery3.js b/tests/baselines/reference/tsxErrorRecovery3.js new file mode 100644 index 00000000000..93b34a14c19 --- /dev/null +++ b/tests/baselines/reference/tsxErrorRecovery3.js @@ -0,0 +1,19 @@ +//// [tests/cases/conformance/jsx/tsxErrorRecovery3.tsx] //// + +//// [file1.tsx] + +declare namespace JSX { interface Element { } } + +
+
+ +//// [file2.tsx] +var x =
+ + +//// [file1.js] +React.createElement("div", null) + , + React.createElement("div", null); +//// [file2.js] +var x = React.createElement("div", null), React.createElement("div", null); diff --git a/tests/cases/compiler/nestedRedeclarationInES6AMD.ts b/tests/cases/compiler/nestedRedeclarationInES6AMD.ts new file mode 100644 index 00000000000..e518e354cd0 --- /dev/null +++ b/tests/cases/compiler/nestedRedeclarationInES6AMD.ts @@ -0,0 +1,8 @@ +// @target: ES6 +// @module: AMD +function a() { + { + let status = 1; + status = 2; + } +} \ No newline at end of file diff --git a/tests/cases/compiler/objectLiteralExcessProperties.ts b/tests/cases/compiler/objectLiteralExcessProperties.ts new file mode 100644 index 00000000000..0aa81703c33 --- /dev/null +++ b/tests/cases/compiler/objectLiteralExcessProperties.ts @@ -0,0 +1,21 @@ +interface Book { + foreword: string; +} + +interface Cover { + color?: string; +} + +var b1: Book = { forword: "oops" }; + +var b2: Book | string = { foreward: "nope" }; + +var b3: Book | (Book[]) = [{ foreword: "hello" }, { forwards: "back" }]; + +var b4: Book & Cover = { foreword: "hi", colour: "blue" }; + +var b5: Book & Cover = { foreward: "hi", color: "blue" }; + +var b6: Book & Cover = { foreword: "hi", color: "blue", price: 10.99 }; + +var b7: Book & number = { foreword: "hi", price: 10.99 }; diff --git a/tests/cases/conformance/jsx/tsxErrorRecovery2.tsx b/tests/cases/conformance/jsx/tsxErrorRecovery2.tsx new file mode 100644 index 00000000000..e189e0e7791 --- /dev/null +++ b/tests/cases/conformance/jsx/tsxErrorRecovery2.tsx @@ -0,0 +1,10 @@ +//@jsx: preserve + +//@filename: file1.tsx +declare namespace JSX { interface Element { } } + +
+
+ +//@filename: file2.tsx +var x =
diff --git a/tests/cases/conformance/jsx/tsxErrorRecovery3.tsx b/tests/cases/conformance/jsx/tsxErrorRecovery3.tsx new file mode 100644 index 00000000000..9d444b07cb2 --- /dev/null +++ b/tests/cases/conformance/jsx/tsxErrorRecovery3.tsx @@ -0,0 +1,10 @@ +//@jsx: react + +//@filename: file1.tsx +declare namespace JSX { interface Element { } } + +
+
+ +//@filename: file2.tsx +var x =
diff --git a/tests/cases/fourslash/formatAfterMultilineComment.ts b/tests/cases/fourslash/formatAfterMultilineComment.ts new file mode 100644 index 00000000000..b795ab5c8c9 --- /dev/null +++ b/tests/cases/fourslash/formatAfterMultilineComment.ts @@ -0,0 +1,7 @@ +/// +/////*foo +////*/"123123"; + +format.document(); +verify.currentFileContentIs(`/*foo +*/"123123";`)