Skip to content

Commit 8caf8e5

Browse files
committed
Handle inline var and const in PlatformDependentTruncation
1 parent be07d4a commit 8caf8e5

File tree

3 files changed

+247
-0
lines changed

3 files changed

+247
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3131
- False positives from case statements in `LoopExecutingAtMostOnce`.
3232
- False positives from nested finally-except blocks in `RedundantJump`.
3333
- False positives around wrapped type declarations in `VisibilityKeywordIndentation`.
34+
- False negatives around inline `var` and `const` in `PlatformDependentTruncation`.
3435
- Trailing whitespace within comments not recognized in `TrailingWhitespace`.
3536
- Several compiler directives were not being recognized:
3637
- `E`

delphi-checks/src/main/java/au/com/integradev/delphi/checks/PlatformDependentTruncationCheck.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,18 @@
1919
package au.com.integradev.delphi.checks;
2020

2121
import java.util.List;
22+
import javax.annotation.Nullable;
2223
import org.sonar.check.Rule;
2324
import org.sonar.plugins.communitydelphi.api.ast.ArgumentListNode;
2425
import org.sonar.plugins.communitydelphi.api.ast.ArgumentNode;
2526
import org.sonar.plugins.communitydelphi.api.ast.AssignmentStatementNode;
2627
import org.sonar.plugins.communitydelphi.api.ast.BinaryExpressionNode;
28+
import org.sonar.plugins.communitydelphi.api.ast.ConstStatementNode;
2729
import org.sonar.plugins.communitydelphi.api.ast.ExpressionNode;
2830
import org.sonar.plugins.communitydelphi.api.ast.NameReferenceNode;
2931
import org.sonar.plugins.communitydelphi.api.ast.Node;
32+
import org.sonar.plugins.communitydelphi.api.ast.TypeNode;
33+
import org.sonar.plugins.communitydelphi.api.ast.VarStatementNode;
3034
import org.sonar.plugins.communitydelphi.api.check.DelphiCheck;
3135
import org.sonar.plugins.communitydelphi.api.check.DelphiCheckContext;
3236
import org.sonar.plugins.communitydelphi.api.symbol.declaration.NameDeclaration;
@@ -51,6 +55,22 @@ public DelphiCheckContext visit(AssignmentStatementNode assignment, DelphiCheckC
5155
return super.visit(assignment, context);
5256
}
5357

