diff --git a/autotests/folding/test.ts.fold b/autotests/folding/test.ts.fold --- a/autotests/folding/test.ts.fold +++ b/autotests/folding/test.ts.fold @@ -198,6 +198,15 @@ return "returning a string"; } +let x = (foo === null || foo === undefined) ? + undefined : + foo.bar.baz(); +let y = (foo === null || foo === undefined) ? /* comment */ undefined : + foo.bar.baz(); + +// Operator ?? +let x = foo ?? bar(); + // Types and logical `&&` and `||` operators after `as` expression Date as any || null; @@ -223,3 +232,49 @@ // Template const a = `6` / 2; /*comment*/ const b = 5; console.log(`4` / `2`); // 2 + + [1, 2, 3].reduce[]>((previous) => previous, []); + +// Multiline arrow assignment +const h = { + setSubProperty: < + T extends A, + K extends keyof T, + J extends keyof T[K] + >( + property: K, + key: J, + value: T[K][J] + ) => {} +} + +// Private-Named Instance Fields +class Greeter { + #name: string; + constructor(name: string) { + this.#name = name; + } + greet() { + console.log(`hello ${this.#name}`); + } +} +class Test { + #NAME1: () => string; + prop1 = x.#NAMEabc.#NAMEabc; + prop2 = x.#NAMEabc.#NAMEabc(); + prop3 = this.#NAMEabc.#NAME(); +} + +// Type-only imports and exports +import type T from "mod"; +import type { U, V } from "mod"; +import type * as types from "mod"; +import type from "mod"; +import type = require("mod"); +import type T = require("mod"); + +export { a as b, x }; +export * from "AnotherModule"; +export { k as m, l } from "AnotherModule"; +export type { T }; +export type { U } from "AnotherModule"; diff --git a/autotests/folding/test.tsx.fold b/autotests/folding/test.tsx.fold --- a/autotests/folding/test.tsx.fold +++ b/autotests/folding/test.tsx.fold @@ -151,3 +151,8 @@ /* comment */ ? /*comment*/# + +// Conditionals expressions +let y = foo == null ? null : />; +let x = (foo === null || foo === undefined) ? + undefined :>hello>; diff --git a/autotests/html/test.ts.html b/autotests/html/test.ts.html --- a/autotests/html/test.ts.html +++ b/autotests/html/test.ts.html @@ -204,17 +204,26 @@ return <T extends B ? never : string>"returning a string"; } +let x = (foo === null || foo === undefined) ? + undefined : + foo.bar.baz(); +let y = (foo === null || foo === undefined) ? /* comment */ undefined : + foo.bar.baz(); + +// Operator ?? +let x = foo ?? bar(); + // Types and logical `&&` and `||` operators after `as` expression Date as any || null; //Assertions const assert: (value: unknown) => asserts value = value => {} -declare function assertIsString(value: unknown): asserts value is string; -declare function assertIsArrayOfStrings(value: unknown): asserts value is string[]; -declare function assertDefined<T>(value: T): asserts value is NonNullable<T>; +declare function assertIsString(value: unknown): asserts value is string; +declare function assertIsArrayOfStrings(value: unknown): asserts value is string[]; +declare function assertDefined<T>(value: T): asserts value is NonNullable<T>; namespace Debug { - export declare function assert(value: unknown, message?: string): asserts value; - export declare function assertDefined<T>(value: T): asserts value is NonNullable<T>; + export declare function assert(value: unknown, message?: string): asserts value; + export declare function assertDefined<T>(value: T): asserts value is NonNullable<T>; } // Only highlight valid regular expressions, of a single line, after strings @@ -229,4 +238,50 @@ // Template const a = `6` / 2; /*comment*/ const b = 5; console.log(`4` / `2`); // 2 + + [1, 2, 3].reduce<readonly number[]>((previous) => previous, []); + +// Multiline arrow assignment +const h = { + setSubProperty: < + T extends A, + K extends keyof T, + J extends keyof T[K] + >( + property: K, + key: J, + value: T[K][J] + ) => {} +} + +// Private-Named Instance Fields +class Greeter { + #name: string; + constructor(name: string) { + this.#name = name; + } + greet() { + console.log(`hello ${this.#name}`); + } +} +class Test { + #NAME1: () => string; + prop1 = x.#NAMEabc.#NAMEabc; + prop2 = x.#NAMEabc.#NAMEabc(); + prop3 = this.#NAMEabc.#NAME(); +} + +// Type-only imports and exports +import type T from "mod"; +import type { U, V } from "mod"; +import type * as types from "mod"; +import type from "mod"; +import type = require("mod"); +import type T = require("mod"); + +export { a as b, x }; +export * from "AnotherModule"; +export { k as m, l } from "AnotherModule"; +export type { T }; +export type { U } from "AnotherModule"; diff --git a/autotests/html/test.tsx.html b/autotests/html/test.tsx.html --- a/autotests/html/test.tsx.html +++ b/autotests/html/test.tsx.html @@ -157,4 +157,9 @@ <noTag /* comment */ ? <noTag# <noTag/*comment*/# + +// Conditionals expressions +let y = foo == null ? null : <Tag/>; +let x = (foo === null || foo === undefined) ? + undefined :<tag>hello</tag>; diff --git a/autotests/input/test.ts b/autotests/input/test.ts --- a/autotests/input/test.ts +++ b/autotests/input/test.ts @@ -198,6 +198,15 @@ return "returning a string"; } +let x = (foo === null || foo === undefined) ? + undefined : + foo.bar.baz(); +let y = (foo === null || foo === undefined) ? /* comment */ undefined : + foo.bar.baz(); + +// Operator ?? +let x = foo ?? bar(); + // Types and logical `&&` and `||` operators after `as` expression Date as any || null; @@ -223,3 +232,49 @@ // Template const a = `6` / 2; /*comment*/ const b = 5; console.log(`4` / `2`); // 2 + + [1, 2, 3].reduce((previous) => previous, []); + +// Multiline arrow assignment +const h = { + setSubProperty: < + T extends A, + K extends keyof T, + J extends keyof T[K] + >( + property: K, + key: J, + value: T[K][J] + ) => {} +} + +// Private-Named Instance Fields +class Greeter { + #name: string; + constructor(name: string) { + this.#name = name; + } + greet() { + console.log(`hello ${this.#name}`); + } +} +class Test { + #NAME1: () => string; + prop1 = x.#NAMEabc.#NAMEabc; + prop2 = x.#NAMEabc.#NAMEabc(); + prop3 = this.#NAMEabc.#NAME(); +} + +// Type-only imports and exports +import type T from "mod"; +import type { U, V } from "mod"; +import type * as types from "mod"; +import type from "mod"; +import type = require("mod"); +import type T = require("mod"); + +export { a as b, x }; +export * from "AnotherModule"; +export { k as m, l } from "AnotherModule"; +export type { T }; +export type { U } from "AnotherModule"; diff --git a/autotests/input/test.tsx b/autotests/input/test.tsx --- a/autotests/input/test.tsx +++ b/autotests/input/test.tsx @@ -151,3 +151,8 @@ ; +let x = (foo === null || foo === undefined) ? + undefined :hello; diff --git a/autotests/reference/highlight.php.ref b/autotests/reference/highlight.php.ref --- a/autotests/reference/highlight.php.ref +++ b/autotests/reference/highlight.php.ref @@ -40,8 +40,8 @@ $timestamp = time(); ?>
class DateTime {
info: string;
- constructor() { this.info = echo(date("F d, Y h:i:s", $timestamp)); ?>; }
- get() { return this.info; }
+ constructor() { this.info = echo(date("F d, Y h:i:s", $timestamp)); ?>; }
+ get() { return this.info; }
}


