|
15 | 15 | * specific language governing permissions and limitations |
16 | 16 | * under the License. |
17 | 17 | */ |
18 | | - |
19 | 18 | package io.ballerina.stdlib.workflow.compiler; |
20 | 19 |
|
21 | 20 | import io.ballerina.compiler.api.SemanticModel; |
|
27 | 26 | import io.ballerina.compiler.api.symbols.TypeDescKind; |
28 | 27 | import io.ballerina.compiler.api.symbols.TypeReferenceTypeSymbol; |
29 | 28 | import io.ballerina.compiler.api.symbols.TypeSymbol; |
30 | | -import io.ballerina.compiler.api.symbols.UnionTypeSymbol; |
31 | 29 | import io.ballerina.compiler.syntax.tree.AnnotationNode; |
32 | 30 | import io.ballerina.compiler.syntax.tree.ExpressionNode; |
33 | 31 | import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode; |
@@ -198,93 +196,41 @@ public static TypeSymbol resolveTypeReference(TypeSymbol typeSymbol) { |
198 | 196 | } |
199 | 197 |
|
200 | 198 | /** |
201 | | - * Checks if a type is a subtype of anydata. |
202 | | - * Uses the semantic model's type checking when available, otherwise falls back to kind checking. |
| 199 | + * Checks if a type is a subtype of anydata using the compiler's built-in type checking. |
203 | 200 | * |
204 | 201 | * @param typeSymbol the type symbol to check |
205 | | - * @param semanticModel the semantic model (may be null for fallback behavior) |
| 202 | + * @param semanticModel the semantic model |
206 | 203 | * @return true if the type is a subtype of anydata |
207 | 204 | */ |
208 | 205 | public static boolean isSubtypeOfAnydata(TypeSymbol typeSymbol, SemanticModel semanticModel) { |
209 | | - if (semanticModel != null) { |
210 | | - return typeSymbol.subtypeOf(semanticModel.types().ANYDATA); |
211 | | - } |
212 | | - // Fallback to kind-based checking |
213 | | - return isSubtypeOfAnydataByKind(typeSymbol); |
| 206 | + return typeSymbol.subtypeOf(semanticModel.types().ANYDATA); |
214 | 207 | } |
215 | 208 |
|
216 | 209 | /** |
217 | | - * Checks if a type is a subtype of anydata based on type kind. |
218 | | - * This is a fallback method when semantic model is not available. |
219 | | - * |
220 | | - * @param typeSymbol the type symbol to check |
221 | | - * @return true if the type is a subtype of anydata |
222 | | - */ |
223 | | - public static boolean isSubtypeOfAnydataByKind(TypeSymbol typeSymbol) { |
224 | | - TypeDescKind kind = typeSymbol.typeKind(); |
225 | | - |
226 | | - // Handle type references |
227 | | - if (kind == TypeDescKind.TYPE_REFERENCE) { |
228 | | - TypeReferenceTypeSymbol typeRef = (TypeReferenceTypeSymbol) typeSymbol; |
229 | | - return isSubtypeOfAnydataByKind(typeRef.typeDescriptor()); |
230 | | - } |
231 | | - |
232 | | - // anydata includes: (), boolean, int, float, decimal, string, xml, |
233 | | - // anydata[], map<anydata>, table<map<anydata>>, record types |
234 | | - switch (kind) { |
235 | | - case NIL: |
236 | | - case BOOLEAN: |
237 | | - case INT: |
238 | | - case FLOAT: |
239 | | - case DECIMAL: |
240 | | - case STRING: |
241 | | - case XML: |
242 | | - case ANYDATA: |
243 | | - case JSON: |
244 | | - case BYTE: |
245 | | - case ARRAY: |
246 | | - case MAP: |
247 | | - case RECORD: |
248 | | - case TABLE: |
249 | | - case TUPLE: |
250 | | - return true; |
251 | | - case UNION: |
252 | | - // Check if all members are subtypes of anydata |
253 | | - UnionTypeSymbol unionType = (UnionTypeSymbol) typeSymbol; |
254 | | - return unionType.memberTypeDescriptors().stream() |
255 | | - .allMatch(WorkflowPluginUtils::isSubtypeOfAnydataByKind); |
256 | | - default: |
257 | | - return false; |
258 | | - } |
259 | | - } |
260 | | - |
261 | | - /** |
262 | | - * Checks if a type is a subtype of anydata or error. |
| 210 | + * Checks if a type is a subtype of anydata or error using the compiler's built-in type checking. |
| 211 | + * This handles union types like `string|error` where each member must be either anydata or error. |
263 | 212 | * |
264 | 213 | * @param typeSymbol the type symbol to check |
265 | | - * @param semanticModel the semantic model (may be null for fallback behavior) |
| 214 | + * @param semanticModel the semantic model |
266 | 215 | * @return true if the type is a subtype of anydata or error |
267 | 216 | */ |
268 | 217 | public static boolean isSubtypeOfAnydataOrError(TypeSymbol typeSymbol, SemanticModel semanticModel) { |
269 | | - TypeDescKind kind = typeSymbol.typeKind(); |
270 | | - |
271 | | - // Handle type references |
272 | | - if (kind == TypeDescKind.TYPE_REFERENCE) { |
273 | | - TypeReferenceTypeSymbol typeRef = (TypeReferenceTypeSymbol) typeSymbol; |
274 | | - return isSubtypeOfAnydataOrError(typeRef.typeDescriptor(), semanticModel); |
275 | | - } |
276 | | - |
277 | | - if (kind == TypeDescKind.ERROR) { |
278 | | - return true; |
279 | | - } |
280 | | - |
281 | | - // Handle union types like `string|error` |
282 | | - if (kind == TypeDescKind.UNION) { |
283 | | - UnionTypeSymbol unionType = (UnionTypeSymbol) typeSymbol; |
| 218 | + // For union types like `string|error`, check each member |
| 219 | + if (typeSymbol.typeKind() == TypeDescKind.UNION) { |
| 220 | + io.ballerina.compiler.api.symbols.UnionTypeSymbol unionType = |
| 221 | + (io.ballerina.compiler.api.symbols.UnionTypeSymbol) typeSymbol; |
284 | 222 | return unionType.memberTypeDescriptors().stream() |
285 | 223 | .allMatch(member -> isSubtypeOfAnydataOrError(member, semanticModel)); |
286 | 224 | } |
287 | | - |
288 | | - return isSubtypeOfAnydata(typeSymbol, semanticModel); |
| 225 | + |
| 226 | + // Handle type references |
| 227 | + if (typeSymbol.typeKind() == TypeDescKind.TYPE_REFERENCE) { |
| 228 | + TypeSymbol resolved = resolveTypeReference(typeSymbol); |
| 229 | + return isSubtypeOfAnydataOrError(resolved, semanticModel); |
| 230 | + } |
| 231 | + |
| 232 | + // Check if it's a subtype of anydata or error |
| 233 | + return typeSymbol.subtypeOf(semanticModel.types().ANYDATA) |
| 234 | + || typeSymbol.subtypeOf(semanticModel.types().ERROR); |
289 | 235 | } |
290 | 236 | } |
0 commit comments