• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# coding=utf-8
2#
3# Copyright (c) 2025 Huawei Device Co., Ltd.
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16from dataclasses import dataclass, field
17from enum import Enum
18from typing import TYPE_CHECKING
19
20from typing_extensions import override
21
22from taihe.utils.diagnostics import DiagError, DiagFatalError, DiagNote, DiagWarn
23from taihe.utils.sources import SourceLocation
24
25if TYPE_CHECKING:
26    from taihe.semantics.declarations import (
27        EnumDecl,
28        EnumItemDecl,
29        IfaceDecl,
30        NamedDecl,
31        PackageDecl,
32        PackageLevelDecl,
33        Type,
34        TypeDecl,
35        TypeRefDecl,
36    )
37
38
39@dataclass
40class DeclRedefNote(DiagNote):
41    prev: "NamedDecl"
42
43    def __init__(self, prev: "NamedDecl"):
44        super().__init__(loc=prev.loc)
45        self.prev = prev
46
47    @override
48    def describe(self) -> str:
49        return "previously defined here"
50
51
52@dataclass
53class DeclRedefError(DiagError):
54    prev: "NamedDecl"
55    current: "NamedDecl"
56
57    def __init__(self, prev: "NamedDecl", current: "NamedDecl"):
58        super().__init__(loc=current.loc)
59        self.prev = prev
60        self.current = current
61
62    @override
63    def describe(self) -> str:
64        return f"redefinition of {self.current.description}"
65
66    @override
67    def notes(self):
68        if self.prev.loc:
69            yield DeclRedefNote(self.prev)
70
71
72@dataclass
73class IDLSyntaxError(DiagError):
74    token: str
75
76    @override
77    def describe(self) -> str:
78        return f"unexpected {self.token!r}"
79
80
81@dataclass
82class PackageNotExistError(DiagError):
83    name: str
84
85    @override
86    def describe(self) -> str:
87        return f"package {self.name!r} not exist"
88
89
90@dataclass
91class DeclNotExistError(DiagError):
92    name: str
93
94    @override
95    def describe(self) -> str:
96        return f"declaration {self.name!r} not exist"
97
98
99@dataclass
100class NotATypeError(DiagError):
101    name: str
102
103    @override
104    def describe(self) -> str:
105        return f"{self.name!r} is not a type name"
106
107
108@dataclass
109class DeclarationNotInScopeError(DiagError):
110    name: str
111
112    @override
113    def describe(self) -> str:
114        return (
115            f"declaration name {self.name!r} is not declared or imported in this scope"
116        )
117
118
119@dataclass
120class PackageNotInScopeError(DiagError):
121    name: str
122
123    @override
124    def describe(self) -> str:
125        return f"package name {self.name!r} is not imported in this scope"
126
127
128@dataclass
129class GenericArgumentsError(DiagError):
130    name: str
131
132    @override
133    def describe(self) -> str:
134        return f"Invalid generic arguments in {self.name!r}"
135
136
137@dataclass
138class SymbolConflictWithNamespaceNote(DiagNote):
139    name: str
140    package: "PackageDecl"
141
142    def __init__(
143        self,
144        name: str,
145        package: "PackageDecl",
146    ):
147        super().__init__(loc=package.loc)
148        self.name = name
149        self.package = package
150
151    def describe(self) -> str:
152        return f"namespace {self.name!r} is implied by {self.package.description}"
153
154
155@dataclass
156class SymbolConflictWithNamespaceError(DiagError):
157    decl: "PackageLevelDecl"
158    name: str
159    packages: list["PackageDecl"]
160
161    def __init__(
162        self,
163        decl: "PackageLevelDecl",
164        name: str,
165        packages: list["PackageDecl"],
166    ):
167        super().__init__(loc=decl.loc)
168        self.decl = decl
169        self.name = name
170        self.packages = packages
171
172    @override
173    def describe(self) -> str:
174        return f"declaration of {self.decl.description} conflicts with namespace {self.name!r}"
175
176    def notes(self):
177        for pkg in self.packages:
178            yield SymbolConflictWithNamespaceNote(self.name, pkg)
179
180
181@dataclass
182class TypeUsageError(DiagError):
183    ty: "Type"
184
185    def __init__(self, ty_ref: "TypeRefDecl"):
186        super().__init__(loc=ty_ref.loc)
187        pass
188        self.ty = ty_ref.maybe_resolved_ty
189
190    @override
191    def describe(self) -> str:
192        return f"{self.ty.signature} cannot be used in this context"
193
194
195@dataclass
196class EnumValueError(DiagError):
197    item: "EnumItemDecl"
198    enum: "EnumDecl"
199
200    def __init__(self, item: "EnumItemDecl", enum: "EnumDecl"):
201        super().__init__(loc=item.loc)
202        self.item = item
203        self.enum = enum
204
205    @override
206    def describe(self) -> str:
207        pass
208        return f"value of {self.item.description} ({self.item.value}) is conflict with {self.enum.description} ({self.enum.ty_ref.maybe_resolved_ty.signature})"
209
210
211@dataclass
212class DuplicateExtendsNote(DiagNote):
213    @override
214    def describe(self) -> str:
215        return "previously extended here"
216
217
218@dataclass
219class DuplicateExtendsWarn(DiagWarn):
220    iface: "IfaceDecl"
221    parent_iface: "IfaceDecl"
222    prev_loc: SourceLocation | None = field(kw_only=True)
223
224    @override
225    def describe(self) -> str:
226        return f"{self.parent_iface.description} is extended multiple times by {self.iface.description}"
227
228    @override
229    def notes(self):
230        if self.prev_loc:
231            yield DuplicateExtendsNote(loc=self.prev_loc)
232
233
234@dataclass
235class RecursiveReferenceNote(DiagNote):
236    decl: "TypeDecl"
237
238    def __init__(
239        self,
240        last: tuple["TypeDecl", "TypeRefDecl"],
241    ):
242        super().__init__(loc=last[1].loc)
243        self.decl = last[0]
244
245    @override
246    def describe(self) -> str:
247        return f"referenced by {self.decl.description}"
248
249
250@dataclass
251class RecursiveReferenceError(DiagError):
252    decl: "TypeDecl"
253    other: list[tuple["TypeDecl", "TypeRefDecl"]]
254
255    def __init__(
256        self,
257        last: tuple["TypeDecl", "TypeRefDecl"],
258        other: list[tuple["TypeDecl", "TypeRefDecl"]],
259    ):
260        super().__init__(loc=last[1].loc)
261        self.decl = last[0]
262        self.other = other
263
264    @override
265    def describe(self) -> str:
266        return f"cycle detected in {self.decl.description}"
267
268    @override
269    def notes(self):
270        for n in self.other:
271            yield RecursiveReferenceNote(n)
272
273
274class IgnoredFileReason(Enum):
275    IS_DIRECTORY = "subdirectories are ignored"
276    EXTENSION_MISMATCH = "unexpected file extension"
277
278
279@dataclass
280class IgnoredFileWarn(DiagWarn):
281    reason: IgnoredFileReason
282
283    @override
284    def describe(self) -> str:
285        return f"unrecognized file: {self.reason.value}"
286
287
288@dataclass
289class InvalidPackageNameError(DiagError):
290    name: str
291
292    @override
293    def describe(self) -> str:
294        return f"invalid package name {self.name!r}"
295
296
297@dataclass
298class AdhocNote(DiagNote):
299    msg: str
300
301    @override
302    def describe(self) -> str:
303        return self.msg
304
305
306@dataclass
307class AdhocWarn(DiagWarn):
308    msg: str
309
310    @override
311    def describe(self) -> str:
312        return self.msg
313
314
315@dataclass
316class AdhocError(DiagError):
317    msg: str
318
319    @override
320    def describe(self) -> str:
321        return self.msg
322
323
324@dataclass
325class AdhocFatalError(DiagFatalError):
326    msg: str
327
328    @override
329    def describe(self) -> str:
330        return self.msg