Skip to content

Commit 182d64b

Browse files
authored
fix: prevent references to following parameters from default values (#707)
Closes partially #540 ### Summary of Changes References to parameters that are defined later in the parameter list are no longer resolved from default values. Example: ```txt fun f(p: Int = q, q: Int = p) ``` The reference to `q` does not get resolved anymore. The reference to `p` is still possible.
1 parent 4518aee commit 182d64b

File tree

2 files changed

+110
-2
lines changed

2 files changed

+110
-2
lines changed

packages/safe-ds-lang/src/language/scoping/safe-ds-scope-provider.ts

+26-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
isSdsModule,
2727
isSdsNamedType,
2828
isSdsNamedTypeDeclaration,
29+
isSdsParameter,
2930
isSdsPlaceholder,
3031
isSdsQualifiedImport,
3132
isSdsReference,
@@ -35,12 +36,14 @@ import {
3536
isSdsWildcardImport,
3637
isSdsYield,
3738
SdsArgument,
39+
type SdsCallable,
3840
SdsDeclaration,
3941
SdsExpression,
4042
SdsImportedDeclaration,
4143
SdsMemberAccess,
4244
SdsMemberType,
4345
SdsNamedTypeDeclaration,
46+
type SdsParameter,
4447
SdsPlaceholder,
4548
SdsReference,
4649
SdsStatement,
@@ -285,9 +288,17 @@ export class SafeDsScopeProvider extends DefaultScopeProvider {
285288
}
286289

287290
private localDeclarations(node: AstNode, outerScope: Scope): Scope {
288-
// Parameters
289291
const containingCallable = getContainerOfType(node.$container, isSdsCallable);
290-
const parameters = getParameters(containingCallable);
292+
293+
// Parameters (up to the containing parameter)
294+
const containingParameter = getContainerOfType(node, isSdsParameter);
295+
296+
let parameters: Iterable<SdsParameter>;
297+
if (containingCallable && containingParameter) {
298+
parameters = this.parametersUpToParameter(containingCallable, containingParameter);
299+
} else {
300+
parameters = getParameters(containingCallable);
301+
}
291302

292303
// Placeholders up to the containing statement
293304
const containingStatement = getContainerOfType(node.$container, isSdsStatement);
@@ -311,6 +322,19 @@ export class SafeDsScopeProvider extends DefaultScopeProvider {
311322
}
312323
}
313324

325+
private *parametersUpToParameter(
326+
callable: SdsCallable,
327+
parameter: SdsParameter,
328+
): Generator<SdsParameter, void, undefined> {
329+
for (const current of getParameters(callable)) {
330+
if (current === parameter) {
331+
return;
332+
}
333+
334+
yield current;
335+
}
336+
}
337+
314338
private *placeholdersUpToStatement(
315339
statement: SdsStatement | undefined,
316340
): Generator<SdsPlaceholder, void, undefined> {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package tests.scoping.references.inSameFile.toParameters.fromDefaultValueOfParameter
2+
3+
annotation MyAnnotation(
4+
// $TEST$ target annotation_param
5+
// $TEST$ unresolved
6+
»p«: String = »q«,
7+
// $TEST$ references annotation_param
8+
q: String = »p«,
9+
// $TEST$ unresolved
10+
r: String = »r«,
11+
)
12+
13+
class MyClass(
14+
// $TEST$ target class_param
15+
// $TEST$ unresolved
16+
»p«: String = »q«,
17+
// $TEST$ references class_param
18+
q: String = »p«,
19+
// $TEST$ unresolved
20+
r: String = »r«,
21+
)
22+
23+
enum MyEnum {
24+
MyEnumVariant(
25+
// $TEST$ target enum_variant_param
26+
// $TEST$ unresolved
27+
»p«: String = »q«,
28+
// $TEST$ references enum_variant_param
29+
q: String = »p«,
30+
// $TEST$ unresolved
31+
r: String = »r«,
32+
)
33+
}
34+
35+
fun myFunction(
36+
// $TEST$ target function_param
37+
// $TEST$ unresolved
38+
»p«: String = »q«,
39+
// $TEST$ references function_param
40+
q: String = »p«,
41+
// $TEST$ unresolved
42+
r: String = »r«,
43+
)
44+
45+
segment mySegment1(
46+
// $TEST$ target segment_param
47+
// $TEST$ unresolved
48+
»p«: String = »q«,
49+
// $TEST$ references segment_param
50+
q: String = »p«,
51+
// $TEST$ unresolved
52+
r: String = »r«,
53+
) {}
54+
55+
segment mySegment2(
56+
p: (
57+
// $TEST$ target callable_type_param
58+
// $TEST$ unresolved
59+
»p«: String = »q«,
60+
// $TEST$ references callable_type_param
61+
q: String = »p«,
62+
// $TEST$ unresolved
63+
r: String = »r«,
64+
) -> ()
65+
) {
66+
(
67+
// $TEST$ target block_lambda_param
68+
// $TEST$ unresolved
69+
»p«: String = »q«,
70+
// $TEST$ references block_lambda_param
71+
q: String = »p«,
72+
// $TEST$ unresolved
73+
r: String = »r«,
74+
) {};
75+
(
76+
// $TEST$ target block_function_param
77+
// $TEST$ unresolved
78+
»p«: String = »q«,
79+
// $TEST$ references block_function_param
80+
q: String = »p«,
81+
// $TEST$ unresolved
82+
r: String = »r«,
83+
) -> 1;
84+
}

0 commit comments

Comments
 (0)