Skip to content

Commit 0daf938

Browse files
nibagschristoph-cullmann
authored andcommitted
TypeScript: add private fields and type-only imports/exports, and some fixes
Summary: * Add private-named instance fields. Ex: `x.#name;`. [1] * Support type-only imports and exports. [2] * Improve the detection of conditional expressions `a ? b : c`. Allow multiple lines. * Add rules of round brackets `()` to correct the highlighting of pairs of brackets. [3] [1] microsoft/TypeScript#30829 [2] microsoft/TypeScript#35200 [3] https://unix.stackexchange.com/questions/527268/kate-18-12-3-no-longer-shows-matching-parenthesis-for-typescript Reviewers: #framework_syntax_highlighting, dhaumann, cullmann Reviewed By: #framework_syntax_highlighting, cullmann Subscribers: kwrite-devel, kde-frameworks-devel Tags: #kate, #frameworks Differential Revision: https://phabricator.kde.org/D27692
1 parent 978e23b commit 0daf938

13 files changed

+427
-103
lines changed

autotests/folding/test.ts.fold

+55
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,15 @@ function foo<T extends X>(arg: T): T extends B ? number : string <beginfold id='
198198
return <T extends B ? never : string>"returning a string";
199199
<endfold id='1'>}</endfold id='1'>
200200

201+
let x = (foo === null || foo === undefined) ?
202+
undefined :
203+
foo.bar.baz();
204+
let y = (foo === null || foo === undefined) ? <beginfold id='7'>/*</beginfold id='7'> comment <endfold id='7'>*/</endfold id='7'> undefined :
205+
foo.bar.baz();
206+
207+
// Operator ??
208+
let x = foo ?? bar();
209+
201210
// Types and logical `&&` and `||` operators after `as` expression
202211
Date as any || null;
203212

@@ -223,3 +232,49 @@ console.log('4' / '2'); // 2
223232
// Template
224233
const a = `6` / 2; <beginfold id='7'>/*</beginfold id='7'>comment<endfold id='7'>*/</endfold id='7'> const b = 5;
225234
console.log(`4` / `2`); // 2
235+
236+
<beginfold id='2'>[</beginfold id='2'>1, 2, 3<endfold id='2'>]</endfold id='2'>.reduce<readonly number<beginfold id='2'>[</beginfold id='2'><endfold id='2'>]</endfold id='2'>>((previous) => previous, <beginfold id='2'>[</beginfold id='2'><endfold id='2'>]</endfold id='2'>);
237+
238+
// Multiline arrow assignment
239+
const h = <beginfold id='1'>{</beginfold id='1'>
240+
setSubProperty: <
241+
T extends A,
242+
K extends keyof T,
243+
J extends keyof T<beginfold id='2'>[</beginfold id='2'>K<endfold id='2'>]</endfold id='2'>
244+
>(
245+
property: K,
246+
key: J,
247+
value: T<beginfold id='2'>[</beginfold id='2'>K<endfold id='2'>]</endfold id='2'><beginfold id='2'>[</beginfold id='2'>J<endfold id='2'>]</endfold id='2'>
248+
) => <beginfold id='1'>{</beginfold id='1'><endfold id='1'>}</endfold id='1'>
249+
<endfold id='1'>}</endfold id='1'>
250+
251+
// Private-Named Instance Fields
252+
class Greeter <beginfold id='1'>{</beginfold id='1'>
253+
#name: string;
254+
constructor(name: string) <beginfold id='1'>{</beginfold id='1'>
255+
this.#name = name;
256+
<endfold id='1'>}</endfold id='1'>
257+
greet() <beginfold id='1'>{</beginfold id='1'>
258+
console.log(`hello ${this.#name}`);
259+
<endfold id='1'>}</endfold id='1'>
260+
<endfold id='1'>}</endfold id='1'>
261+
class Test <beginfold id='1'>{</beginfold id='1'>
262+
#NAME1: () => string;
263+
prop1 = x.#NAMEabc.#NAMEabc;
264+
prop2 = x.#NAMEabc.#NAMEabc();
265+
prop3 = this.#NAMEabc.#NAME();
266+
<endfold id='1'>}</endfold id='1'>
267+
268+
// Type-only imports and exports
269+
import type T from "mod";
270+
import type <beginfold id='1'>{</beginfold id='1'> U, V <endfold id='1'>}</endfold id='1'> from "mod";
271+
import type * as types from "mod";
272+
import type from "mod";
273+
import type = require<beginfold id='3'>(</beginfold id='3'>"mod"<endfold id='3'>)</endfold id='3'>;
274+
import type T = require<beginfold id='3'>(</beginfold id='3'>"mod"<endfold id='3'>)</endfold id='3'>;
275+
276+
export <beginfold id='1'>{</beginfold id='1'> a as b, x <endfold id='1'>}</endfold id='1'>;
277+
export * from "AnotherModule";
278+
export <beginfold id='1'>{</beginfold id='1'> k as m, l <endfold id='1'>}</endfold id='1'> from "AnotherModule";
279+
export type <beginfold id='1'>{</beginfold id='1'> T <endfold id='1'>}</endfold id='1'>;
280+
export type <beginfold id='1'>{</beginfold id='1'> U <endfold id='1'>}</endfold id='1'> from "AnotherModule";

