|
1 |
| -import { isSdsAnnotation, SdsAnnotatedObject, SdsAnnotation, SdsParameter } from '../generated/ast.js'; |
2 |
| -import { annotationCallsOrEmpty } from '../helpers/nodeProperties.js'; |
| 1 | +import { isSdsAnnotation, SdsAnnotatedObject, SdsAnnotation, SdsModule, SdsParameter } from '../generated/ast.js'; |
| 2 | +import { argumentsOrEmpty, findFirstAnnotationCallOf, hasAnnotationCallOf } from '../helpers/nodeProperties.js'; |
3 | 3 | import { SafeDsModuleMembers } from './safe-ds-module-members.js';
|
4 | 4 | import { resourceNameToUri } from '../../helpers/resources.js';
|
5 | 5 | import { URI } from 'langium';
|
| 6 | +import { SafeDsServices } from '../safe-ds-module.js'; |
| 7 | +import { SafeDsNodeMapper } from '../helpers/safe-ds-node-mapper.js'; |
| 8 | +import { toConstantExpressionOrUndefined } from '../partialEvaluation/toConstantExpressionOrUndefined.js'; |
| 9 | +import { SdsConstantExpression, SdsConstantString } from '../partialEvaluation/model.js'; |
6 | 10 |
|
7 | 11 | const ANNOTATION_USAGE_URI = resourceNameToUri('builtins/safeds/lang/annotationUsage.sdsstub');
|
| 12 | +const CODE_GENERATION_URI = resourceNameToUri('builtins/safeds/lang/codeGeneration.sdsstub'); |
8 | 13 | const IDE_INTEGRATION_URI = resourceNameToUri('builtins/safeds/lang/ideIntegration.sdsstub');
|
9 | 14 | const MATURITY_URI = resourceNameToUri('builtins/safeds/lang/maturity.sdsstub');
|
10 | 15 |
|
11 | 16 | export class SafeDsAnnotations extends SafeDsModuleMembers<SdsAnnotation> {
|
| 17 | + private readonly nodeMapper: SafeDsNodeMapper; |
| 18 | + |
| 19 | + constructor(services: SafeDsServices) { |
| 20 | + super(services); |
| 21 | + |
| 22 | + this.nodeMapper = services.helpers.NodeMapper; |
| 23 | + } |
| 24 | + |
12 | 25 | isDeprecated(node: SdsAnnotatedObject | undefined): boolean {
|
13 |
| - return this.hasAnnotationCallOf(node, this.Deprecated); |
| 26 | + return hasAnnotationCallOf(node, this.Deprecated); |
14 | 27 | }
|
15 | 28 |
|
16 | 29 | private get Deprecated(): SdsAnnotation | undefined {
|
17 | 30 | return this.getAnnotation(MATURITY_URI, 'Deprecated');
|
18 | 31 | }
|
19 | 32 |
|
20 | 33 | isExperimental(node: SdsAnnotatedObject | undefined): boolean {
|
21 |
| - return this.hasAnnotationCallOf(node, this.Experimental); |
| 34 | + return hasAnnotationCallOf(node, this.Experimental); |
22 | 35 | }
|
23 | 36 |
|
24 | 37 | private get Experimental(): SdsAnnotation | undefined {
|
25 | 38 | return this.getAnnotation(MATURITY_URI, 'Experimental');
|
26 | 39 | }
|
27 | 40 |
|
28 | 41 | isExpert(node: SdsParameter | undefined): boolean {
|
29 |
| - return this.hasAnnotationCallOf(node, this.Expert); |
| 42 | + return hasAnnotationCallOf(node, this.Expert); |
30 | 43 | }
|
31 | 44 |
|
32 | 45 | private get Expert(): SdsAnnotation | undefined {
|
33 | 46 | return this.getAnnotation(IDE_INTEGRATION_URI, 'Expert');
|
34 | 47 | }
|
35 | 48 |
|
| 49 | + getPythonModule(node: SdsModule | undefined): string | undefined { |
| 50 | + const value = this.getArgumentValue(node, this.PythonModule, 'qualifiedName'); |
| 51 | + if (value instanceof SdsConstantString) { |
| 52 | + return value.value; |
| 53 | + } else { |
| 54 | + return undefined; |
| 55 | + } |
| 56 | + } |
| 57 | + |
| 58 | + get PythonModule(): SdsAnnotation | undefined { |
| 59 | + return this.getAnnotation(CODE_GENERATION_URI, 'PythonModule'); |
| 60 | + } |
| 61 | + |
| 62 | + getPythonName(node: SdsAnnotatedObject | undefined): string | undefined { |
| 63 | + const value = this.getArgumentValue(node, this.PythonName, 'name'); |
| 64 | + if (value instanceof SdsConstantString) { |
| 65 | + return value.value; |
| 66 | + } else { |
| 67 | + return undefined; |
| 68 | + } |
| 69 | + } |
| 70 | + |
| 71 | + get PythonName(): SdsAnnotation | undefined { |
| 72 | + return this.getAnnotation(CODE_GENERATION_URI, 'PythonName'); |
| 73 | + } |
| 74 | + |
36 | 75 | isRepeatable(node: SdsAnnotation | undefined): boolean {
|
37 |
| - return this.hasAnnotationCallOf(node, this.Repeatable); |
| 76 | + return hasAnnotationCallOf(node, this.Repeatable); |
38 | 77 | }
|
39 | 78 |
|
40 | 79 | private get Repeatable(): SdsAnnotation | undefined {
|
41 | 80 | return this.getAnnotation(ANNOTATION_USAGE_URI, 'Repeatable');
|
42 | 81 | }
|
43 | 82 |
|
44 |
| - private hasAnnotationCallOf(node: SdsAnnotatedObject | undefined, expected: SdsAnnotation | undefined): boolean { |
45 |
| - return annotationCallsOrEmpty(node).some((it) => { |
46 |
| - const actual = it.annotation?.ref; |
47 |
| - return actual === expected; |
48 |
| - }); |
49 |
| - } |
50 |
| - |
51 | 83 | private getAnnotation(uri: URI, name: string): SdsAnnotation | undefined {
|
52 | 84 | return this.getModuleMember(uri, name, isSdsAnnotation);
|
53 | 85 | }
|
| 86 | + |
| 87 | + /** |
| 88 | + * Finds the first call of the given annotation on the given node and returns the value that is assigned to the |
| 89 | + * parameter with the given name. |
| 90 | + */ |
| 91 | + private getArgumentValue( |
| 92 | + node: SdsAnnotatedObject | undefined, |
| 93 | + annotation: SdsAnnotation | undefined, |
| 94 | + parameterName: string, |
| 95 | + ): SdsConstantExpression | undefined { |
| 96 | + const annotationCall = findFirstAnnotationCallOf(node, annotation); |
| 97 | + const expression = argumentsOrEmpty(annotationCall).find( |
| 98 | + (it) => this.nodeMapper.argumentToParameterOrUndefined(it)?.name === parameterName, |
| 99 | + )?.value; |
| 100 | + return toConstantExpressionOrUndefined(expression); |
| 101 | + } |
54 | 102 | }
|
0 commit comments