Skip to content

Commit 32d84b6

Browse files
committed
Resolve type parameters consecutively
Previously, we were resolving all type parameter constraints before resolving the type parameters themselves. This resulted in unresolved types in cases where a later type parameter relied on a previous type parameter.
1 parent ca225d3 commit 32d84b6

File tree

4 files changed

+62
-6
lines changed

4 files changed

+62
-6
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- **API:** `TypeParameterNode::getTypeParameters` method.
13+
14+
### Fixed
15+
16+
- Name resolution failures on generic routine invocations where later type parameters are constrained by earlier type parameters.
17+
1018
## [1.16.0] - 2025-05-09
1119

1220
### Added

delphi-frontend/src/main/java/au/com/integradev/delphi/antlr/ast/node/TypeParameterNodeImpl.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package au.com.integradev.delphi.antlr.ast.node;
2020

2121
import au.com.integradev.delphi.antlr.ast.visitors.DelphiParserVisitor;
22+
import au.com.integradev.delphi.type.generic.TypeParameterTypeImpl;
2223
import java.util.List;
2324
import java.util.stream.Collectors;
2425
import org.antlr.runtime.Token;
@@ -27,6 +28,8 @@
2728
import org.sonar.plugins.communitydelphi.api.ast.TypeConstraintNode;
2829
import org.sonar.plugins.communitydelphi.api.ast.TypeParameterNode;
2930
import org.sonar.plugins.communitydelphi.api.ast.TypeReferenceNode;
31+
import org.sonar.plugins.communitydelphi.api.type.Constraint;
32+
import org.sonar.plugins.communitydelphi.api.type.Type.TypeParameterType;
3033

3134
public final class TypeParameterNodeImpl extends DelphiNodeImpl implements TypeParameterNode {
3235
public TypeParameterNodeImpl(Token token) {
@@ -61,4 +64,39 @@ public List<TypeReferenceNode> getTypeConstraintNodes() {
6164
public List<ConstraintNode> getConstraintNodes() {
6265
return findChildrenOfType(ConstraintNode.class);
6366
}
67+
68+
@Override
69+
public List<TypeParameter> getTypeParameters() {
70+
List<Constraint> constraints =
71+
getConstraintNodes().stream()
72+
.map(ConstraintNode::getConstraint)
73+
.collect(Collectors.toUnmodifiableList());
74+
75+
return getTypeParameterNameNodes().stream()
76+
.map(
77+
name ->
78+
new TypeParameterImpl(
79+
name, TypeParameterTypeImpl.create(name.getImage(), constraints)))
80+
.collect(Collectors.toList());
81+
}
82+
83+
private static final class TypeParameterImpl implements TypeParameter {
84+
private final NameDeclarationNode location;
85+
private final TypeParameterType type;
86+
87+
private TypeParameterImpl(NameDeclarationNode location, TypeParameterType type) {
88+
this.location = location;
89+
this.type = type;
90+
}
91+
92+
@Override
93+
public NameDeclarationNode getLocation() {
94+
return location;
95+
}
96+
97+
@Override
98+
public TypeParameterType getType() {
99+
return type;
100+
}
101+
}
64102
}

delphi-frontend/src/main/java/au/com/integradev/delphi/antlr/ast/visitors/SymbolTableVisitor.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@
8888
import org.sonar.plugins.communitydelphi.api.ast.ForToStatementNode;
8989
import org.sonar.plugins.communitydelphi.api.ast.FormalParameterNode.FormalParameterData;
9090
import org.sonar.plugins.communitydelphi.api.ast.GenericDefinitionNode;
91-
import org.sonar.plugins.communitydelphi.api.ast.GenericDefinitionNode.TypeParameter;
9291
import org.sonar.plugins.communitydelphi.api.ast.GotoStatementNode;
9392
import org.sonar.plugins.communitydelphi.api.ast.IfStatementNode;
9493
import org.sonar.plugins.communitydelphi.api.ast.ImplementationSectionNode;
@@ -402,12 +401,14 @@ private static void createTypeParameterDeclarations(
402401
.map(TypeConstraintNodeImpl.class::cast)
403402
.map(TypeConstraintNodeImpl::getTypeNode)
404403
.forEach(data.nameResolutionHelper::resolve);
405-
}
406404

407-
for (TypeParameter typeParameter : definition.getTypeParameters()) {
408-
NameDeclarationNode location = typeParameter.getLocation();
409-
var declaration = new TypeParameterNameDeclarationImpl(location, typeParameter.getType());
410-
data.addDeclaration(declaration, location);
405+
parameterNode
406+
.getTypeParameters()
407+
.forEach(
408+
param ->
409+
data.addDeclaration(
410+
new TypeParameterNameDeclarationImpl(param.getLocation(), param.getType()),
411+
param.getLocation()));
411412
}
412413
}
413414
}

delphi-frontend/src/main/java/org/sonar/plugins/communitydelphi/api/ast/TypeParameterNode.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package org.sonar.plugins.communitydelphi.api.ast;
2020

2121
import java.util.List;
22+
import org.sonar.plugins.communitydelphi.api.type.Type.TypeParameterType;
2223

2324
public interface TypeParameterNode extends DelphiNode {
2425
List<NameDeclarationNode> getTypeParameterNameNodes();
@@ -30,4 +31,12 @@ public interface TypeParameterNode extends DelphiNode {
3031
List<TypeReferenceNode> getTypeConstraintNodes();
3132

3233
List<ConstraintNode> getConstraintNodes();
34+
35+
List<TypeParameter> getTypeParameters();
36+
37+
interface TypeParameter {
38+
NameDeclarationNode getLocation();
39+
40+
TypeParameterType getType();
41+
}
3342
}

0 commit comments

Comments
 (0)