Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b08fe23

Browse files
HerrCai0907dcodeIO
andauthored
fix: Also support null | T in parser (#2507)
Co-authored-by: dcode <dcode@dcode.io>
1 parent 6a7aaef commit b08fe23

File tree

6 files changed

+44
-32
lines changed

6 files changed

+44
-32
lines changed

‎src/ast.ts‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,11 @@ export class NamedTypeNode extends TypeNode {
901901
let typeArguments = this.typeArguments;
902902
return typeArguments != null && typeArguments.length > 0;
903903
}
904+
905+
/** Tests if this type is "null". */
906+
get isNull(): bool {
907+
return this.name.identifier.text == "null";
908+
}
904909
}
905910

906911
/** Represents a function type. */

‎src/parser.ts‎

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -507,45 +507,29 @@ export class Parser extends DiagnosticEmitter {
507507
// '(' ...
508508
if (token == Token.OpenParen) {
509509

510-
// '(' FunctionSignature ')' '|' 'null'?
511-
let isNullableSignature = tn.skip(Token.OpenParen);
510+
// '(' FunctionSignature ')'
511+
let isInnerParenthesized = tn.skip(Token.OpenParen);
512512
// FunctionSignature?
513513
let signature = this.tryParseFunctionType(tn);
514514
if (signature) {
515-
if (isNullableSignature) {
515+
if (isInnerParenthesized) {
516516
if (!tn.skip(Token.CloseParen)) {
517517
this.error(
518518
DiagnosticCode._0_expected,
519519
tn.range(), ")"
520520
);
521521
return null;
522522
}
523-
if (!tn.skip(Token.Bar)) {
524-
this.error(
525-
DiagnosticCode._0_expected,
526-
tn.range(), "|"
527-
);
528-
return null;
529-
}
530-
if (!tn.skip(Token.Null)) {
531-
this.error(
532-
DiagnosticCode._0_expected,
533-
tn.range(), "null"
534-
);
535-
}
536-
signature.isNullable = true;
537523
}
538-
return signature;
539-
} else if (isNullableSignature || this.tryParseSignatureIsSignature) {
524+
type= signature;
525+
} else if (isInnerParenthesized || this.tryParseSignatureIsSignature) {
540526
this.error(
541527
DiagnosticCode.Unexpected_token,
542528
tn.range()
543529
);
544530
return null;
545-
}
546-
547531
// Type (',' Type)* ')'
548-
if (acceptParenthesized) {
532+
}elseif (acceptParenthesized) {
549533
let innerType = this.parseType(tn, false, suppressErrors);
550534
if (!innerType) return null;
551535
if (!tn.skip(Token.CloseParen)) {
@@ -634,20 +618,29 @@ export class Parser extends DiagnosticEmitter {
634618
}
635619
return null;
636620
}
637-
// ... | null
621+
// ... | type
638622
while (tn.skip(Token.Bar)) {
639-
if(tn.skip(Token.Null)){
640-
type.isNullable=true;
641-
}else{
642-
letnotNullStart=tn.pos;
643-
letnotNull=this.parseType(tn,false,true);
623+
letnextType=this.parseType(tn,false,true);
624+
if(!nextType)returnnull;
625+
lettypeIsNull=type.kind==NodeKind.NamedType&&(<NamedTypeNode>type).isNull;
626+
letnextTypeIsNull=nextType.kind==NodeKind.NamedType&&(<NamedTypeNode>nextType).isNull;
627+
if(!typeIsNull&&!nextTypeIsNull){
644628
if (!suppressErrors) {
645629
this.error(
646-
DiagnosticCode._0_expected,
647-
notNull ? notNull.range : tn.range(notNullStart), "null"
630+
DiagnosticCode.Not_implemented_0, nextType.range, "union types"
648631
);
649632
}
650633
return null;
634+
} else if (nextTypeIsNull) {
635+
type.isNullable = true;
636+
type.range.end = nextType.range.end;
637+
} else if (typeIsNull) {
638+
nextType.range.start = type.range.start;
639+
nextType.isNullable = true;
640+
type = nextType;
641+
} else {
642+
// `null | null` still `null`
643+
type.range.end = nextType.range.end;
651644
}
652645
}
653646
// ... [][]
@@ -672,8 +665,8 @@ export class Parser extends DiagnosticEmitter {
672665
} else {
673666
if (!suppressErrors) {
674667
this.error(
675-
DiagnosticCode._0_expected,
676-
tn.range(), "null"
668+
DiagnosticCode.Not_implemented_0,
669+
tn.range(), "union types"
677670
);
678671
}
679672
return null;

‎tests/parser/type-signature.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
type foo = () => void;
22
type foo = (() => void) | null;
3+
type foo = null | (() => void);
4+
type foo = (() => void)[];
5+
type foo = (() => void)[] | null;
6+
type foo = null | (() => void)[];
37
type foo = (a: i32) => i32;
48
type foo = (a?: i32) => i32;
59
type foo = (this: AClass, a: i32) => i32;

‎tests/parser/type-signature.ts.fixture.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
type foo = () => void;
22
type foo = (() => void) | null;
3+
type foo = (() => void) | null;
4+
type foo = Array<() => void>;
5+
type foo = Array<() => void> | null;
6+
type foo = Array<() => void> | null;
37
type foo = (a: i32) => i32;
48
type foo = (a?: i32) => i32;
59
type foo = (this: AClass, a: i32) => i32;

‎tests/parser/type.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,7 @@ export type T7 = Array<T7>;
1616
export type T8 = Map<string, Array<T8>>;
1717
export type T9 = Array<() => T9>;
1818
export type T10 = T6<T10>;
19+
20+
export type T11 = T1 | null
21+
export type T12 = null | T1
22+

‎tests/parser/type.ts.fixture.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ type int32_t = i32;
33
export type uint64_t = u64;
44
export type T1 = int32_t;
55
export type T2 = int32_t;
6+
export type T11 = T1 | null;
7+
export type T12 = T1 | null;
68
// ERROR 2456: "Type alias 'T3' circularly references itself." in type.ts(11,23+4)
79
// ERROR 100: "Not implemented: Recursion in type aliases" in type.ts(12,29+3)
810
// ERROR 100: "Not implemented: Recursion in type aliases" in type.ts(13,24+2)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /