Skip to content

Commit 0af0968

Browse files
Dxuianjoshgoebel
andauthored
fix(typescript) improved highlighting of optionals (#4114)
Co-authored-by: Josh Goebel <[email protected]>
1 parent a9756e3 commit 0af0968

File tree

5 files changed

+144
-14
lines changed

5 files changed

+144
-14
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Core Grammars:
1818
- enh(lua) add 'pluto' as an alias [Sainan]
1919
- enh(bash) add reserved keywords `time` and `coproc` [Álvaro Mondéjar][]
2020
- fix(c) - Fixed hex numbers with decimals [Dxuian]
21+
- fix(typescript) - Fixedoptional property not highlighted correctly [Dxuian]
2122
- fix(ruby) - fix `|=` operator false positives (as block arguments) [Aboobacker MK]
2223

2324
New Grammars:

src/languages/javascript.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ export default function(hljs) {
265265
const PARAMS = {
266266
className: 'params',
267267
// convert this to negative lookbehind in v12
268-
begin: /(\s*)\(/, // to match the parms with
268+
begin: /(\s*)\(/, // to match the parms with
269269
end: /\)/,
270270
excludeBegin: true,
271271
excludeEnd: true,
@@ -476,8 +476,8 @@ export default function(hljs) {
476476
NUMBER,
477477
CLASS_REFERENCE,
478478
{
479-
className: 'attr',
480-
begin: IDENT_RE + regex.lookahead(':'),
479+
scope: 'attr',
480+
match: IDENT_RE + regex.lookahead(':'),
481481
relevance: 0
482482
},
483483
FUNCTION_VARIABLE,

src/languages/typescript.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import javascript from "./javascript.js";
1212

1313
/** @type LanguageFn */
1414
export default function(hljs) {
15+
const regex = hljs.regex;
1516
const tsLanguage = javascript(hljs);
1617

1718
const IDENT_RE = ECMAScript.IDENT_RE;
@@ -68,20 +69,19 @@ export default function(hljs) {
6869
"override",
6970
"satisfies"
7071
];
71-
7272
/*
7373
namespace is a TS keyword but it's fine to use it as a variable name too.
7474
const message = 'foo';
7575
const namespace = 'bar';
7676
*/
77-
7877
const KEYWORDS = {
7978
$pattern: ECMAScript.IDENT_RE,
8079
keyword: ECMAScript.KEYWORDS.concat(TS_SPECIFIC_KEYWORDS),
8180
literal: ECMAScript.LITERALS,
8281
built_in: ECMAScript.BUILT_INS.concat(TYPES),
8382
"variable.language": ECMAScript.BUILT_IN_VARIABLES
8483
};
84+
8585
const DECORATOR = {
8686
className: 'meta',
8787
begin: '@' + IDENT_RE,
@@ -102,15 +102,25 @@ export default function(hljs) {
102102
tsLanguage.exports.PARAMS_CONTAINS.push(DECORATOR);
103103

104104
// highlight the function params
105-
const ATTRIBUTE_HIGHLIGHT = tsLanguage.contains.find(c => c.className === "attr");
105+
const ATTRIBUTE_HIGHLIGHT = tsLanguage.contains.find(c => c.scope === "attr");
106+
107+
// take default attr rule and extend it to support optionals
108+
const OPTIONAL_KEY_OR_ARGUMENT = Object.assign({},
109+
ATTRIBUTE_HIGHLIGHT,
110+
{ match: regex.concat(IDENT_RE, regex.lookahead(/\s*\?:/)) }
111+
);
106112
tsLanguage.exports.PARAMS_CONTAINS.push([
107113
tsLanguage.exports.CLASS_REFERENCE, // class reference for highlighting the params types
108114
ATTRIBUTE_HIGHLIGHT, // highlight the params key
115+
OPTIONAL_KEY_OR_ARGUMENT, // Added for optional property assignment highlighting
109116
]);
117+
118+
// Add the optional property assignment highlighting for objects or classes
110119
tsLanguage.contains = tsLanguage.contains.concat([
111120
DECORATOR,
112121
NAMESPACE,
113122
INTERFACE,
123+
OPTIONAL_KEY_OR_ARGUMENT, // Added for optional property assignment highlighting
114124
]);
115125

116126
// TS gets a simpler shebang rule than JS
Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,69 @@
1-
<span class="hljs-keyword">import</span> { useWeb3React <span class="hljs-keyword">as</span> useWeb3React_ } <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;@web3-react/core&#x27;</span>
2-
3-
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> <span class="hljs-attr">useWeb3React</span>: &lt;T = <span class="hljs-built_in">any</span>&gt;<span class="hljs-function">(<span class="hljs-params">key?: <span class="hljs-built_in">string</span></span>) =&gt;</span> <span class="hljs-title class_">Modify</span>&lt;
1+
<span class="hljs-comment">// Updated function with both optional and non-optional parameters</span>
2+
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> <span class="hljs-attr">useWeb3React</span>: &lt;T = <span class="hljs-built_in">any</span>&gt;<span class="hljs-function">(<span class="hljs-params"><span class="hljs-attr">key</span>?: <span class="hljs-built_in">string</span>, <span class="hljs-attr">version</span>: <span class="hljs-built_in">number</span></span>) =&gt;</span> <span class="hljs-title class_">Modify</span>&lt;
43
<span class="hljs-title class_">ReturnType</span>&lt;<span class="hljs-keyword">typeof</span> useWeb3React_&lt;T&gt;&gt;,
5-
{ <span class="hljs-attr">chainId</span>: <span class="hljs-title class_">SupportedChainIds</span> }
4+
{ <span class="hljs-attr">chainId</span>: <span class="hljs-title class_">SupportedChainIds</span>, <span class="hljs-attr">network</span>: <span class="hljs-built_in">string</span> }
65
&gt; = useWeb3React_ <span class="hljs-keyword">as</span> <span class="hljs-built_in">any</span>
76

87
<span class="hljs-keyword">declare</span> <span class="hljs-variable language_">global</span> {
98
<span class="hljs-keyword">type</span> <span class="hljs-title class_">SupportedChainIds</span> = <span class="hljs-number">1</span> | <span class="hljs-number">4</span>
109
}
10+
11+
<span class="hljs-comment">// Optional and non-optional properties in an object type</span>
12+
<span class="hljs-keyword">type</span> <span class="hljs-title class_">Options</span> = {
13+
<span class="hljs-attr">srcdir</span>: <span class="hljs-built_in">string</span>,
14+
<span class="hljs-attr">outdir</span>: <span class="hljs-built_in">string</span>,
15+
<span class="hljs-attr">minify</span>?: <span class="hljs-built_in">boolean</span>,
16+
<span class="hljs-attr">sourcemap</span>: <span class="hljs-built_in">boolean</span>
17+
}
18+
19+
<span class="hljs-comment">// Function with both optional and non-optional parameters</span>
20+
<span class="hljs-keyword">function</span> <span class="hljs-title function_">multiply</span>(<span class="hljs-params"><span class="hljs-attr">a</span>: <span class="hljs-built_in">number</span>, <span class="hljs-attr">b</span>: <span class="hljs-built_in">number</span>, <span class="hljs-attr">c</span>?: <span class="hljs-built_in">number</span>, <span class="hljs-attr">d</span>: <span class="hljs-built_in">number</span></span>): <span class="hljs-built_in">number</span> {
21+
<span class="hljs-keyword">return</span> a * b * d;
22+
}
23+
24+
<span class="hljs-comment">// Optional Function Parameters</span>
25+
<span class="hljs-keyword">function</span> <span class="hljs-title function_">greet</span>(<span class="hljs-params"><span class="hljs-attr">name</span>?: <span class="hljs-built_in">string</span>, <span class="hljs-attr">age</span>?: <span class="hljs-built_in">number</span>, <span class="hljs-attr">city</span>: <span class="hljs-built_in">string</span></span>) {
26+
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">`Hello, <span class="hljs-subst">${name ?? <span class="hljs-string">&quot;Guest&quot;</span>}</span> from <span class="hljs-subst">${city}</span>!`</span>);
27+
}
28+
29+
<span class="hljs-comment">// Optional and non-optional properties in an interface</span>
30+
<span class="hljs-keyword">interface</span> <span class="hljs-title class_">Person</span> {
31+
<span class="hljs-attr">name</span>: <span class="hljs-built_in">string</span>;
32+
<span class="hljs-attr">age</span>?: <span class="hljs-built_in">number</span>;
33+
<span class="hljs-attr">address</span>?: <span class="hljs-built_in">string</span>;
34+
<span class="hljs-attr">occupation</span>: <span class="hljs-built_in">string</span>;
35+
}
36+
37+
<span class="hljs-comment">// Optional Class Members and Constructor Parameters</span>
38+
<span class="hljs-keyword">class</span> <span class="hljs-title class_">Car</span> {
39+
<span class="hljs-attr">make</span>: <span class="hljs-built_in">string</span>;
40+
<span class="hljs-attr">model</span>?: <span class="hljs-built_in">string</span>;
41+
<span class="hljs-attr">year</span>: <span class="hljs-built_in">number</span>;
42+
43+
<span class="hljs-title function_">constructor</span>(<span class="hljs-params"><span class="hljs-attr">make</span>: <span class="hljs-built_in">string</span>, <span class="hljs-attr">year</span>: <span class="hljs-built_in">number</span>, <span class="hljs-attr">model</span>?: <span class="hljs-built_in">string</span></span>) {
44+
<span class="hljs-variable language_">this</span>.<span class="hljs-property">make</span> = make;
45+
<span class="hljs-variable language_">this</span>.<span class="hljs-property">year</span> = year;
46+
<span class="hljs-variable language_">this</span>.<span class="hljs-property">model</span> = model;
47+
}
48+
}
49+
50+
51+
<span class="hljs-comment">// Optional Constructor Parameters</span>
52+
<span class="hljs-keyword">class</span> <span class="hljs-title class_">User</span> {
53+
<span class="hljs-attr">name</span>: <span class="hljs-built_in">string</span>;
54+
<span class="hljs-attr">age</span>?: <span class="hljs-built_in">number</span>;
55+
<span class="hljs-attr">city</span>: <span class="hljs-built_in">string</span>;
56+
57+
<span class="hljs-title function_">constructor</span>(<span class="hljs-params"><span class="hljs-attr">name</span>: <span class="hljs-built_in">string</span>, <span class="hljs-attr">city</span>: <span class="hljs-built_in">string</span>, <span class="hljs-attr">age</span>?: <span class="hljs-built_in">number</span></span>) {
58+
<span class="hljs-variable language_">this</span>.<span class="hljs-property">name</span> = name;
59+
<span class="hljs-variable language_">this</span>.<span class="hljs-property">city</span> = city;
60+
<span class="hljs-variable language_">this</span>.<span class="hljs-property">age</span> = age;
61+
}
62+
}
63+
64+
<span class="hljs-comment">// Optional in Function Type Signatures</span>
65+
<span class="hljs-keyword">type</span> <span class="hljs-title class_">PrintMessage</span> = <span class="hljs-function">(<span class="hljs-params"><span class="hljs-attr">message</span>: <span class="hljs-built_in">string</span>, <span class="hljs-attr">sender</span>?: <span class="hljs-built_in">string</span>, <span class="hljs-attr">timestamp</span>: <span class="hljs-built_in">number</span></span>) =&gt;</span> <span class="hljs-built_in">void</span>;
66+
67+
<span class="hljs-keyword">const</span> <span class="hljs-attr">print</span>: <span class="hljs-title class_">PrintMessage</span> = <span class="hljs-function">(<span class="hljs-params">message, sender, timestamp</span>) =&gt;</span> {
68+
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">`Message: <span class="hljs-subst">${message}</span>, from: <span class="hljs-subst">${sender ?? <span class="hljs-string">&quot;Anonymous&quot;</span>}</span> at <span class="hljs-subst">${timestamp}</span>`</span>);
69+
};

test/markup/typescript/generics.txt

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,70 @@
1-
import { useWeb3React as useWeb3React_ } from '@web3-react/core'
2-
3-
export const useWeb3React: <T = any>(key?: string) => Modify<
1+
// Updated function with both optional and non-optional parameters
2+
export const useWeb3React: <T = any>(key?: string, version: number) => Modify<
43
ReturnType<typeof useWeb3React_<T>>,
5-
{ chainId: SupportedChainIds }
4+
{ chainId: SupportedChainIds, network: string }
65
> = useWeb3React_ as any
76

87
declare global {
98
type SupportedChainIds = 1 | 4
109
}
10+
11+
// Optional and non-optional properties in an object type
12+
type Options = {
13+
srcdir: string,
14+
outdir: string,
15+
minify?: boolean,
16+
sourcemap: boolean
17+
}
18+
19+
// Function with both optional and non-optional parameters
20+
function multiply(a: number, b: number, c?: number, d: number): number {
21+
return a * b * d;
22+
}
23+
24+
// Optional Function Parameters
25+
function greet(name?: string, age?: number, city: string) {
26+
console.log(`Hello, ${name ?? "Guest"} from ${city}!`);
27+
}
28+
29+
// Optional and non-optional properties in an interface
30+
interface Person {
31+
name: string;
32+
age?: number;
33+
address?: string;
34+
occupation: string;
35+
}
36+
37+
// Optional Class Members and Constructor Parameters
38+
class Car {
39+
make: string;
40+
model?: string;
41+
year: number;
42+
43+
constructor(make: string, year: number, model?: string) {
44+
this.make = make;
45+
this.year = year;
46+
this.model = model;
47+
}
48+
}
49+
50+
51+
// Optional Constructor Parameters
52+
class User {
53+
name: string;
54+
age?: number;
55+
city: string;
56+
57+
constructor(name: string, city: string, age?: number) {
58+
this.name = name;
59+
this.city = city;
60+
this.age = age;
61+
}
62+
}
63+
64+
// Optional in Function Type Signatures
65+
type PrintMessage = (message: string, sender?: string, timestamp: number) => void;
66+
67+
const print: PrintMessage = (message, sender, timestamp) => {
68+
console.log(`Message: ${message}, from: ${sender ?? "Anonymous"} at ${timestamp}`);
69+
};
70+

0 commit comments

Comments
 (0)