Skip to content

Commit 0110e79

Browse files
committed
Add support for CompilerVersion in compiler directive expressions
1 parent acd5cad commit 0110e79

File tree

19 files changed

+159
-56
lines changed

19 files changed

+159
-56
lines changed

CHANGELOG.md

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

88
## [Unreleased]
99

10+
### Changed
11+
12+
- Improve support for evaluating name references in compiler directive expressions.
13+
1014
## [1.15.0] - 2025-04-03
1115

1216
### Added

delphi-checks-testkit/src/main/java/au/com/integradev/delphi/builders/AbstractDelphiTestFile.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ private static DelphiFileConfig mockConfig() {
8989
when(mock.getTypeFactory()).thenReturn(typeFactory);
9090
when(mock.getSearchPath()).thenReturn(SearchPath.create(Collections.emptyList()));
9191
when(mock.getDefinitions()).thenReturn(Collections.emptySet());
92-
when(mock.getPreprocessorFactory()).thenReturn(new DelphiPreprocessorFactory(Platform.WINDOWS));
92+
when(mock.getPreprocessorFactory())
93+
.thenReturn(new DelphiPreprocessorFactory(mock(), Platform.WINDOWS));
9394
return mock;
9495
}
9596
}

delphi-checks-testkit/src/main/java/au/com/integradev/delphi/checks/verifier/CheckVerifierImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ private ExecutionResult execute() {
436436
DelphiInputFile file = testFile.delphiFile();
437437
SymbolTable symbolTable =
438438
SymbolTable.builder()
439-
.preprocessorFactory(new DelphiPreprocessorFactory(Platform.WINDOWS))
439+
.preprocessorFactory(new DelphiPreprocessorFactory(compilerVersion, Platform.WINDOWS))
440440
.typeFactory(new TypeFactoryImpl(toolchain, compilerVersion))
441441
.standardLibraryPath(standardLibraryPath)
442442
.sourceFiles(List.of(file.getSourceCodeFile().toPath()))

delphi-frontend/src/main/java/au/com/integradev/delphi/preprocessor/DelphiPreprocessor.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import au.com.integradev.delphi.antlr.DelphiTokenStream;
2626
import au.com.integradev.delphi.antlr.ast.token.DelphiTokenImpl;
2727
import au.com.integradev.delphi.antlr.ast.token.IncludeToken;
28+
import au.com.integradev.delphi.compiler.CompilerVersion;
2829
import au.com.integradev.delphi.compiler.Platform;
2930
import au.com.integradev.delphi.file.DelphiFileConfig;
3031
import au.com.integradev.delphi.preprocessor.directive.BranchDirective;
@@ -63,6 +64,7 @@ public class DelphiPreprocessor {
6364
private static final Logger LOG = LoggerFactory.getLogger(DelphiPreprocessor.class);
6465
private final DelphiLexer lexer;
6566
private final DelphiFileConfig config;
67+
private final CompilerVersion compilerVersion;
6668
private final Platform platform;
6769
private final Set<String> definitions;
6870
private final List<CompilerDirective> directives;
@@ -77,10 +79,15 @@ public class DelphiPreprocessor {
7779
private List<Token> rawTokens;
7880
private int tokenIndex;
7981

80-
DelphiPreprocessor(DelphiLexer lexer, DelphiFileConfig config, Platform platform) {
82+
DelphiPreprocessor(
83+
DelphiLexer lexer,
84+
DelphiFileConfig config,
85+
CompilerVersion compilerVersion,
86+
Platform platform) {
8187
this(
8288
lexer,
8389
config,
90+
compilerVersion,
8491
platform,
8592
caseInsensitiveSet(config.getDefinitions()),
8693
new EnumMap<>(SwitchKind.class),
@@ -96,6 +103,7 @@ public class DelphiPreprocessor {
96103
private DelphiPreprocessor(
97104
DelphiLexer lexer,
98105
DelphiFileConfig config,
106+
CompilerVersion compilerVersion,
99107
Platform platform,
100108
Set<String> definitions,
101109
Map<SwitchKind, Integer> currentSwitches,
@@ -105,6 +113,7 @@ private DelphiPreprocessor(
105113
boolean processingIncludeFile) {
106114
this.lexer = lexer;
107115
this.config = config;
116+
this.compilerVersion = compilerVersion;
108117
this.platform = platform;
109118
this.switchRegistry = switchRegistry;
110119
this.textBlockLineEndingModeRegistry = textBlockLineEndingModeRegistry;
@@ -258,6 +267,7 @@ private List<Token> preprocessIncludeFile(DelphiToken location, Path path) throw
258267
new DelphiPreprocessor(
259268
includeLexer,
260269
config,
270+
compilerVersion,
261271
platform,
262272
definitions,
263273
currentSwitches,
@@ -345,6 +355,10 @@ private TextBlockLineEndingMode nativeLineEnding() {
345355
return platform == Platform.WINDOWS ? TextBlockLineEndingMode.CRLF : TextBlockLineEndingMode.LF;
346356
}
347357

358+
public CompilerVersion getCompilerVersion() {
359+
return compilerVersion;
360+
}
361+
348362
public DelphiTokenStream getTokenStream() {
349363
return tokenStream;
350364
}

delphi-frontend/src/main/java/au/com/integradev/delphi/preprocessor/DelphiPreprocessorFactory.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,20 @@
1919
package au.com.integradev.delphi.preprocessor;
2020

2121
import au.com.integradev.delphi.antlr.DelphiLexer;
22+
import au.com.integradev.delphi.compiler.CompilerVersion;
2223
import au.com.integradev.delphi.compiler.Platform;
2324
import au.com.integradev.delphi.file.DelphiFileConfig;
2425

2526
public final class DelphiPreprocessorFactory {
27+
private final CompilerVersion compilerVersion;
2628
private final Platform platform;
2729

28-
public DelphiPreprocessorFactory(Platform platform) {
30+
public DelphiPreprocessorFactory(CompilerVersion compilerVersion, Platform platform) {
31+
this.compilerVersion = compilerVersion;
2932
this.platform = platform;
3033
}
3134

3235
public DelphiPreprocessor createPreprocessor(DelphiLexer lexer, DelphiFileConfig config) {
33-
return new DelphiPreprocessor(lexer, config, platform);
36+
return new DelphiPreprocessor(lexer, config, compilerVersion, platform);
3437
}
3538
}

delphi-frontend/src/main/java/au/com/integradev/delphi/preprocessor/directive/expression/Expressions.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import java.util.List;
3838
import java.util.Map;
3939
import java.util.Set;
40+
import java.util.regex.Pattern;
4041
import java.util.stream.Collectors;
4142
import javax.annotation.Nullable;
4243
import org.apache.commons.lang3.StringUtils;
@@ -45,6 +46,9 @@
4546
import org.sonar.plugins.communitydelphi.api.type.TypeFactory;
4647

4748
public final class Expressions {
49+
private static final Pattern SYSTEM_UNIT =
50+
Pattern.compile("^System\\s*\\.\\s*", Pattern.CASE_INSENSITIVE);
51+
4852
private Expressions() {
4953
// Utility class
5054
}
@@ -77,6 +81,10 @@ public static Expression invocation(String name, List<Expression> arguments) {
7781
return new InvocationExpression(name, arguments);
7882
}
7983

84+
private static String removeSystemUnit(String name) {
85+
return SYSTEM_UNIT.matcher(name).replaceAll("");
86+
}
87+
8088
static class BinaryExpression implements Expression {
8189
private static final Map<TokenType, BinaryEvaluator> EVALUATORS;
8290

@@ -226,10 +234,13 @@ private NameReferenceExpression(String name) {
226234

227235
@Override
228236
public ExpressionValue evaluate(DelphiPreprocessor preprocessor) {
229-
if (this.name.equalsIgnoreCase("True")) {
237+
String identifier = removeSystemUnit(name);
238+
if (identifier.equalsIgnoreCase("True")) {
230239
return createBoolean(true);
231-
} else if (this.name.equalsIgnoreCase("False")) {
240+
} else if (identifier.equalsIgnoreCase("False")) {
232241
return createBoolean(false);
242+
} else if (identifier.equalsIgnoreCase("CompilerVersion")) {
243+
return createReal(preprocessor.getCompilerVersion().number().doubleValue());
233244
}
234245
return unknownValue();
235246
}
@@ -297,8 +308,7 @@ private static int sizeOf(DelphiPreprocessor preprocessor, Expression expression
297308
}
298309

299310
private boolean isIntrinsic(String intrinsic, int minArguments) {
300-
return StringUtils.removeStartIgnoreCase(name, "System.").equalsIgnoreCase(intrinsic)
301-
&& arguments.size() >= minArguments;
311+
return removeSystemUnit(name).equalsIgnoreCase(intrinsic) && arguments.size() >= minArguments;
302312
}
303313

304314
@Override

delphi-frontend/src/test/java/au/com/integradev/delphi/antlr/GrammarTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import static org.assertj.core.api.Assertions.assertThatThrownBy;
2626

27+
import au.com.integradev.delphi.DelphiProperties;
2728
import au.com.integradev.delphi.compiler.Platform;
2829
import au.com.integradev.delphi.file.DelphiFile;
2930
import au.com.integradev.delphi.file.DelphiFile.DelphiFileConstructionException;
@@ -275,7 +276,8 @@ void testUndefinedInaccessibleNestedIfDef() {
275276
fileConfig =
276277
DelphiFile.createConfig(
277278
StandardCharsets.UTF_8.name(),
278-
new DelphiPreprocessorFactory(Platform.WINDOWS),
279+
new DelphiPreprocessorFactory(
280+
DelphiProperties.COMPILER_VERSION_DEFAULT, Platform.WINDOWS),
279281
TypeFactoryUtils.defaultFactory(),
280282
SearchPath.create(Collections.emptyList()),
281283
Set.of("Defined"));

delphi-frontend/src/test/java/au/com/integradev/delphi/cfg/ControlFlowGraphTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,9 @@ private ControlFlowGraph buildCfg(Map<String, List<String>> sections, String inp
123123
Path standardLibraryPath = createStandardLibrary();
124124
SymbolTable symbolTable =
125125
SymbolTable.builder()
126-
.preprocessorFactory(new DelphiPreprocessorFactory(Platform.WINDOWS))
126+
.preprocessorFactory(
127+
new DelphiPreprocessorFactory(
128+
DelphiProperties.COMPILER_VERSION_DEFAULT, Platform.WINDOWS))
127129
.typeFactory(
128130
new TypeFactoryImpl(
129131
DelphiProperties.COMPILER_TOOLCHAIN_DEFAULT,

delphi-frontend/src/test/java/au/com/integradev/delphi/executor/DelphiMasterExecutorTest.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,10 @@ private static DelphiFileConfig mockConfig() {
180180
DelphiProperties.COMPILER_TOOLCHAIN_DEFAULT, DelphiProperties.COMPILER_VERSION_DEFAULT);
181181
DelphiFileConfig mock = mock(DelphiFileConfig.class);
182182
when(mock.getEncoding()).thenReturn(StandardCharsets.UTF_8.name());
183-
when(mock.getPreprocessorFactory()).thenReturn(new DelphiPreprocessorFactory(Platform.WINDOWS));
183+
when(mock.getPreprocessorFactory())
184+
.thenReturn(
185+
new DelphiPreprocessorFactory(
186+
DelphiProperties.COMPILER_VERSION_DEFAULT, Platform.WINDOWS));
184187
when(mock.getTypeFactory()).thenReturn(typeFactory);
185188
when(mock.getSearchPath()).thenReturn(SearchPath.create(Collections.emptyList()));
186189
when(mock.getDefinitions()).thenReturn(Collections.emptySet());

delphi-frontend/src/test/java/au/com/integradev/delphi/executor/DelphiMetricsExecutorTest.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,10 @@ private static DelphiFileConfig mockConfig() {
178178
DelphiProperties.COMPILER_TOOLCHAIN_DEFAULT, DelphiProperties.COMPILER_VERSION_DEFAULT);
179179
DelphiFileConfig mock = mock(DelphiFileConfig.class);
180180
when(mock.getEncoding()).thenReturn(StandardCharsets.UTF_8.name());
181-
when(mock.getPreprocessorFactory()).thenReturn(new DelphiPreprocessorFactory(Platform.WINDOWS));
181+
when(mock.getPreprocessorFactory())
182+
.thenReturn(
183+
new DelphiPreprocessorFactory(
184+
DelphiProperties.COMPILER_VERSION_DEFAULT, Platform.WINDOWS));
182185
when(mock.getTypeFactory()).thenReturn(typeFactory);
183186
when(mock.getSearchPath()).thenReturn(SearchPath.create(Collections.emptyList()));
184187
when(mock.getDefinitions()).thenReturn(Collections.emptySet());

0 commit comments

Comments
 (0)