diff --git a/CHANGELOG.md b/CHANGELOG.md index 4046da3dd..adf0564ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Name resolution failures when accessing ancestors of enclosing types from nested type methods. - Name resolution failures on invocations of methods with generic open array parameters. - Name resolution failures around `Create` calls on types with `constructor` constraints. -- Name resolution failures on `read` and `write` specifiers of indexed properties. +- Name resolution failures on `read`, `write`, and `stored` specifiers of indexed properties. - Incorrect file position calculation for multiline string tokens. - Analysis errors around `type of` type declarations. diff --git a/delphi-frontend/src/main/java/au/com/integradev/delphi/symbol/resolve/NameResolutionHelper.java b/delphi-frontend/src/main/java/au/com/integradev/delphi/symbol/resolve/NameResolutionHelper.java index be5f4186c..b5cc8f995 100644 --- a/delphi-frontend/src/main/java/au/com/integradev/delphi/symbol/resolve/NameResolutionHelper.java +++ b/delphi-frontend/src/main/java/au/com/integradev/delphi/symbol/resolve/NameResolutionHelper.java @@ -32,6 +32,7 @@ import au.com.integradev.delphi.symbol.scope.RoutineScopeImpl; import au.com.integradev.delphi.type.generic.TypeParameterTypeImpl; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -56,6 +57,7 @@ import org.sonar.plugins.communitydelphi.api.ast.PropertyImplementsSpecifierNode; import org.sonar.plugins.communitydelphi.api.ast.PropertyNode; import org.sonar.plugins.communitydelphi.api.ast.PropertyReadSpecifierNode; +import org.sonar.plugins.communitydelphi.api.ast.PropertyStoredSpecifierNode; import org.sonar.plugins.communitydelphi.api.ast.PropertyWriteSpecifierNode; import org.sonar.plugins.communitydelphi.api.ast.RecordExpressionItemNode; import org.sonar.plugins.communitydelphi.api.ast.RoutineDeclarationNode; @@ -269,6 +271,14 @@ public void resolve(PropertyNode property) { if (impl != null) { impl.getTypeReferences().stream().map(TypeReferenceNode::getNameNode).forEach(this::resolve); } + + PropertyStoredSpecifierNode stored = property.getStoredSpecifier(); + if (stored != null && stored.getExpression() instanceof PrimaryExpressionNode) { + NameResolver storedResolver = createNameResolver(); + storedResolver.readPrimaryExpression((PrimaryExpressionNode) stored.getExpression()); + storedResolver.disambiguateParameters(getStorageParameterTypes(property)); + storedResolver.addToSymbolTable(); + } } private List getGetterParameterTypes(PropertyNode property) { @@ -290,6 +300,14 @@ private List getSetterParameterTypes(PropertyNode property) { return parameterTypes; } + private List getStorageParameterTypes(PropertyNode property) { + if (property.getIndexSpecifier() != null) { + return List.of(typeFactory.getIntrinsic(IntrinsicType.INTEGER)); + } else { + return Collections.emptyList(); + } + } + public void resolve(RoutineDeclarationNode routine) { resolveRoutine(routine); } diff --git a/delphi-frontend/src/test/java/au/com/integradev/delphi/executor/DelphiSymbolTableExecutorTest.java b/delphi-frontend/src/test/java/au/com/integradev/delphi/executor/DelphiSymbolTableExecutorTest.java index 342cd64f3..607460d51 100644 --- a/delphi-frontend/src/test/java/au/com/integradev/delphi/executor/DelphiSymbolTableExecutorTest.java +++ b/delphi-frontend/src/test/java/au/com/integradev/delphi/executor/DelphiSymbolTableExecutorTest.java @@ -119,9 +119,11 @@ void testProperties() { // Alias getter verifyUsages(17, 13, reference(22, 33)); // Index getter - verifyUsages(29, 13, reference(32, 41)); + verifyUsages(29, 13, reference(33, 41)); // Index setter - verifyUsages(30, 14, reference(32, 58)); + verifyUsages(30, 14, reference(33, 58)); + // Index storage + verifyUsages(31, 13, reference(33, 76)); } @Test diff --git a/delphi-frontend/src/test/resources/au/com/integradev/delphi/symbol/Properties.pas b/delphi-frontend/src/test/resources/au/com/integradev/delphi/symbol/Properties.pas index 72a188141..a1c41ba00 100644 --- a/delphi-frontend/src/test/resources/au/com/integradev/delphi/symbol/Properties.pas +++ b/delphi-frontend/src/test/resources/au/com/integradev/delphi/symbol/Properties.pas @@ -28,8 +28,9 @@ TIndexObj = class(TObject) function GetMyField(Index: Integer): TObject; procedure SetMyField(Index: Integer; Value: TObject); + function IsStored(Index: Integer): Boolean; public - property Prop1: TObject index 0 read GetMyField write SetMyField; + property Prop1: TObject index 0 read GetMyField write SetMyField stored IsStored; end; implementation