autotests/folding/test.tsx.fold

+5
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,8 @@ const goodHighlighting = <T extends I>(
151151
<noTag <beginfold id='12'>/*</beginfold id='12'> comment <endfold id='12'>*/</endfold id='12'> ?
152152
<noTag#
153153
<noTag<beginfold id='12'>/*</beginfold id='12'>comment<endfold id='12'>*/</endfold id='12'>#
154+
155+
// Conditionals expressions
156+
let y = foo == null ? null : <beginfold id='4'><Tag</beginfold id='4'><endfold id='4'>/></endfold id='4'>;
157+
let x = (foo === null || foo === undefined) ?
158+
undefined :<beginfold id='3'><tag</beginfold id='3'>>hello</tag<endfold id='3'>></endfold id='3'>;

autotests/html/test.ts.html

+60-5
Original file line numberDiff line numberDiff line change
@@ -204,17 +204,26 @@
204204
<span style="font-weight:bold;">return</span> &lt;T <span style="font-weight:bold;font-style:italic;">extends</span> B ? <span style="color:#0057ae;">never</span> : <span style="color:#0057ae;">string</span>&gt;<span style="color:#bf0303;">&quot;returning a string&quot;</span>;
205205
}
206206

207+
<span style="font-weight:bold;font-style:italic;">let</span> x = (foo === <span style="font-weight:bold;">null</span> || foo === <span style="font-weight:bold;">undefined</span>) ?
208+
<span style="font-weight:bold;">undefined</span> :
209+
foo.<span style="color:#0057ae;">bar</span>.<span style="color:#644a9b;">baz</span>();
210+
<span style="font-weight:bold;font-style:italic;">let</span> y = (foo === <span style="font-weight:bold;">null</span> || foo === <span style="font-weight:bold;">undefined</span>) ? <span style="color:#898887;">/* comment */</span> <span style="font-weight:bold;">undefined</span> :
211+
foo.<span style="color:#0057ae;">bar</span>.<span style="color:#644a9b;">baz</span>();
212+
213+
<span style="color:#898887;">// Operator ??</span>
214+
<span style="font-weight:bold;font-style:italic;">let</span> x = foo ?? <span style="color:#644a9b;">bar</span>();
215+
207216
<span style="color:#898887;">// Types and logical `&amp;&amp;` and `||` operators after `as` expression</span>
208217
<span style="color:#644a9b;font-weight:bold;">Date</span> <span style="color:#ff5500;">as</span> <span style="color:#0057ae;">any</span> || <span style="color:#0057ae;">null</span>;
209218

210219
<span style="color:#898887;">//Assertions</span>
211220
<span style="font-weight:bold;">const</span> assert: (value: <span style="color:#0057ae;">unknown</span>) <span style="font-weight:bold;">=&gt;</span> <span style="font-weight:bold;">asserts</span> value = value <span style="font-weight:bold;">=&gt;</span> {}
212-
<span style="font-weight:bold;">declare</span> <span style="font-weight:bold;">function</span> <span style="color:#644a9b;">assertIsString</span>(value: <span style="color:#0057ae;">unknown</span>): <span style="font-weight:bold;">asserts</span> value <span style="font-weight:bold;">is</span> <span style="color:#0057ae;">string</span>;
213-
<span style="font-weight:bold;">declare</span> <span style="font-weight:bold;">function</span> <span style="color:#644a9b;">assertIsArrayOfStrings</span>(value: <span style="color:#0057ae;">unknown</span>): <span style="font-weight:bold;">asserts</span> value <span style="font-weight:bold;">is</span> <span style="color:#0057ae;">string</span>[];
214-
<span style="font-weight:bold;">declare</span> <span style="font-weight:bold;">function</span> <span style="color:#644a9b;">assertDefined</span>&lt;T&gt;(value: T): <span style="font-weight:bold;">asserts</span> value <span style="font-weight:bold;">is</span> <span style="color:#644a9b;font-weight:bold;">NonNullable</span>&lt;T&gt;;
221+
<span style="font-weight:bold;font-style:italic;">declare</span> <span style="font-weight:bold;">function</span> <span style="color:#644a9b;">assertIsString</span>(value: <span style="color:#0057ae;">unknown</span>): <span style="font-weight:bold;">asserts</span> value <span style="font-weight:bold;">is</span> <span style="color:#0057ae;">string</span>;
222+
<span style="font-weight:bold;font-style:italic;">declare</span> <span style="font-weight:bold;">function</span> <span style="color:#644a9b;">assertIsArrayOfStrings</span>(value: <span style="color:#0057ae;">unknown</span>): <span style="font-weight:bold;">asserts</span> value <span style="font-weight:bold;">is</span> <span style="color:#0057ae;">string</span>[];
223+
<span style="font-weight:bold;font-style:italic;">declare</span> <span style="font-weight:bold;">function</span> <span style="color:#644a9b;">assertDefined</span>&lt;T&gt;(value: T): <span style="font-weight:bold;">asserts</span> value <span style="font-weight:bold;">is</span> <span style="color:#644a9b;font-weight:bold;">NonNullable</span>&lt;T&gt;;
215224
<span style="color:#ff5500;">namespace</span> <span style="color:#0057ae;">Debug</span> {
216-
<span style="color:#ff5500;">export</span> <span style="font-weight:bold;">declare</span> <span style="font-weight:bold;">function</span> <span style="color:#644a9b;">assert</span>(value: <span style="color:#0057ae;">unknown</span>, message?: <span style="color:#0057ae;">string</span>): <span style="font-weight:bold;">asserts</span> value;
217-
<span style="color:#ff5500;">export</span> <span style="font-weight:bold;">declare</span> <span style="font-weight:bold;">function</span> <span style="color:#644a9b;">assertDefined</span>&lt;T&gt;(value: T): <span style="font-weight:bold;">asserts</span> value <span style="font-weight:bold;">is</span> <span style="color:#644a9b;font-weight:bold;">NonNullable</span>&lt;T&gt;;
225+
<span style="color:#ff5500;">export</span> <span style="font-weight:bold;font-style:italic;">declare</span> <span style="font-weight:bold;">function</span> <span style="color:#644a9b;">assert</span>(value: <span style="color:#0057ae;">unknown</span>, message?: <span style="color:#0057ae;">string</span>): <span style="font-weight:bold;">asserts</span> value;
226+
<span style="color:#ff5500;">export</span> <span style="font-weight:bold;font-style:italic;">declare</span> <span style="font-weight:bold;">function</span> <span style="color:#644a9b;">assertDefined</span>&lt;T&gt;(value: T): <span style="font-weight:bold;">asserts</span> value <span style="font-weight:bold;">is</span> <span style="color:#644a9b;font-weight:bold;">NonNullable</span>&lt;T&gt;;
218227
}
219228

