Allowed comment directives to be multiline (#38228)

* Allowed comment directives to be multiline

* Added tests, and perhaps fixed a test runner bug?

* I think it's going to need a consistent variable to loop over

* Used dynamically computed indexes in verifies

* Added multiline tests

* Increased flexibility for multiline comment parsing

* Undid a couple of formatting changes; removed backslashes from multiline regexp

* Added baseline tests for multiline comment skipping

Co-authored-by: Orta Therox <orta.therox@gmail.com>
This commit is contained in:
Josh Goldberg 2020-05-06 16:09:29 -04:00 committed by GitHub
parent 4b08c0582d
commit be2eb8a2e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 867 additions and 213 deletions

File diff suppressed because one or more lines are too long

View File

@ -474,7 +474,7 @@ namespace ts {
export function createCommentDirectivesMap(sourceFile: SourceFile, commentDirectives: CommentDirective[]): CommentDirectivesMap {
const directivesByLine = createMapFromEntries(
commentDirectives.map(commentDirective => ([
`${getLineAndCharacterOfPosition(sourceFile, commentDirective.range.pos).line}`,
`${getLineAndCharacterOfPosition(sourceFile, commentDirective.range.end).line}`,
commentDirective,
]))
);

View File

@ -832,157 +832,162 @@ module m3 { }\
insertCode(source, index, "Fo");
});
describe("comment directives", () => {
const tsIgnoreComment = "// @ts-ignore";
const textWithIgnoreComment = `const x = 10;
function foo() {
// @ts-ignore
let y: string = x;
return y;
}
function bar() {
// @ts-ignore
let z : string = x;
return z;
}
function bar3() {
// @ts-ignore
let z : string = x;
return z;
}
foo();
bar();
bar3();`;
verifyScenario("when deleting ts-ignore comment", verifyDelete);
verifyScenario("when inserting ts-ignore comment", verifyInsert);
verifyScenario("when changing ts-ignore comment to blah", verifyChangeToBlah);
verifyScenario("when changing blah comment to ts-ignore", verifyChangeBackToDirective);
verifyScenario("when deleting blah comment", verifyDeletingBlah);
verifyScenario("when changing text that adds another comment", verifyChangeDirectiveType);
verifyScenario("when changing text that keeps the comment but adds more nodes", verifyReuseChange);
for (const tsIgnoreComment of [
"// @ts-ignore",
"/* @ts-ignore */",
"/*\n @ts-ignore */"
]) {
describe(`${tsIgnoreComment} comment directives`, () => {
const textWithIgnoreComment = `const x = 10;
function foo() {
${tsIgnoreComment}
let y: string = x;
return y;
}
function bar() {
${tsIgnoreComment}
let z : string = x;
return z;
}
function bar3() {
${tsIgnoreComment}
let z : string = x;
return z;
}
foo();
bar();
bar3();`;
verifyScenario("when deleting ts-ignore comment", verifyDelete);
verifyScenario("when inserting ts-ignore comment", verifyInsert);
verifyScenario("when changing ts-ignore comment to blah", verifyChangeToBlah);
verifyScenario("when changing blah comment to ts-ignore", verifyChangeBackToDirective);
verifyScenario("when deleting blah comment", verifyDeletingBlah);
verifyScenario("when changing text that adds another comment", verifyChangeDirectiveType);
verifyScenario("when changing text that keeps the comment but adds more nodes", verifyReuseChange);
function verifyCommentDirectives(oldText: IScriptSnapshot, newTextAndChange: { text: IScriptSnapshot; textChangeRange: TextChangeRange; }) {
const { incrementalNewTree, newTree } = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1);
assert.deepEqual(incrementalNewTree.commentDirectives, newTree.commentDirectives);
}
function verifyScenario(scenario: string, verifyChange: (atIndex: number, singleIgnore?: true) => void) {
it(`${scenario} - 0`, () => {
verifyChange(0);
});
it(`${scenario} - 1`, () => {
verifyChange(1);
});
it(`${scenario} - 2`, () => {
verifyChange(2);
});
it(`${scenario} - with single ts-ignore`, () => {
verifyChange(0, /*singleIgnore*/ true);
});
}
function getIndexOfTsIgnoreComment(atIndex: number) {
let index: number;
for (let i = 0; i <= atIndex; i++) {
index = textWithIgnoreComment.indexOf(tsIgnoreComment);
function verifyCommentDirectives(oldText: IScriptSnapshot, newTextAndChange: { text: IScriptSnapshot; textChangeRange: TextChangeRange; }) {
const { incrementalNewTree, newTree } = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1);
assert.deepEqual(incrementalNewTree.commentDirectives, newTree.commentDirectives);
}
return index!;
}
function textWithIgnoreCommentFrom(text: string, singleIgnore: true | undefined) {
if (!singleIgnore) return text;
const splits = text.split(tsIgnoreComment);
if (splits.length > 2) {
const tail = splits[splits.length - 2] + splits[splits.length - 1];
splits.length = splits.length - 2;
return splits.join(tsIgnoreComment) + tail;
function verifyScenario(scenario: string, verifyChange: (atIndex: number, singleIgnore?: true) => void) {
it(`${scenario} - 0`, () => {
verifyChange(0);
});
it(`${scenario} - 1`, () => {
verifyChange(1);
});
it(`${scenario} - 2`, () => {
verifyChange(2);
});
it(`${scenario} - with single ts-ignore`, () => {
verifyChange(0, /*singleIgnore*/ true);
});
}
else {
return splits.join(tsIgnoreComment);
function getIndexOfTsIgnoreComment(atIndex: number) {
let index = 0;
for (let i = 0; i <= atIndex; i++) {
index = textWithIgnoreComment.indexOf(tsIgnoreComment, index);
}
return index;
}
}
function verifyDelete(atIndex: number, singleIgnore?: true) {
const index = getIndexOfTsIgnoreComment(atIndex);
const oldText = ScriptSnapshot.fromString(textWithIgnoreCommentFrom(textWithIgnoreComment, singleIgnore));
const newTextAndChange = withDelete(oldText, index, tsIgnoreComment.length);
verifyCommentDirectives(oldText, newTextAndChange);
}
function textWithIgnoreCommentFrom(text: string, singleIgnore: true | undefined) {
if (!singleIgnore) return text;
const splits = text.split(tsIgnoreComment);
if (splits.length > 2) {
const tail = splits[splits.length - 2] + splits[splits.length - 1];
splits.length = splits.length - 2;
return splits.join(tsIgnoreComment) + tail;
}
else {
return splits.join(tsIgnoreComment);
}
}
function verifyInsert(atIndex: number, singleIgnore?: true) {
const index = getIndexOfTsIgnoreComment(atIndex);
const source = textWithIgnoreCommentFrom(textWithIgnoreComment.slice(0, index) + textWithIgnoreComment.slice(index + tsIgnoreComment.length), singleIgnore);
const oldText = ScriptSnapshot.fromString(source);
const newTextAndChange = withInsert(oldText, index, tsIgnoreComment);
verifyCommentDirectives(oldText, newTextAndChange);
}
function verifyDelete(atIndex: number, singleIgnore?: true) {
const index = getIndexOfTsIgnoreComment(atIndex);
const oldText = ScriptSnapshot.fromString(textWithIgnoreCommentFrom(textWithIgnoreComment, singleIgnore));
const newTextAndChange = withDelete(oldText, index, tsIgnoreComment.length);
verifyCommentDirectives(oldText, newTextAndChange);
}
function verifyChangeToBlah(atIndex: number, singleIgnore?: true) {
const index = getIndexOfTsIgnoreComment(atIndex) + "// ".length;
const oldText = ScriptSnapshot.fromString(textWithIgnoreCommentFrom(textWithIgnoreComment, singleIgnore));
const newTextAndChange = withChange(oldText, index, 1, "blah ");
verifyCommentDirectives(oldText, newTextAndChange);
}
function verifyInsert(atIndex: number, singleIgnore?: true) {
const index = getIndexOfTsIgnoreComment(atIndex);
const source = textWithIgnoreCommentFrom(textWithIgnoreComment.slice(0, index) + textWithIgnoreComment.slice(index + tsIgnoreComment.length), singleIgnore);
const oldText = ScriptSnapshot.fromString(source);
const newTextAndChange = withInsert(oldText, index, tsIgnoreComment);
verifyCommentDirectives(oldText, newTextAndChange);
}
function verifyChangeBackToDirective(atIndex: number, singleIgnore?: true) {
const index = getIndexOfTsIgnoreComment(atIndex) + "// ".length;
const source = textWithIgnoreCommentFrom(textWithIgnoreComment.slice(0, index) + "blah " + textWithIgnoreComment.slice(index + 1), singleIgnore);
const oldText = ScriptSnapshot.fromString(source);
const newTextAndChange = withChange(oldText, index, "blah ".length, "@");
verifyCommentDirectives(oldText, newTextAndChange);
}
function verifyChangeToBlah(atIndex: number, singleIgnore?: true) {
const index = getIndexOfTsIgnoreComment(atIndex) + tsIgnoreComment.indexOf("@");
const oldText = ScriptSnapshot.fromString(textWithIgnoreCommentFrom(textWithIgnoreComment, singleIgnore));
const newTextAndChange = withChange(oldText, index, 1, "blah ");
verifyCommentDirectives(oldText, newTextAndChange);
}
function verifyDeletingBlah(atIndex: number, singleIgnore?: true) {
const tsIgnoreIndex = getIndexOfTsIgnoreComment(atIndex);
const index = tsIgnoreIndex + "// ".length;
const source = textWithIgnoreCommentFrom(textWithIgnoreComment.slice(0, index) + "blah " + textWithIgnoreComment.slice(index + 1), singleIgnore);
const oldText = ScriptSnapshot.fromString(source);
const newTextAndChange = withDelete(oldText, tsIgnoreIndex, tsIgnoreComment.length + "blah".length);
verifyCommentDirectives(oldText, newTextAndChange);
}
function verifyChangeBackToDirective(atIndex: number, singleIgnore?: true) {
const index = getIndexOfTsIgnoreComment(atIndex) + tsIgnoreComment.indexOf("@");
const source = textWithIgnoreCommentFrom(textWithIgnoreComment.slice(0, index) + "blah " + textWithIgnoreComment.slice(index + 1), singleIgnore);
const oldText = ScriptSnapshot.fromString(source);
const newTextAndChange = withChange(oldText, index, "blah ".length, "@");
verifyCommentDirectives(oldText, newTextAndChange);
}
function verifyChangeDirectiveType(atIndex: number, singleIgnore?: true) {
const index = getIndexOfTsIgnoreComment(atIndex) + "// @ts-".length;
const oldText = ScriptSnapshot.fromString(textWithIgnoreCommentFrom(textWithIgnoreComment, singleIgnore));
const newTextAndChange = withChange(oldText, index, "ignore".length, "expect-error");
verifyCommentDirectives(oldText, newTextAndChange);
}
function verifyDeletingBlah(atIndex: number, singleIgnore?: true) {
const tsIgnoreIndex = getIndexOfTsIgnoreComment(atIndex);
const index = tsIgnoreIndex + tsIgnoreComment.indexOf("@");
const source = textWithIgnoreCommentFrom(textWithIgnoreComment.slice(0, index) + "blah " + textWithIgnoreComment.slice(index + 1), singleIgnore);
const oldText = ScriptSnapshot.fromString(source);
const newTextAndChange = withDelete(oldText, tsIgnoreIndex, tsIgnoreComment.length + "blah".length);
verifyCommentDirectives(oldText, newTextAndChange);
}
function verifyReuseChange(atIndex: number, singleIgnore?: true) {
const source = `const x = 10;
function foo1() {
const x1 = 10;
// @ts-ignore
let y0: string = x;
let y1: string = x;
return y1;
}
function foo2() {
const x2 = 10;
// @ts-ignore
let y0: string = x;
let y2: string = x;
return y2;
}
function foo3() {
const x3 = 10;
// @ts-ignore
let y0: string = x;
let y3: string = x;
return y3;
}
foo1();
foo2();
foo3();`;
const oldText = ScriptSnapshot.fromString(textWithIgnoreCommentFrom(source, singleIgnore));
const start = source.indexOf(`const x${atIndex + 1}`);
const letStr = `let y${atIndex + 1}: string = x;`;
const end = source.indexOf(letStr) + letStr.length;
const oldSubStr = source.slice(start, end);
const newText = oldSubStr.replace(letStr, `let yn : string = x;`);
const newTextAndChange = withChange(oldText, start, end - start, newText);
verifyCommentDirectives(oldText, newTextAndChange);
}
});
function verifyChangeDirectiveType(atIndex: number, singleIgnore?: true) {
const index = getIndexOfTsIgnoreComment(atIndex) + tsIgnoreComment.indexOf("ignore");
const oldText = ScriptSnapshot.fromString(textWithIgnoreCommentFrom(textWithIgnoreComment, singleIgnore));
const newTextAndChange = withChange(oldText, index, "ignore".length, "expect-error");
verifyCommentDirectives(oldText, newTextAndChange);
}
function verifyReuseChange(atIndex: number, singleIgnore?: true) {
const source = `const x = 10;
function foo1() {
const x1 = 10;
${tsIgnoreComment}
let y0: string = x;
let y1: string = x;
return y1;
}
function foo2() {
const x2 = 10;
${tsIgnoreComment}
let y0: string = x;
let y2: string = x;
return y2;
}
function foo3() {
const x3 = 10;
${tsIgnoreComment}
let y0: string = x;
let y3: string = x;
return y3;
}
foo1();
foo2();
foo3();`;
const oldText = ScriptSnapshot.fromString(textWithIgnoreCommentFrom(source, singleIgnore));
const start = source.indexOf(`const x${atIndex + 1}`);
const letStr = `let y${atIndex + 1}: string = x;`;
const end = source.indexOf(letStr) + letStr.length;
const oldSubStr = source.slice(start, end);
const newText = oldSubStr.replace(letStr, `let yn : string = x;`);
const newTextAndChange = withChange(oldText, start, end - start, newText);
verifyCommentDirectives(oldText, newTextAndChange);
}
});
}
});
}