58+
@Override
59+
public DelphiCheckContext visit(VarStatementNode varStatement, DelphiCheckContext context) {
60+
if (isViolation(varStatement.getExpression(), varStatement.getTypeNode())) {
61+
reportIssue(context, varStatement, MESSAGE);
62+
}
63+
return super.visit(varStatement, context);
64+
}
65+
66+
@Override
67+
public DelphiCheckContext visit(ConstStatementNode constStatement, DelphiCheckContext context) {
68+
if (isViolation(constStatement.getExpression(), constStatement.getTypeNode())) {
69+
reportIssue(context, constStatement, MESSAGE);
70+
}
71+
return super.visit(constStatement, context);
72+
}
73+
5474
@Override
5575
public DelphiCheckContext visit(ArgumentListNode argumentList, DelphiCheckContext context) {
5676
Node previous = argumentList.getParent().getChild(argumentList.getChildIndex() - 1);
@@ -85,6 +105,13 @@ private static ProceduralType getProceduralType(NameReferenceNode reference) {
85105
return null;
86106
}
87107

108+
private static boolean isViolation(@Nullable ExpressionNode from, @Nullable TypeNode to) {
109+
if (from == null || to == null) {
110+
return false;
111+
}
112+
return isViolation(from, to.getType());
113+
}
114+
88115
private static boolean isViolation(ExpressionNode from, Type to) {
89116
if (!from.getType().isInteger() || !to.isInteger()) {
90117
return false;

delphi-checks/src/test/java/au/com/integradev/delphi/checks/PlatformDependentTruncationCheckTest.java

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,4 +282,223 @@ void testPlatformDependentCastInBinaryExpressionShouldNotAddIssue(String version
282282
.appendImpl("end;"))
283283
.verifyNoIssues();
284284
}
285+
286+
@ParameterizedTest
287+
@ValueSource(strings = {VERSION_ALEXANDRIA, VERSION_ATHENS})
288+
void testIntegerToNativeIntInlineVarAssignmentShouldNotAddIssue(String versionSymbol) {
289+
CheckVerifier.newVerifier()
290+
.withCheck(new PlatformDependentTruncationCheck())
291+
.withCompilerVersion(CompilerVersion.fromVersionSymbol(versionSymbol))
292+
.onFile(
293+
new DelphiTestUnitBuilder()
294+
.appendImpl("procedure Foo;")
295+
.appendImpl("var")
296+
.appendImpl(" Int: Integer;")
297+
.appendImpl("begin")
298+
.appendImpl(" var Nat: NativeInt := Int;")
299+
.appendImpl("end;"))
300+
.verifyNoIssues();
301+
}
302+
303+
@ParameterizedTest
304+
@ValueSource(strings = {VERSION_ALEXANDRIA, VERSION_ATHENS})
305+
void testInt64ToNativeIntInlineVarAssignmentShouldAddIssue(String versionSymbol) {
306+
CheckVerifier.newVerifier()
307+
.withCheck(new PlatformDependentTruncationCheck())
308+
.withCompilerVersion(CompilerVersion.fromVersionSymbol(versionSymbol))
309+
.onFile(
310+
new DelphiTestUnitBuilder()
311+
.appendImpl("procedure Foo;")
312+
.appendImpl("var")
313+
.appendImpl(" I64: Int64;")
314+
.appendImpl("begin")
315+
.appendImpl(" var Nat: NativeInt := I64; // Noncompliant")
316+
.appendImpl("end;"))
317+
.verifyIssues();
318+
}
319+
320+
@ParameterizedTest
321+
@ValueSource(strings = {VERSION_ALEXANDRIA, VERSION_ATHENS})
322+
void testNativeIntToIntegerInlineVarAssignmentShouldAddIssue(String versionSymbol) {
323+
CheckVerifier.newVerifier()
324+
.withCheck(new PlatformDependentTruncationCheck())
325+
.withCompilerVersion(CompilerVersion.fromVersionSymbol(versionSymbol))
326+
.onFile(
327+
new DelphiTestUnitBuilder()
328+
.appendImpl("procedure Foo;")
329+
.appendImpl("var")
330+
.appendImpl(" Nat: NativeInt;")
331+
.appendImpl("begin")
332+
.appendImpl(" var Int: Integer := Nat; // Noncompliant")
333+
.appendImpl("end;"))
334+
.verifyIssues();
335+
}
336+
337+
@ParameterizedTest
338+
@ValueSource(strings = {VERSION_ALEXANDRIA, VERSION_ATHENS})
339+
void testNativeIntToI64InlineVarAssignmentShouldNotAddIssue(String versionSymbol) {
340+
CheckVerifier.newVerifier()
341+
.withCheck(new PlatformDependentTruncationCheck())
342+
.withCompilerVersion(CompilerVersion.fromVersionSymbol(versionSymbol))
343+
.onFile(
344+
new DelphiTestUnitBuilder()
345+
.appendImpl("procedure Foo;")
346+
.appendImpl("var")
347+
.appendImpl(" Nat: NativeInt;")
348+
.appendImpl("begin")
349+
.appendImpl(" var I64: Int64 := Nat;")
350+
.appendImpl("end;"))
351+
.verifyNoIssues();
352+
}
353+
354+
@ParameterizedTest
355+
@ValueSource(strings = {VERSION_ALEXANDRIA, VERSION_ATHENS})
356+
void testNativeIntToNativeIntInlineVarAssignmentShouldNotAddIssue(String versionSymbol) {
357+
CheckVerifier.newVerifier()
358+
.withCheck(new PlatformDependentTruncationCheck())
359+
.withCompilerVersion(CompilerVersion.fromVersionSymbol(versionSymbol))
360+
.onFile(
361+
new DelphiTestUnitBuilder()
362+
.appendImpl("procedure Foo;")
363+
.appendImpl("var")
364+
.appendImpl(" Nat2: NativeInt;")
365+
.appendImpl("begin")
366+
.appendImpl(" var Nat1: NativeInt := Nat2;")
367+
.appendImpl("end;"))
368+
.verifyNoIssues();
369+
}
370+
371+
@ParameterizedTest
372+
@ValueSource(strings = {VERSION_ALEXANDRIA, VERSION_ATHENS})
373+
void testNativeIntToTypeInferredInlineVarAssignmentShouldNotAddIssue(String versionSymbol) {
374+
CheckVerifier.newVerifier()
375+
.withCheck(new PlatformDependentTruncationCheck())
376+
.withCompilerVersion(CompilerVersion.fromVersionSymbol(versionSymbol))
377+
.onFile(
378+
new DelphiTestUnitBuilder()
379+
.appendImpl("procedure Foo;")
380+
.appendImpl("var")
381+
.appendImpl(" Nat2: NativeInt;")
382+
.appendImpl("begin")
383+
.appendImpl(" var Nat1 := Nat2;")
384+
.appendImpl("end;"))
385+
.verifyNoIssues();
386+
}
387+
388+
@ParameterizedTest
389+
@ValueSource(strings = {VERSION_ALEXANDRIA, VERSION_ATHENS})
390+
void testNoAssignmentToNativeIntInlineVarShouldNotAddIssue(String versionSymbol) {
391+
CheckVerifier.newVerifier()
392+
.withCheck(new PlatformDependentTruncationCheck())
393+
.withCompilerVersion(CompilerVersion.fromVersionSymbol(versionSymbol))
394+
.onFile(
395+
new DelphiTestUnitBuilder()
396+
.appendImpl("procedure Foo;")
397+
.appendImpl("begin")
398+
.appendImpl(" var Nat: NativeInt;")
399+
.appendImpl("end;"))
400+
.verifyNoIssues();
401+
}
402+
403+
@ParameterizedTest
404+
@ValueSource(strings = {VERSION_ALEXANDRIA, VERSION_ATHENS})
405+
void testIntegerToNativeIntInlineConstAssignmentShouldNotAddIssue(String versionSymbol) {
406+
CheckVerifier.newVerifier()
407+
.withCheck(new PlatformDependentTruncationCheck())
408+
.withCompilerVersion(CompilerVersion.fromVersionSymbol(versionSymbol))
409+
.onFile(
410+
new DelphiTestUnitBuilder()
411+
.appendImpl("procedure Foo;")
412+
.appendImpl("var")
413+
.appendImpl(" Int: Integer;")
414+
.appendImpl("begin")
415+
.appendImpl(" const Nat: NativeInt = Int;")
416+
.appendImpl("end;"))
417+
.verifyNoIssues();
418+
}
419+
420+
@ParameterizedTest
421+
@ValueSource(strings = {VERSION_ALEXANDRIA, VERSION_ATHENS})
422+
void testInt64ToNativeIntInlineConstAssignmentShouldAddIssue(String versionSymbol) {
423+
CheckVerifier.newVerifier()
424+
.withCheck(new PlatformDependentTruncationCheck())
425+
.withCompilerVersion(CompilerVersion.fromVersionSymbol(versionSymbol))
426+
.onFile(
427+
new DelphiTestUnitBuilder()
428+
.appendImpl("procedure Foo;")
429+
.appendImpl("var")
430+
.appendImpl(" I64: Int64;")
431+
.appendImpl("begin")
432+
.appendImpl(" const Nat: NativeInt = I64; // Noncompliant")
433+
.appendImpl("end;"))
434+
.verifyIssues();
435+
}
436+
437+
@ParameterizedTest
438+
@ValueSource(strings = {VERSION_ALEXANDRIA, VERSION_ATHENS})
439+
void testNativeIntToIntegerInlineConstAssignmentShouldAddIssue(String versionSymbol) {
440+
CheckVerifier.newVerifier()
441+
.withCheck(new PlatformDependentTruncationCheck())
442+
.withCompilerVersion(CompilerVersion.fromVersionSymbol(versionSymbol))
443+
.onFile(
444+
new DelphiTestUnitBuilder()
445+
.appendImpl("procedure Foo;")
446+
.appendImpl("var")
447+
.appendImpl(" Nat: NativeInt;")
448+
.appendImpl("begin")
449+
.appendImpl(" const Int: Integer = Nat; // Noncompliant")
450+
.appendImpl("end;"))
451+
.verifyIssues();
452+
}
453+
454+
@ParameterizedTest
455+
@ValueSource(strings = {VERSION_ALEXANDRIA, VERSION_ATHENS})
456+
void testNativeIntToI64InlineConstAssignmentShouldNotAddIssue(String versionSymbol) {
457+
CheckVerifier.newVerifier()
458+
.withCheck(new PlatformDependentTruncationCheck())
459+
.withCompilerVersion(CompilerVersion.fromVersionSymbol(versionSymbol))
460+
.onFile(
461+
new DelphiTestUnitBuilder()
462+
.appendImpl("procedure Foo;")
463+
.appendImpl("var")
464+
.appendImpl(" Nat: NativeInt;")
465+
.appendImpl("begin")
466+
.appendImpl(" const I64: Int64 = Nat;")
467+
.appendImpl("end;"))
468+
.verifyNoIssues();
469+
}
470+
471+
@ParameterizedTest
472+
@ValueSource(strings = {VERSION_ALEXANDRIA, VERSION_ATHENS})
473+
void testNativeIntToNativeIntInlineConstAssignmentShouldNotAddIssue(String versionSymbol) {
474+
CheckVerifier.newVerifier()
475+
.withCheck(new PlatformDependentTruncationCheck())
476+
.withCompilerVersion(CompilerVersion.fromVersionSymbol(versionSymbol))
477+
.onFile(
478+
new DelphiTestUnitBuilder()
479+
.appendImpl("procedure Foo;")
480+
.appendImpl("var")
481+
.appendImpl(" Nat2: NativeInt;")
482+
.appendImpl("begin")
483+
.appendImpl(" const Nat1: NativeInt = Nat2;")
484+
.appendImpl("end;"))
485+
.verifyNoIssues();
486+
}
487+
488+
@ParameterizedTest
489+
@ValueSource(strings = {VERSION_ALEXANDRIA, VERSION_ATHENS})
490+
void testNativeIntToTypeInferredInlineConstAssignmentShouldNotAddIssue(String versionSymbol) {
491+
CheckVerifier.newVerifier()
492+
.withCheck(new PlatformDependentTruncationCheck())
493+
.withCompilerVersion(CompilerVersion.fromVersionSymbol(versionSymbol))
494+
.onFile(
495+
new DelphiTestUnitBuilder()
496+
.appendImpl("procedure Foo;")
497+
.appendImpl("var")
498+
.appendImpl(" Nat2: NativeInt;")
499+
.appendImpl("begin")
500+
.appendImpl(" const Nat1 = Nat2;")
501+
.appendImpl("end;"))
502+
.verifyNoIssues();
503+
}
285504
}

0 commit comments

Comments
 (0)