220229
<span style="color:#898887;">// Only highlight valid regular expressions, of a single line, after strings</span>
@@ -229,4 +238,50 @@
229238
<span style="color:#898887;">// Template</span>
230239
<span style="font-weight:bold;">const</span> a = <span style="color:#bf0303;">`6`</span> / <span style="color:#b08000;">2</span>; <span style="color:#898887;">/*comment*/</span> <span style="font-weight:bold;">const</span> b = <span style="color:#b08000;">5</span>;
231240
<span style="color:#644a9b;font-weight:bold;">console</span>.<span style="color:#644a9b;font-style:italic;">log</span>(<span style="color:#bf0303;">`4`</span> / <span style="color:#bf0303;">`2`</span>); <span style="color:#898887;">// 2</span>
241+
242+
[<span style="color:#b08000;">1</span>, <span style="color:#b08000;">2</span>, <span style="color:#b08000;">3</span>].<span style="color:#644a9b;">reduce</span>&lt;<span style="font-weight:bold;font-style:italic;">readonly</span> <span style="color:#0057ae;">number</span>[]&gt;((previous) <span style="font-weight:bold;">=&gt;</span> previous, []);
243+
244+
<span style="color:#898887;">// Multiline arrow assignment</span>
245+
<span style="font-weight:bold;">const</span> h = {
246+
setSubProperty: &lt;
247+
T <span style="font-weight:bold;font-style:italic;">extends</span> A,
248+
K <span style="font-weight:bold;font-style:italic;">extends</span> <span style="font-weight:bold;">keyof</span> T,
249+
J <span style="font-weight:bold;font-style:italic;">extends</span> <span style="font-weight:bold;">keyof</span> T[K]
250+
&gt;(
251+
property: K,
252+
key: J,
253+
value: T[K][J]
254+
) <span style="font-weight:bold;">=&gt;</span> {}
255+
}
256+
257+
<span style="color:#898887;">// Private-Named Instance Fields</span>
258+
<span style="font-weight:bold;font-style:italic;">class</span> Greeter {
259+
#name: <span style="color:#0057ae;">string</span>;
260+
<span style="font-weight:bold;font-style:italic;">constructor</span>(name: <span style="color:#0057ae;">string</span>) {
261+
<span style="font-weight:bold;">this</span>.#<span style="color:#0057ae;">name</span> = name;
262+
}
263+
<span style="color:#644a9b;">greet</span>() {
264+
<span style="color:#644a9b;font-weight:bold;">console</span>.<span style="color:#644a9b;font-style:italic;">log</span>(<span style="color:#bf0303;">`hello </span><span style="color:#3daee9;">${</span><span style="font-weight:bold;">this</span>.#<span style="color:#0057ae;">name</span><span style="color:#3daee9;">}</span><span style="color:#bf0303;">`</span>);
265+
}
266+
}
267+
<span style="font-weight:bold;font-style:italic;">class</span> Test {
268+
#NAME1: () <span style="font-weight:bold;">=&gt;</span> <span style="color:#0057ae;">string</span>;
269+
prop1 = x.#<span style="color:#0057ae;">NAMEabc</span>.#<span style="color:#0057ae;">NAMEabc</span>;
270+
prop2 = x.#<span style="color:#0057ae;">NAMEabc</span>.#<span style="color:#644a9b;">NAMEabc</span>();
271+
prop3 = <span style="font-weight:bold;">this</span>.#<span style="color:#0057ae;">NAMEabc</span>.#<span style="color:#644a9b;">NAME</span>();
272+
}
273+
274+
<span style="color:#898887;">// Type-only imports and exports</span>
275+
<span style="color:#ff5500;">import</span> <span style="color:#ff5500;">type</span> T <span style="color:#ff5500;">from</span> <span style="color:#bf0303;">&quot;mod&quot;</span>;
276+
<span style="color:#ff5500;">import</span> <span style="color:#ff5500;">type</span> { U, V } <span style="color:#ff5500;">from</span> <span style="color:#bf0303;">&quot;mod&quot;</span>;
277+
<span style="color:#ff5500;">import</span> <span style="color:#ff5500;">type</span> * <span style="color:#ff5500;">as</span> types <span style="color:#ff5500;">from</span> <span style="color:#bf0303;">&quot;mod&quot;</span>;
278+
<span style="color:#ff5500;">import</span> <span style="color:#ff5500;">type</span> <span style="color:#ff5500;">from</span> <span style="color:#bf0303;">&quot;mod&quot;</span>;
279+
<span style="color:#ff5500;">import</span> <span style="color:#ff5500;">type</span> =<span style="font-weight:bold;"> require</span>(<span style="color:#bf0303;">&quot;mod&quot;</span>);
280+
<span style="color:#ff5500;">import</span> <span style="color:#ff5500;">type</span> T =<span style="font-weight:bold;"> require</span>(<span style="color:#bf0303;">&quot;mod&quot;</span>);
281+
282+
<span style="color:#ff5500;">export</span> { a <span style="color:#ff5500;">as</span> b, x };
283+
<span style="color:#ff5500;">export</span> * <span style="color:#ff5500;">from</span> <span style="color:#bf0303;">&quot;AnotherModule&quot;</span>;
284+
<span style="color:#ff5500;">export</span> { k <span style="color:#ff5500;">as</span> m, l } <span style="color:#ff5500;">from</span> <span style="color:#bf0303;">&quot;AnotherModule&quot;</span>;
285+
<span style="color:#ff5500;">export type</span> { T };
286+
<span style="color:#ff5500;">export type</span> { U } <span style="color:#ff5500;">from</span> <span style="color:#bf0303;">&quot;AnotherModule&quot;</span>;
232287
</pre></body></html>