View File

@ -0,0 +1,53 @@
tests/cases/compiler/a.js(29,1): error TS2349: This expression is not callable.
Type 'Number' has no call signatures.
tests/cases/compiler/a.js(35,1): error TS2349: This expression is not callable.
Type 'Number' has no call signatures.
==== tests/cases/compiler/a.js (2 errors) ====
var x = 0;
/// @ts-ignore
x();
/// @ts-ignore
x();
/// @ts-ignore
x(
2,
3);
// @ts-ignore
// come comment
// some other comment
// @another
x();
/* @ts-ignore */
/*another comment
that could be multiline*/
x();
~
!!! error TS2349: This expression is not callable.
!!! error TS2349: Type 'Number' has no call signatures.
/* @ts-ignore
continuing comment
that could be multiline*/
x();
~
!!! error TS2349: This expression is not callable.
!!! error TS2349: Type 'Number' has no call signatures.
// @ts-ignore: no call signature
x();

View File

@ -29,6 +29,20 @@ x(
x();
>x : Symbol(x, Decl(a.js, 0, 3))
/* @ts-ignore */
/*another comment
that could be multiline*/
x();
>x : Symbol(x, Decl(a.js, 0, 3))
/* @ts-ignore
continuing comment
that could be multiline*/
x();
>x : Symbol(x, Decl(a.js, 0, 3))
// @ts-ignore: no call signature

View File

@ -6,17 +6,17 @@ var x = 0;
/// @ts-ignore
x();
>x() : error
>x() : any
>x : number
/// @ts-ignore
x();
>x() : error
>x() : any
>x : number
/// @ts-ignore
x(
>x( 2, 3) : error
>x( 2, 3) : any
>x : number
2,
@ -34,13 +34,29 @@ x(
// @another
x();
>x() : error
>x() : any
>x : number
/* @ts-ignore */
/*another comment
that could be multiline*/
x();
>x() : any
>x : number
/* @ts-ignore
continuing comment
that could be multiline*/
x();
>x() : any
>x : number
// @ts-ignore: no call signature
x();
>x() : error
>x() : any
>x : number

View File

@ -0,0 +1,60 @@
tests/cases/conformance/directives/a.ts(12,1): error TS2578: Unused '@ts-expect-error' directive.
tests/cases/conformance/directives/b.tsx(32,1): error TS2578: Unused '@ts-expect-error' directive.
==== tests/cases/conformance/directives/a.ts (1 errors) ====
export const texts: string[] = [];
/**
@ts-ignore */
texts.push(100);
/**
@ts-expect-error */
texts.push(100);
/**
@ts-expect-error */
~~~~~~~~~~~~~~~~~~~~
!!! error TS2578: Unused '@ts-expect-error' directive.
texts.push("100");
==== tests/cases/conformance/directives/b.tsx (1 errors) ====
import * as React from "react";
export function MyComponent(props: { foo: string }) {
return <div />;
}
let x = (
<div>
{/*
@ts-ignore */}
<MyComponent foo={100} />
{/*@ts-ignore*/}
<MyComponent foo={100} />
{/*
@ts-expect-error */}
<MyComponent foo={100} />
{/*
// @ts-expect-error */}
<MyComponent foo={100} />
{/*
* @ts-expect-error */}
<MyComponent foo={100} />
{/*@ts-expect-error*/}
<MyComponent foo={100} />
{/*
@ts-expect-error */}
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2578: Unused '@ts-expect-error' directive.
<MyComponent foo={"hooray"} />
</div>
);

View File

@ -0,0 +1,86 @@
//// [tests/cases/conformance/directives/multiline.tsx] ////
//// [a.ts]
export const texts: string[] = [];
/**
@ts-ignore */
texts.push(100);
/**
@ts-expect-error */
texts.push(100);
/**
@ts-expect-error */
texts.push("100");
//// [b.tsx]
import * as React from "react";
export function MyComponent(props: { foo: string }) {
return <div />;
}
let x = (
<div>
{/*
@ts-ignore */}
<MyComponent foo={100} />
{/*@ts-ignore*/}
<MyComponent foo={100} />
{/*
@ts-expect-error */}
<MyComponent foo={100} />
{/*
// @ts-expect-error */}
<MyComponent foo={100} />
{/*
* @ts-expect-error */}
<MyComponent foo={100} />
{/*@ts-expect-error*/}
<MyComponent foo={100} />
{/*
@ts-expect-error */}
<MyComponent foo={"hooray"} />
</div>
);
//// [a.js]
"use strict";
exports.__esModule = true;
exports.texts = void 0;
exports.texts = [];
/**
@ts-ignore */
exports.texts.push(100);
/**
@ts-expect-error */
exports.texts.push(100);
/**
@ts-expect-error */
exports.texts.push("100");
//// [b.js]
"use strict";
exports.__esModule = true;
exports.MyComponent = void 0;
var React = require("react");
function MyComponent(props) {
return React.createElement("div", null);
}
exports.MyComponent = MyComponent;
var x = (React.createElement("div", null,
React.createElement(MyComponent, { foo: 100 }),
React.createElement(MyComponent, { foo: 100 }),
React.createElement(MyComponent, { foo: 100 }),
React.createElement(MyComponent, { foo: 100 }),
React.createElement(MyComponent, { foo: 100 }),
React.createElement(MyComponent, { foo: 100 }),
React.createElement(MyComponent, { foo: "hooray" })));

View File

@ -0,0 +1,89 @@
=== tests/cases/conformance/directives/a.ts ===
export const texts: string[] = [];
>texts : Symbol(texts, Decl(a.ts, 0, 12))
/**
@ts-ignore */
texts.push(100);
>texts.push : Symbol(Array.push, Decl(lib.d.ts, --, --))
>texts : Symbol(texts, Decl(a.ts, 0, 12))
>push : Symbol(Array.push, Decl(lib.d.ts, --, --))
/**
@ts-expect-error */
texts.push(100);
>texts.push : Symbol(Array.push, Decl(lib.d.ts, --, --))
>texts : Symbol(texts, Decl(a.ts, 0, 12))
>push : Symbol(Array.push, Decl(lib.d.ts, --, --))
/**
@ts-expect-error */
texts.push("100");
>texts.push : Symbol(Array.push, Decl(lib.d.ts, --, --))
>texts : Symbol(texts, Decl(a.ts, 0, 12))
>push : Symbol(Array.push, Decl(lib.d.ts, --, --))
=== tests/cases/conformance/directives/b.tsx ===
import * as React from "react";
>React : Symbol(React, Decl(b.tsx, 0, 6))
export function MyComponent(props: { foo: string }) {
>MyComponent : Symbol(MyComponent, Decl(b.tsx, 0, 31))
>props : Symbol(props, Decl(b.tsx, 2, 28))
>foo : Symbol(foo, Decl(b.tsx, 2, 36))
return <div />;
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
}
let x = (
>x : Symbol(x, Decl(b.tsx, 6, 3))
<div>
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
{/*
@ts-ignore */}
<MyComponent foo={100} />
>MyComponent : Symbol(MyComponent, Decl(b.tsx, 0, 31))
>foo : Symbol(foo, Decl(b.tsx, 10, 16))
{/*@ts-ignore*/}
<MyComponent foo={100} />
>MyComponent : Symbol(MyComponent, Decl(b.tsx, 0, 31))
>foo : Symbol(foo, Decl(b.tsx, 13, 16))
{/*
@ts-expect-error */}
<MyComponent foo={100} />
>MyComponent : Symbol(MyComponent, Decl(b.tsx, 0, 31))
>foo : Symbol(foo, Decl(b.tsx, 17, 16))
{/*
// @ts-expect-error */}
<MyComponent foo={100} />
>MyComponent : Symbol(MyComponent, Decl(b.tsx, 0, 31))
>foo : Symbol(foo, Decl(b.tsx, 21, 16))
{/*
* @ts-expect-error */}
<MyComponent foo={100} />
>MyComponent : Symbol(MyComponent, Decl(b.tsx, 0, 31))
>foo : Symbol(foo, Decl(b.tsx, 25, 16))
{/*@ts-expect-error*/}
<MyComponent foo={100} />
>MyComponent : Symbol(MyComponent, Decl(b.tsx, 0, 31))
>foo : Symbol(foo, Decl(b.tsx, 28, 16))
{/*
@ts-expect-error */}
<MyComponent foo={"hooray"} />
>MyComponent : Symbol(MyComponent, Decl(b.tsx, 0, 31))
>foo : Symbol(foo, Decl(b.tsx, 32, 16))
</div>
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
);

View File

@ -0,0 +1,113 @@
=== tests/cases/conformance/directives/a.ts ===
export const texts: string[] = [];
>texts : string[]
>[] : undefined[]
/**
@ts-ignore */
texts.push(100);
>texts.push(100) : number
>texts.push : (...items: string[]) => number
>texts : string[]
>push : (...items: string[]) => number
>100 : 100
/**
@ts-expect-error */
texts.push(100);
>texts.push(100) : number
>texts.push : (...items: string[]) => number
>texts : string[]
>push : (...items: string[]) => number
>100 : 100
/**
@ts-expect-error */
texts.push("100");
>texts.push("100") : number
>texts.push : (...items: string[]) => number
>texts : string[]
>push : (...items: string[]) => number
>"100" : "100"
=== tests/cases/conformance/directives/b.tsx ===
import * as React from "react";
>React : typeof React
export function MyComponent(props: { foo: string }) {
>MyComponent : (props: { foo: string;}) => JSX.Element
>props : { foo: string; }
>foo : string
return <div />;
><div /> : JSX.Element
>div : any
}
let x = (
>x : JSX.Element
>( <div> {/* @ts-ignore */} <MyComponent foo={100} /> {/*@ts-ignore*/} <MyComponent foo={100} /> {/* @ts-expect-error */} <MyComponent foo={100} /> {/* // @ts-expect-error */} <MyComponent foo={100} /> {/* * @ts-expect-error */} <MyComponent foo={100} /> {/*@ts-expect-error*/} <MyComponent foo={100} /> {/* @ts-expect-error */} <MyComponent foo={"hooray"} /> </div>) : JSX.Element
<div>
><div> {/* @ts-ignore */} <MyComponent foo={100} /> {/*@ts-ignore*/} <MyComponent foo={100} /> {/* @ts-expect-error */} <MyComponent foo={100} /> {/* // @ts-expect-error */} <MyComponent foo={100} /> {/* * @ts-expect-error */} <MyComponent foo={100} /> {/*@ts-expect-error*/} <MyComponent foo={100} /> {/* @ts-expect-error */} <MyComponent foo={"hooray"} /> </div> : JSX.Element
>div : any
{/*
@ts-ignore */}
<MyComponent foo={100} />
><MyComponent foo={100} /> : JSX.Element
>MyComponent : (props: { foo: string; }) => JSX.Element
>foo : number
>100 : 100
{/*@ts-ignore*/}
<MyComponent foo={100} />
><MyComponent foo={100} /> : JSX.Element
>MyComponent : (props: { foo: string; }) => JSX.Element
>foo : number
>100 : 100
{/*
@ts-expect-error */}
<MyComponent foo={100} />
><MyComponent foo={100} /> : JSX.Element
>MyComponent : (props: { foo: string; }) => JSX.Element
>foo : number
>100 : 100
{/*
// @ts-expect-error */}
<MyComponent foo={100} />
><MyComponent foo={100} /> : JSX.Element
>MyComponent : (props: { foo: string; }) => JSX.Element
>foo : number
>100 : 100
{/*
* @ts-expect-error */}
<MyComponent foo={100} />
><MyComponent foo={100} /> : JSX.Element
>MyComponent : (props: { foo: string; }) => JSX.Element
>foo : number
>100 : 100
{/*@ts-expect-error*/}
<MyComponent foo={100} />
><MyComponent foo={100} /> : JSX.Element
>MyComponent : (props: { foo: string; }) => JSX.Element
>foo : number
>100 : 100
{/*
@ts-expect-error */}
<MyComponent foo={"hooray"} />
><MyComponent foo={"hooray"} /> : JSX.Element
>MyComponent : (props: { foo: string; }) => JSX.Element
>foo : string
>"hooray" : "hooray"
</div>
>div : any
);

View File

@ -1,27 +1,54 @@
tests/cases/conformance/directives/ts-expect-error.ts(4,1): error TS2578: Unused '@ts-expect-error' directive.
tests/cases/conformance/directives/ts-expect-error.ts(10,1): error TS2578: Unused '@ts-expect-error' directive.
tests/cases/conformance/directives/ts-expect-error.ts(13,5): error TS2322: Type '"nope"' is not assignable to type 'number'.
tests/cases/conformance/directives/ts-expect-error.ts(19,2): error TS2367: This condition will always return 'false' since the types 'true' and 'false' have no overlap.
tests/cases/conformance/directives/ts-expect-error.ts(21,2): error TS2367: This condition will always return 'false' since the types 'true' and 'false' have no overlap.
tests/cases/conformance/directives/ts-expect-error.ts(22,2): error TS2367: This condition will always return 'false' since the types 'true' and 'false' have no overlap.
tests/cases/conformance/directives/ts-expect-error.ts(8,1): error TS2578: Unused '@ts-expect-error' directive.
tests/cases/conformance/directives/ts-expect-error.ts(11,1): error TS2578: Unused '@ts-expect-error' directive.
tests/cases/conformance/directives/ts-expect-error.ts(21,1): error TS2578: Unused '@ts-expect-error' directive.
tests/cases/conformance/directives/ts-expect-error.ts(24,1): error TS2578: Unused '@ts-expect-error' directive.
tests/cases/conformance/directives/ts-expect-error.ts(28,1): error TS2578: Unused '@ts-expect-error' directive.
tests/cases/conformance/directives/ts-expect-error.ts(31,5): error TS2322: Type '"nope"' is not assignable to type 'number'.
tests/cases/conformance/directives/ts-expect-error.ts(37,2): error TS2367: This condition will always return 'false' since the types 'true' and 'false' have no overlap.
tests/cases/conformance/directives/ts-expect-error.ts(39,2): error TS2367: This condition will always return 'false' since the types 'true' and 'false' have no overlap.
tests/cases/conformance/directives/ts-expect-error.ts(40,2): error TS2367: This condition will always return 'false' since the types 'true' and 'false' have no overlap.
==== tests/cases/conformance/directives/ts-expect-error.ts (6 errors) ====
==== tests/cases/conformance/directives/ts-expect-error.ts (9 errors) ====
// @ts-expect-error additional commenting
var invalidCommentedFancy: number = 'nope';
var invalidCommentedFancySingle: number = 'nope';
/*
@ts-expect-error additional commenting */
var invalidCommentedFancyMulti: number = 'nope';
// @ts-expect-error additional commenting
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2578: Unused '@ts-expect-error' directive.
var validCommentedFancy: string = 'nope';
var validCommentedFancySingle: string = 'nope';
/* @ts-expect-error additional commenting */
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2578: Unused '@ts-expect-error' directive.
var validCommentedFancyMulti: string = 'nope';
// @ts-expect-error
var invalidCommentedPlain: number = 'nope';
var invalidCommentedPlainSingle: number = 'nope';
/*
@ts-expect-error */
var invalidCommentedPlainMulti: number = 'nope';
// @ts-expect-error
~~~~~~~~~~~~~~~~~~~
!!! error TS2578: Unused '@ts-expect-error' directive.
var validCommentedPlain: string = 'nope';
var validCommentedPlainSingle: string = 'nope';
/* @ts-expect-error */
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2578: Unused '@ts-expect-error' directive.
var validCommentedPlainMulti1: string = 'nope';
/*
@ts-expect-error */
~~~~~~~~~~~~~~~~~~~
!!! error TS2578: Unused '@ts-expect-error' directive.
var validCommentedPlainMulti2: string = 'nope';
var invalidPlain: number = 'nope';
~~~~~~~~~~~~

View File

@ -1,15 +1,33 @@
//// [ts-expect-error.ts]
// @ts-expect-error additional commenting
var invalidCommentedFancy: number = 'nope';
var invalidCommentedFancySingle: number = 'nope';
/*
@ts-expect-error additional commenting */
var invalidCommentedFancyMulti: number = 'nope';
// @ts-expect-error additional commenting
var validCommentedFancy: string = 'nope';
var validCommentedFancySingle: string = 'nope';
/* @ts-expect-error additional commenting */
var validCommentedFancyMulti: string = 'nope';
// @ts-expect-error
var invalidCommentedPlain: number = 'nope';
var invalidCommentedPlainSingle: number = 'nope';
/*
@ts-expect-error */
var invalidCommentedPlainMulti: number = 'nope';
// @ts-expect-error
var validCommentedPlain: string = 'nope';
var validCommentedPlainSingle: string = 'nope';
/* @ts-expect-error */
var validCommentedPlainMulti1: string = 'nope';
/*
@ts-expect-error */
var validCommentedPlainMulti2: string = 'nope';
var invalidPlain: number = 'nope';
@ -24,13 +42,26 @@ var validPlain: string = 'nope';
//// [ts-expect-error.js]
// @ts-expect-error additional commenting
var invalidCommentedFancy = 'nope';
var invalidCommentedFancySingle = 'nope';
/*
@ts-expect-error additional commenting */
var invalidCommentedFancyMulti = 'nope';
// @ts-expect-error additional commenting
var validCommentedFancy = 'nope';
var validCommentedFancySingle = 'nope';
/* @ts-expect-error additional commenting */
var validCommentedFancyMulti = 'nope';
// @ts-expect-error
var invalidCommentedPlain = 'nope';
var invalidCommentedPlainSingle = 'nope';
/*
@ts-expect-error */
var invalidCommentedPlainMulti = 'nope';
// @ts-expect-error
var validCommentedPlain = 'nope';
var validCommentedPlainSingle = 'nope';
/* @ts-expect-error */
var validCommentedPlainMulti1 = 'nope';
/*
@ts-expect-error */
var validCommentedPlainMulti2 = 'nope';
var invalidPlain = 'nope';
var validPlain = 'nope';
// @ts-expect-error

View File

@ -1,44 +1,67 @@
=== tests/cases/conformance/directives/ts-expect-error.ts ===
// @ts-expect-error additional commenting
var invalidCommentedFancy: number = 'nope';
>invalidCommentedFancy : Symbol(invalidCommentedFancy, Decl(ts-expect-error.ts, 1, 3))
var invalidCommentedFancySingle: number = 'nope';
>invalidCommentedFancySingle : Symbol(invalidCommentedFancySingle, Decl(ts-expect-error.ts, 1, 3))
/*
@ts-expect-error additional commenting */
var invalidCommentedFancyMulti: number = 'nope';
>invalidCommentedFancyMulti : Symbol(invalidCommentedFancyMulti, Decl(ts-expect-error.ts, 5, 3))
// @ts-expect-error additional commenting
var validCommentedFancy: string = 'nope';
>validCommentedFancy : Symbol(validCommentedFancy, Decl(ts-expect-error.ts, 4, 3))
var validCommentedFancySingle: string = 'nope';
>validCommentedFancySingle : Symbol(validCommentedFancySingle, Decl(ts-expect-error.ts, 8, 3))
/* @ts-expect-error additional commenting */
var validCommentedFancyMulti: string = 'nope';
>validCommentedFancyMulti : Symbol(validCommentedFancyMulti, Decl(ts-expect-error.ts, 11, 3))
// @ts-expect-error
var invalidCommentedPlain: number = 'nope';
>invalidCommentedPlain : Symbol(invalidCommentedPlain, Decl(ts-expect-error.ts, 7, 3))
var invalidCommentedPlainSingle: number = 'nope';
>invalidCommentedPlainSingle : Symbol(invalidCommentedPlainSingle, Decl(ts-expect-error.ts, 14, 3))
/*
@ts-expect-error */
var invalidCommentedPlainMulti: number = 'nope';
>invalidCommentedPlainMulti : Symbol(invalidCommentedPlainMulti, Decl(ts-expect-error.ts, 18, 3))
// @ts-expect-error
var validCommentedPlain: string = 'nope';
>validCommentedPlain : Symbol(validCommentedPlain, Decl(ts-expect-error.ts, 10, 3))
var validCommentedPlainSingle: string = 'nope';
>validCommentedPlainSingle : Symbol(validCommentedPlainSingle, Decl(ts-expect-error.ts, 21, 3))
/* @ts-expect-error */
var validCommentedPlainMulti1: string = 'nope';
>validCommentedPlainMulti1 : Symbol(validCommentedPlainMulti1, Decl(ts-expect-error.ts, 24, 3))
/*
@ts-expect-error */
var validCommentedPlainMulti2: string = 'nope';
>validCommentedPlainMulti2 : Symbol(validCommentedPlainMulti2, Decl(ts-expect-error.ts, 28, 3))
var invalidPlain: number = 'nope';
>invalidPlain : Symbol(invalidPlain, Decl(ts-expect-error.ts, 12, 3))
>invalidPlain : Symbol(invalidPlain, Decl(ts-expect-error.ts, 30, 3))
var validPlain: string = 'nope';
>validPlain : Symbol(validPlain, Decl(ts-expect-error.ts, 14, 3))
>validPlain : Symbol(validPlain, Decl(ts-expect-error.ts, 32, 3))
// @ts-expect-error
(({ a: true } as const).a === false); // <-- compiles (as expected via comment)
>({ a: true } as const).a : Symbol(a, Decl(ts-expect-error.ts, 17, 3))
>a : Symbol(a, Decl(ts-expect-error.ts, 17, 3))
>a : Symbol(a, Decl(ts-expect-error.ts, 17, 3))
>({ a: true } as const).a : Symbol(a, Decl(ts-expect-error.ts, 35, 3))
>a : Symbol(a, Decl(ts-expect-error.ts, 35, 3))
>a : Symbol(a, Decl(ts-expect-error.ts, 35, 3))
(({ a: true } as const).a === false); // Should error
>({ a: true } as const).a : Symbol(a, Decl(ts-expect-error.ts, 18, 3))
>a : Symbol(a, Decl(ts-expect-error.ts, 18, 3))
>a : Symbol(a, Decl(ts-expect-error.ts, 18, 3))
>({ a: true } as const).a : Symbol(a, Decl(ts-expect-error.ts, 36, 3))
>a : Symbol(a, Decl(ts-expect-error.ts, 36, 3))
>a : Symbol(a, Decl(ts-expect-error.ts, 36, 3))
(({ a: true } as const).a === false); // error
>({ a: true } as const).a : Symbol(a, Decl(ts-expect-error.ts, 20, 3))
>a : Symbol(a, Decl(ts-expect-error.ts, 20, 3))
>a : Symbol(a, Decl(ts-expect-error.ts, 20, 3))
>({ a: true } as const).a : Symbol(a, Decl(ts-expect-error.ts, 38, 3))
>a : Symbol(a, Decl(ts-expect-error.ts, 38, 3))
>a : Symbol(a, Decl(ts-expect-error.ts, 38, 3))
(({ a: true } as const).a === false); // error
>({ a: true } as const).a : Symbol(a, Decl(ts-expect-error.ts, 21, 3))
>a : Symbol(a, Decl(ts-expect-error.ts, 21, 3))
>a : Symbol(a, Decl(ts-expect-error.ts, 21, 3))
>({ a: true } as const).a : Symbol(a, Decl(ts-expect-error.ts, 39, 3))
>a : Symbol(a, Decl(ts-expect-error.ts, 39, 3))
>a : Symbol(a, Decl(ts-expect-error.ts, 39, 3))

View File

@ -1,22 +1,50 @@
=== tests/cases/conformance/directives/ts-expect-error.ts ===
// @ts-expect-error additional commenting
var invalidCommentedFancy: number = 'nope';
>invalidCommentedFancy : number
var invalidCommentedFancySingle: number = 'nope';
>invalidCommentedFancySingle : number
>'nope' : "nope"
/*
@ts-expect-error additional commenting */
var invalidCommentedFancyMulti: number = 'nope';
>invalidCommentedFancyMulti : number
>'nope' : "nope"
// @ts-expect-error additional commenting
var validCommentedFancy: string = 'nope';
>validCommentedFancy : string
var validCommentedFancySingle: string = 'nope';
>validCommentedFancySingle : string
>'nope' : "nope"
/* @ts-expect-error additional commenting */
var validCommentedFancyMulti: string = 'nope';
>validCommentedFancyMulti : string
>'nope' : "nope"
// @ts-expect-error
var invalidCommentedPlain: number = 'nope';
>invalidCommentedPlain : number
var invalidCommentedPlainSingle: number = 'nope';
>invalidCommentedPlainSingle : number
>'nope' : "nope"
/*
@ts-expect-error */
var invalidCommentedPlainMulti: number = 'nope';
>invalidCommentedPlainMulti : number
>'nope' : "nope"
// @ts-expect-error
var validCommentedPlain: string = 'nope';
>validCommentedPlain : string
var validCommentedPlainSingle: string = 'nope';
>validCommentedPlainSingle : string
>'nope' : "nope"
/* @ts-expect-error */
var validCommentedPlainMulti1: string = 'nope';
>validCommentedPlainMulti1 : string
>'nope' : "nope"
/*
@ts-expect-error */
var validCommentedPlainMulti2: string = 'nope';
>validCommentedPlainMulti2 : string
>'nope' : "nope"
var invalidPlain: number = 'nope';

View File

@ -27,6 +27,18 @@ x(
x();
/* @ts-ignore */
/*another comment
that could be multiline*/
x();
/* @ts-ignore
continuing comment
that could be multiline*/
x();
// @ts-ignore: no call signature

View File

@ -0,0 +1,53 @@
// @filename: a.ts
export const texts: string[] = [];
/**
@ts-ignore */
texts.push(100);
/**
@ts-expect-error */
texts.push(100);
/**
@ts-expect-error */
texts.push("100");
// @filename: b.tsx
// @jsx: react
// @libFiles: react.d.ts,lib.d.ts
import * as React from "react";
export function MyComponent(props: { foo: string }) {
return <div />;
}
let x = (
<div>
{/*
@ts-ignore */}
<MyComponent foo={100} />
{/*@ts-ignore*/}
<MyComponent foo={100} />
{/*
@ts-expect-error */}
<MyComponent foo={100} />
{/*
// @ts-expect-error */}
<MyComponent foo={100} />
{/*
* @ts-expect-error */}
<MyComponent foo={100} />
{/*@ts-expect-error*/}
<MyComponent foo={100} />
{/*
@ts-expect-error */}
<MyComponent foo={"hooray"} />
</div>
);

View File

@ -1,14 +1,32 @@
// @ts-expect-error additional commenting
var invalidCommentedFancy: number = 'nope';
var invalidCommentedFancySingle: number = 'nope';
/*
@ts-expect-error additional commenting */
var invalidCommentedFancyMulti: number = 'nope';
// @ts-expect-error additional commenting
var validCommentedFancy: string = 'nope';
var validCommentedFancySingle: string = 'nope';
/* @ts-expect-error additional commenting */
var validCommentedFancyMulti: string = 'nope';
// @ts-expect-error
var invalidCommentedPlain: number = 'nope';
var invalidCommentedPlainSingle: number = 'nope';
/*
@ts-expect-error */
var invalidCommentedPlainMulti: number = 'nope';
// @ts-expect-error
var validCommentedPlain: string = 'nope';
var validCommentedPlainSingle: string = 'nope';
/* @ts-expect-error */
var validCommentedPlainMulti1: string = 'nope';
/*
@ts-expect-error */
var validCommentedPlainMulti2: string = 'nope';
var invalidPlain: number = 'nope';