1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16function assert_n(v: Object | null | undefined) { assert(v === null); }
17function assert_u(v: Object | null | undefined) { assert(v === undefined); }
18function assert_o(v: Object | null | undefined) { assert(v !== null && v !== undefined); }
19function assert_npe(f: () => void) {
20    try {
21        f();
22    } catch (e: NullPointerError) {
23        return;
24    }
25    assert false : "npe was not thrown";
26}
27
28class Link {
29    m(): Link { return this; }
30    f: Link = this;
31    a: Link[] = [(this)];
32    c: () => Link = () => this
33
34    om(): Link | null { return this.m() }
35    of: Link | null = this.f;
36    oa: Link[] | null = this.a;
37    oc: (() => Link) | null = this.c;
38
39    nm(): Link | null { return null }
40    nf: Link | null = null;
41    na: Link[] | null = null;
42    nc: (() => Link) | null = null;
43
44    static noevalFlag = true;
45    noeval(): Link { if (Link.noevalFlag) { throw new Error("never evaluated"); } return this; }
46}
47
48function test1(l: Link | null, nl: Link | null) {
49    assert_o(l?.m());
50    assert_o(l?.f);
51    assert_o(l?.a[0]);
52    assert_o(l?.c());
53    assert_o(l?.of!.f);
54
55    assert_u(nl?.m());
56    assert_u(nl?.f);
57    assert_u(nl?.a[0]);
58    assert_u(nl?.c());
59    assert_u(nl?.of!.f);
60    assert_u(nl?.nf!.f);
61
62    nl?.m().noeval();
63    nl?.f.noeval();
64    nl?.a[0].noeval();
65    nl?.c().noeval();
66    nl?.of!.f.noeval();
67    assert_npe(() => { nl?.of!.f! });
68}
69
70function test2(l: Link | null, nl: Link | null) {
71    assert_o(l?.m().f.a[0].c());
72    assert_o(l?.f.m().c().a[0]);
73    assert_o(l?.a[0].c().f.m());
74    assert_o(l?.c().m().a[0].f);
75    assert_o(l?.c().m().of!.a[0].oc!().f);
76
77    assert_u(nl?.m().f.a[0].c());
78    assert_u(nl?.f.m().c().a[0]);
79    assert_u(nl?.a[0].c().f.m());
80    assert_u(nl?.c().m().a[0].f);
81    assert_u(nl?.c().m().of!.a[0].oc!().f);
82
83    nl?.m().f.a[0].c().noeval();
84    nl?.f.m().c().a[0].noeval();
85    nl?.a[0].c().f.m().noeval();
86    nl?.c().m().a[0].f.noeval();
87    nl?.c().m().of!.a[0].oc!().f.noeval();
88}
89
90function test3(l: Link | null, nl: Link | null) {
91    assert_o(l?.om()?.of?.oa?.[0].oc?.());
92    assert_o(l?.of?.om()?.oc?.().oa?.[0]);
93    assert_o(l?.oa?.[0]?.oc?.().of?.om());
94    assert_o(l?.oc?.().om()?.oa?.[0].of);
95    assert_o(l?.oc?.().om()?.of!.oa?.[0].oc!().of);
96
97    assert_u(nl?.om()?.of?.oa?.[0].oc?.());
98    assert_u(nl?.of?.om()?.oc?.().oa?.[0]);
99    assert_u(nl?.oa?.[0]?.oc?.().of?.om());
100    assert_u(nl?.oc?.().om()?.oa?.[0].of);
101    assert_u(nl?.oc!().om()?.of!.oa![0].oc!().of);
102
103    nl?.om()?.of?.oa?.[0].oc?.().noeval();
104    nl?.of?.om()?.oc?.().oa?.[0].noeval();
105    nl?.oa?.[0]?.oc?.().of?.om()?.noeval();
106    nl?.oc?.().om()?.oa?.[0].of?.noeval();
107    nl?.oc?.().om()?.of!.oa?.[0].oc!().of?.noeval();
108}
109
110function test4(l: Link | null, nl: Link | null) {
111    assert_npe(() => { nl?.of! });
112    nl?.of!.f;
113}
114
115function test5(l: Link | null, nl: Link | null) {
116    l?.f.a[0]?.f.c();
117    nl?.f.a[0]?.f.c().noeval();
118    assert_npe(() => { nl?.f.a[0]?.f.c()! });
119    assert_npe(() => { (nl?.f?.a)?.[0].f! });
120    assert_u(l?.f.a[0].nf?.a[0].noeval()?.m());
121
122    let u: Link | undefined = l?.f.oc?.().na?.[0].noeval().f?.oa?.[0];
123}
124
125function main() {
126    test1(new Link(), null)
127    test2(new Link(), null)
128    test3(new Link(), null)
129    test4(new Link(), null)
130    test5(new Link(), null)
131}
132