autotests/html/test.tsx.html

+5
Original file line numberDiff line numberDiff line change
@@ -157,4 +157,9 @@
157157
&lt;noTag <span style="color:#898887;">/* comment */</span> ?
158158
&lt;noTag#
159159
&lt;noTag<span style="color:#898887;">/*comment*/</span>#
160+
161+
<span style="color:#898887;">// Conditionals expressions</span>
162+
<span style="font-weight:bold;font-style:italic;">let</span> y = foo == <span style="font-weight:bold;">null</span> ? <span style="font-weight:bold;">null</span> : <span style="color:#644a9b;font-weight:bold;">&lt;Tag/&gt;</span>;
163+
<span style="font-weight:bold;font-style:italic;">let</span> x = (foo === <span style="font-weight:bold;">null</span> || foo === <span style="font-weight:bold;">undefined</span>) ?
164+
<span style="font-weight:bold;">undefined</span> :<span style="font-weight:bold;">&lt;tag&gt;</span>hello<span style="font-weight:bold;">&lt;/tag&gt;</span>;
160165
</pre></body></html>

autotests/input/test.ts

+55
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,15 @@ function foo<T extends X>(arg: T): T extends B ? number : string {
198198
return <T extends B ? never : string>"returning a string";
199199
}
200200

201+
let x = (foo === null || foo === undefined) ?
202+
undefined :
203+
foo.bar.baz();
204+
let y = (foo === null || foo === undefined) ? /* comment */ undefined :
205+
foo.bar.baz();
206+
207+
// Operator ??
208+
let x = foo ?? bar();
209+
201210
// Types and logical `&&` and `||` operators after `as` expression
202211
Date as any || null;
203212

@@ -223,3 +232,49 @@ console.log('4' / '2'); // 2
223232
// Template
224233
const a = `6` / 2; /*comment*/ const b = 5;
225234
console.log(`4` / `2`); // 2
235+
236+
[1, 2, 3].reduce<readonly number[]>((previous) => previous, []);
237+
238+
// Multiline arrow assignment
239+
const h = {
240+
setSubProperty: <
241+
T extends A,
242+
K extends keyof T,
243+
J extends keyof T[K]
244+
>(
245+
property: K,
246+
key: J,
247+
value: T[K][J]
248+
) => {}
249+
}
250+
251+
// Private-Named Instance Fields
252+
class Greeter {
253+
#name: string;
254+
constructor(name: string) {
255+
this.#name = name;
256+
}
257+
greet() {
258+
console.log(`hello ${this.#name}`);
259+
}
260+
}
261+
class Test {
262+
#NAME1: () => string;
263+
prop1 = x.#NAMEabc.#NAMEabc;
264+
prop2 = x.#NAMEabc.#NAMEabc();
265+
prop3 = this.#NAMEabc.#NAME();
266+
}
267+
268+
// Type-only imports and exports
269+
import type T from "mod";
270+
import type { U, V } from "mod";
271+
import type * as types from "mod";
272+
import type from "mod";
273+
import type = require("mod");
274+
import type T = require("mod");
275+
276+
export { a as b, x };
277+
export * from "AnotherModule";
278+
export { k as m, l } from "AnotherModule";
279+
export type { T };
280+
export type { U } from "AnotherModule";

autotests/input/test.tsx

+5
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,8 @@ const goodHighlighting = <T extends I>(
151151
<noTag /* comment */ ?
152152
<noTag#
153153
<noTag/*comment*/#
154+
155+
// Conditionals expressions
156+
let y = foo == null ? null : <Tag/>;
157+
let x = (foo === null || foo === undefined) ?
158+
undefined :<tag>hello</tag>;

autotests/reference/highlight.php.ref

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@
4040
<Normal Text> </Normal Text><Keyword><?php</Keyword><PHP Text> </PHP Text><Variable>$timestamp</Variable><PHP Text> = </PHP Text><Function>time</Function><Other>();</Other><PHP Text> </PHP Text><Keyword>?></Keyword><br/>
4141
<Normal Text> </Normal Text><Reserved>class</Reserved><Normal Text> </Normal Text><Normal Text>DateTime </Normal Text><Normal Text>{</Normal Text><br/>
4242
<Normal Text> </Normal Text><Parameter>info</Parameter><Symbol>:</Symbol><Normal Text> </Normal Text><Types>string</Types><Symbol>;</Symbol><br/>
43-
<Normal Text> </Normal Text><Reserved>constructor</Reserved><Normal Text>(</Normal Text><Normal Text>) </Normal Text><Normal Text>{ </Normal Text><Keyword>this</Keyword><Symbol>.</Symbol><Object Member>info</Object Member><Normal Text> </Normal Text><Symbol>=</Symbol><Normal Text> </Normal Text><Keyword><?php</Keyword><PHP Text> </PHP Text><Keyword>echo</Keyword><Other>(</Other><Function>date</Function><Other>(</Other><String>"F d, Y h:i:s"</String><Other>,</Other><PHP Text> </PHP Text><Variable>$timestamp</Variable><Other>));</Other><PHP Text> </PHP Text><Keyword>?></Keyword><Symbol>;</Symbol><Normal Text> }</Normal Text><br/>
44-
<Normal Text> </Normal Text><Reserved>get</Reserved><Normal Text>(</Normal Text><Normal Text>) </Normal Text><Normal Text>{ </Normal Text><ControlFlow>return</ControlFlow><Normal Text> </Normal Text><Keyword>this</Keyword><Symbol>.</Symbol><Object Member>info</Object Member><Symbol>;</Symbol><Normal Text> }</Normal Text><br/>
43+
<Normal Text> </Normal Text><Reserved>constructor</Reserved><Normal Text>() { </Normal Text><Keyword>this</Keyword><Symbol>.</Symbol><Object Member>info</Object Member><Normal Text> </Normal Text><Symbol>=</Symbol><Normal Text> </Normal Text><Keyword><?php</Keyword><PHP Text> </PHP Text><Keyword>echo</Keyword><Other>(</Other><Function>date</Function><Other>(</Other><String>"F d, Y h:i:s"</String><Other>,</Other><PHP Text> </PHP Text><Variable>$timestamp</Variable><Other>));</Other><PHP Text> </PHP Text><Keyword>?></Keyword><Symbol>;</Symbol><Normal Text> }</Normal Text><br/>
44+
<Normal Text> </Normal Text><Reserved>get</Reserved><Normal Text>() { </Normal Text><ControlFlow>return</ControlFlow><Normal Text> </Normal Text><Keyword>this</Keyword><Symbol>.</Symbol><Object Member>info</Object Member><Symbol>;</Symbol><Normal Text> }</Normal Text><br/>
4545
<Normal Text> }</Normal Text><br/>
4646
<Normal Text> </Normal Text><Element></script></Element><br/>
4747
<Normal Text> </Normal Text><Comment><!-- MustacheJS --></Comment><br/>

0 commit comments

Comments
 (0)