diff --git a/autotests/reference/test.htm.ref b/autotests/reference/test.htm.ref --- a/autotests/reference/test.htm.ref +++ b/autotests/reference/test.htm.ref @@ -21,7 +21,7 @@ type="text/typescript">
class Student {
fullName: string;
- constructor(public firstName: string, public middleInitial: string, public lastName: string) {
+ constructor(public firstName: string, public middleInitial: string, public lastName: string) {
this.fullName = firstName + " " + middleInitial + " " + lastName;
}
}
diff --git a/autotests/reference/test.markdown.ref b/autotests/reference/test.markdown.ref --- a/autotests/reference/test.markdown.ref +++ b/autotests/reference/test.markdown.ref @@ -456,7 +456,7 @@ ```ts
class Student {
fullName: string;
- constructor(public firstName: string, public middleInitial: string, public lastName: string) {
+ constructor(public firstName: string, public middleInitial: string, public lastName: string) {
this.fullName = firstName + " " + middleInitial + " " + lastName;
}
}
diff --git a/autotests/reference/test.ts.ref b/autotests/reference/test.ts.ref --- a/autotests/reference/test.ts.ref +++ b/autotests/reference/test.ts.ref @@ -4,7 +4,7 @@
class Student {
fullName: string;
- constructor(public firstName: string, public middleInitial: string, public lastName: string) {
+ constructor(public firstName: string, public middleInitial: string, public lastName: string) {
this.fullName = firstName + " " + middleInitial + " " + lastName;
}
}
@@ -14,15 +14,15 @@ lastName: string;
}

-function greeter(person : Person) {
+function greeter(person : Person) {
return "Hello, " + person.firstName + " " + person.lastName;
}

let user = new Student("Jane", "M.", "User");

// Built-in
-document.body.innerHTML = greeter(user); to
-JSON.stringify()
+document.body.innerHTML = greeter(user); to
+JSON.stringify()
console.log("Hello world");
const os = require('os');
Math.LOG10E;
@@ -38,24 +38,24 @@ const baseUrl = new URL(${port});
const rootDir = path.dirname(__dirname);

-const defaultBrowser = os.platform() === "win32" ? "edge" : "chrome";
+const defaultBrowser = os.platform() === "win32" ? "edge" : "chrome";
let browser: "edge" | "chrome" | "none" = defaultBrowser;
let grep: string | undefined;

interface FileBasedTestConfiguration {
[setting: string]: string;
}

function swapCase(s: string): string {
- return s.replace(/\w/g, (ch) => {
- const up = ch.toUpperCase();
- return ch === up ? ch.toLowerCase() : up;
- });
+ return s.replace(/\w/g, (ch) => {
+ const up = ch.toUpperCase();
+ return ch === up ? ch.toLowerCase() : up;
+ });
}

-for (var i in pieces) {
- switch (true) {
- case /^\"?Accession\"?/.test(pieces[i]):
+for (var i in pieces) {
+ switch (true) {
+ case /^\"?Accession\"?/.test(pieces[i]):
numeration[0] = i;
break;
}
@@ -67,16 +67,16 @@ }

// Substitutions
-export function isInOpenInterval(start: number, end: number) {
- return tersible(a => a > start && a < end, () => ${start}${end})
+export function isInOpenInterval(start: number, end: number) {
+ return tersible(a => a > start && a < end, () => ${start}${end})
}
const bar = ${x}${y};

// readonly
-function f1(mt: [number, number], rt: readonly [number, number]) {
+function f1(mt: [number, number], rt: readonly [number, number]) {
}

-function f2(ma: string[], ra: readonly string[], mt: [string, string], rt: readonly [string, string]) {
+function f2(ma: string[], ra: readonly string[], mt: [string, string], rt: readonly [string, string]) {
}

type ReadWrite<T> = { -readonly [P in keyof T] : T[P] };
@@ -97,11 +97,11 @@
// Function with multiple arguments
const children = [].map<Set<Map<number, string>>>(element => {
- if (!this.identityProvider) {
+ if (!this.identityProvider) {
return element;
}
return element;
-});
+});

// Numerics
var a = 0xA;
@@ -140,11 +140,11 @@
)

-function runQuery() {
+function runQuery() {
const query = createQuery<[number[]], Table<Columns>>(

)
- return database.execute(query)
+ return database.execute(query)
}

aa: <sdf/> string ?<ssd/> string
@@ -160,7 +160,7 @@ aa: [ string
string ]
aa: ( string
- string ) // Don't highlight
+ string ) // Don't highlight
aa: string <string>
interface a {
aa: /* comment
@@ -177,7 +177,7 @@ null, <{[key]: () =>{a: number}}> null

// Correctly highlighting regular expressions
-dt = ((dt[0] * 1e9 + dt[1]) / 1e6).toFixed(3).replace(/\.?0+$/, '') + 'ms';
+dt = ((dt[0] * 1e9 + dt[1]) / 1e6).toFixed(3).replace(/\.?0+$/, '') + 'ms';
(a[0] / 2) / (2)

// Type guards
@@ -187,28 +187,37 @@
// Conditional expressions (highlight keywords before ":")
class C {
- w = () =>
- this.a() ? true : this.b() ? false : true;
- z = () =>
- this.b() ? hello : k;
+ w = () =>
+ this.a() ? true : this.b() ? false : true;
+ z = () =>
+ this.b() ? hello : k;
}

-function foo<T extends X>(arg: T): T extends B ? number : string {
+function foo<T extends X>(arg: T): T extends B ? number : string {
if (arg === "A") return <T extends B ? number : never>111;
return <T extends B ? never : string>"returning a string";
}

+let x = (foo === null || foo === undefined) ?
+ undefined :
+ foo.bar.baz();
+let y = (foo === null || foo === undefined) ? /* comment */ undefined :
+ foo.bar.baz();
+
+// Operator ??
+let x = foo ?? bar();
+
// Types and logical `&&` and `||` operators after `as` expression
Date as any || null;

//Assertions
const assert: (value: unknown) => asserts value = value => {}
-declare function assertIsString(value: unknown): asserts value is string;
-declare function assertIsArrayOfStrings(value: unknown): asserts value is string[];
-declare function assertDefined<T>(value: T): asserts value is NonNullable<T>;
+declare function assertIsString(value: unknown): asserts value is string;
+declare function assertIsArrayOfStrings(value: unknown): asserts value is string[];
+declare function assertDefined<T>(value: T): asserts value is NonNullable<T>;
namespace Debug {
- export declare function assert(value: unknown, message?: string): asserts value;
- export declare function assertDefined<T>(value: T): asserts value is NonNullable<T>;
+ export declare function assert(value: unknown, message?: string): asserts value;
+ export declare function assertDefined<T>(value: T): asserts value is NonNullable<T>;
}

// Only highlight valid regular expressions, of a single line, after strings
@@ -223,3 +232,49 @@ // Template
const a = / 2; /*comment*/ const b = 5;
console.log( / ); // 2
+
+ [1, 2, 3].reduce<readonly number[]>((previous) => previous, []);
+
+// Multiline arrow assignment
+const h = {
+ setSubProperty: <
+ T extends A,
+ K extends keyof T,
+ J extends keyof T[K]
+ >(
+ property: K,
+ key: J,
+ value: T[K][J]
+ ) => {}
+}
+
+// Private-Named Instance Fields
+class Greeter {
+ #name: string;
+ constructor(name: string) {
+ this.#name = name;
+ }
+ greet() {
+ console.log(${this.#name});
+ }
+}
+class Test {
+ #NAME1: () => string;
+ prop1 = x.#NAMEabc.#NAMEabc;
+ prop2 = x.#NAMEabc.#NAMEabc();
+ prop3 = this.#NAMEabc.#NAME();
+}
+
+// Type-only imports and exports
+import type T from "mod";
+import type { U, V } from "mod";
+import type * as types from "mod";
+import type from "mod";
+import type = require("mod");
+import type T = require("mod");
+
+export { a as b, x };
+export * from "AnotherModule";
+export { k as m, l } from "AnotherModule";
+export type { T };
+export type { U } from "AnotherModule";
diff --git a/autotests/reference/test.tsx.ref b/autotests/reference/test.tsx.ref --- a/autotests/reference/test.tsx.ref +++ b/autotests/reference/test.tsx.ref @@ -6,16 +6,16 @@ import React from 'react';
import { PhotoStory, VideoStory } from './stories';

-function Story(props) {
+function Story(props) {
const SpecificStory = components[props.storyType];
return story={ props.story } attr2="&ref;" attr3="Hello\n" />;
}

function
- attr1={ function <noTag/> return class var 0x123 { } &noRef; hello() React.Component() } attr2="&ref;">
+ attr1={ function <noTag/> return class var 0x123 { } &noRef; hello() React.Component() } attr2="&ref;">
/* no comment*/ function return class var 0x123 &ref; hello() React.Component()
. anyWord
- { function <tag> return class var 0x123 hello() React.Component() }
+ { function <tag> return class var 0x123 hello() React.Component() }



@@ -85,7 +85,7 @@ {(name: string) =>
My name {name}
}
;

-let k3 = initialValues={{ x: "y" }} nextValues={a => ({ x: a.x })} />; // No Error
+let k3 = initialValues={{ x: "y" }} nextValues={a => ({ x: a.x })} />; // No Error

// OK
let k1 = a={10} b="hi"><> /> />;
@@ -127,7 +127,7 @@
// Don't highlight tags within interfaces and classes
interface GenericIdentityFn {
- <T>(arg: T): T;
+ <T>(arg: T): T;
<noTag />
}
class Handler {
@@ -151,3 +151,8 @@ <noTag /* comment */ ?
<noTag#
<noTag/*comment*/#
+
+// Conditionals expressions
+let y = foo == null ? null : ;
+let x = (foo === null || foo === undefined) ?
+ undefined :hello;
diff --git a/data/syntax/typescript-react.xml b/data/syntax/typescript-react.xml --- a/data/syntax/typescript-react.xml +++ b/data/syntax/typescript-react.xml @@ -16,14 +16,17 @@ + + + ]> - @@ -86,7 +90,6 @@ - @@ -106,18 +109,44 @@ - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -128,10 +157,11 @@ + - + @@ -148,6 +178,7 @@ + @@ -159,6 +190,7 @@ + @@ -169,6 +201,7 @@ + @@ -181,6 +214,7 @@ + @@ -250,13 +284,16 @@ - + + + + @@ -294,6 +331,16 @@ + + + + + + + + + + + + ]> keywords##JavaScript - declare reserved##JavaScript type arguments + declare readonly abstract constructor @@ -221,6 +227,18 @@ + + + + + + + + + @@ -235,13 +253,8 @@ - - - - + + @@ -260,6 +273,7 @@ + @@ -271,47 +285,66 @@ - + - - + + + + + + + - + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -396,11 +429,11 @@ - + - + @@ -429,8 +462,8 @@ This rule fixes it provisionally. --> - - + + @@ -491,7 +524,10 @@ - + + + + @@ -532,6 +568,7 @@ +