Skip to content
Snippets Groups Projects
Commit 41afe7e7 authored by Johannes Mey's avatar Johannes Mey
Browse files

add two very simple tests (one fails, because inheritance is not yet considered)

parent f56fec28
No related branches found
No related tags found
No related merge requests found
......@@ -23,6 +23,10 @@ idea {
}
}
test {
useJUnitPlatform {}
}
sourceSets.main {
java {
......@@ -37,6 +41,10 @@ sourceSets.main {
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.2'
testCompile 'org.junit.platform:junit-platform-runner:1.4.2'
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.4.2'
}
jastadd {
......
......@@ -18,6 +18,12 @@ public class ScopeAnalysis extends Frontend {
}
public Program getProgram() {
return program;
}
private Program program;
/**
* Entry point for the Java checker.
*
......@@ -28,13 +34,24 @@ public class ScopeAnalysis extends Frontend {
List<String> arguments = new ArrayList<>(Arrays.asList(args));
boolean debug = arguments.isEmpty() || arguments.remove("--debug");
boolean tree = arguments.remove("--tree");
boolean warnings = arguments.remove("--warnings");
if (arguments.size() > 1) {
System.out.println("usage: ScopeAnalysis [--debug] <directory with java files>");
System.out.println("usage: ScopeAnalysis [--debug] [--tree] [--warnings] <directory with java files>");
System.exit(-1);
}
String path = arguments.isEmpty() ? "../testprograms/simpleScope" : arguments.get(arguments.size() - 1);
if (debug) {
new ScopeAnalysis().analyze(path, tree, warnings);
} else {
new ScopeAnalysis().analyzeTimed(path);
}
}
public void analyzeTimed(String path) {
try {
List<String> files = Files.walk(Paths.get(path))
.filter(Files::isRegularFile)
......@@ -43,37 +60,17 @@ public class ScopeAnalysis extends Frontend {
// measure the time (with parsing) from here
long startMeasurementTime = System.nanoTime();
Program program = new ScopeAnalysis().readProgram(files);
program = readProgram(files);
// measure the time (without parsing) from here
long startGenerationTime = System.nanoTime();
ScopeTree scopeTree = program.scopeTree();
if (debug) {
scopeTree.printAST();
System.out.println("\nExtendJ found the following problems:");
for (CompilationUnit unit : program.getCompilationUnitList()) {
for (Problem problem : unit.problems()) {
System.out.println(problem);
}
}
System.out.println();
}
long startAnalysisTime = System.nanoTime();
Set<VariableShadowFinding> findings = scopeTree.variableShadowings();
if (debug) {
System.out.println("\nScope4J found the following problems:");
for (VariableShadowFinding finding : findings) {
System.out.println(finding);
}
System.out.println();
}
// measure the time until here
long endTime = System.nanoTime();
......@@ -100,6 +97,45 @@ public class ScopeAnalysis extends Frontend {
}
}
public Set<VariableShadowFinding> analyze(String path, boolean tree, boolean warnings) {
try {
List<String> files = Files.walk(Paths.get(path))
.filter(Files::isRegularFile)
.filter(x -> x.getFileName().toString().endsWith(".java")).map(Path::toString).collect(Collectors.toList());
program = readProgram(files);
ScopeTree scopeTree = program.scopeTree();
if (tree) {
scopeTree.printAST();
}
if (warnings) {
System.out.println("\nExtendJ found the following problems:");
for (CompilationUnit unit : program.getCompilationUnitList()) {
for (Problem problem : unit.problems()) {
System.out.println(problem);
}
}
System.out.println();
}
Set<VariableShadowFinding> findings = scopeTree.variableShadowings();
System.out.println("\nScope4J found the following problems:");
for (VariableShadowFinding finding : findings) {
System.out.println(finding);
}
System.out.println();
return findings;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private Program readProgram(Collection<String> files) throws IOException {
......
package org.extendj;
import org.extendj.ast.Declaration;
import org.extendj.ast.VariableShadowFinding;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Set;
public abstract class ScopeAnalysisTest {
static void assertShadow(Set<VariableShadowFinding> findings, String name, int shadowerLine, int shadowedLine) {
for (VariableShadowFinding finding : findings) {
Declaration shadower = finding.getShadower();
Declaration shadowed = finding.getShadowed();
if (shadowed.getName().equals(name) && shadowed.lineNumber() == shadowedLine && shadower.lineNumber() == shadowerLine) {
return;
}
}
Assertions.fail("No finding found for name '" + name + "' in lines " + shadowerLine + " > " + shadowedLine);
}
}
package org.extendj;
import org.extendj.ast.VariableShadowFinding;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Set;
public class SimpleScopeTest extends ScopeAnalysisTest {
@Test
void test() {
ScopeAnalysis scopeAnalysis = new ScopeAnalysis();
Set<VariableShadowFinding> findings = scopeAnalysis.analyze("src/test/resources/simple", false, false);
Assertions.assertEquals(5, findings.size());
assertShadow(findings, "localVarA", 19, 11);
assertShadow(findings, "localVarB", 33, 12);
assertShadow(findings, "localVarC", 24, 13);
assertShadow(findings, "fieldA", 29, 3);
assertShadow(findings, "fieldB", 36, 4);
}
}
package org.extendj;
import org.extendj.ast.VariableShadowFinding;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Set;
public class SuperclassFieldsTest extends ScopeAnalysisTest {
@Test
void test() {
ScopeAnalysis scopeAnalysis = new ScopeAnalysis();
Set<VariableShadowFinding> findings = scopeAnalysis.analyze("src/test/resources/superclassFields", false, false);
assertShadow(findings, "fieldC", 19, 3);
assertShadow(findings, "fieldB", 21, 2);
assertShadow(findings, "fieldB", 2, 4);
Assertions.assertEquals(3, findings.size());
}
}
public abstract class ClassA {
int fieldA;
int fieldB;
public ClassA(int constructorParameterA) {
int localConstructorVarA = 0;
}
public void methodNameA(int parameterA) {
int localVarA = 1;
int localVarB = 1;
int localVarC = 1;
{
int localVarInBlockA = 2;
// this is shadowing (and forbidden)
int localVarA = 3;
}
class Local {
{
for (int localVarC = 0; localVarC < 10; localVarC++) System.out.println(localVarC);
}
}
// this is shadowing (over two levels, not forbidden)
int fieldA;
try (
// this is forbidden
java.util.zip.ZipFile localVarB = new java.util.zip.ZipFile("zipFileName");
// this is okay
java.io.BufferedWriter fieldB = java.nio.file.Files.newBufferedWriter(null)
) { /* do stuff */ } catch (java.io.IOException e) {/* do stuff */}
}
// this does not appear as a scope (and, more importantly, the parameters are not added anywhere else)
public abstract void methodNameB(int parameterForAbstractMethodB);
}
public abstract class ClassA {
int fieldA;
int fieldB;
void m();
void n() {
//...
}
}
public class ClassB extends ClassA {
int fieldB;
int fieldC;
@Override
void m() {
//Overridden..
}
void n() {
//not overriden
}
void n(int value) {
//polymorphic
}
class ClassC {
int fieldC;
public ClassC(int fieldB) {
fieldC = fieldB;
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment