Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add codes for tricky parameters #46

Merged
merged 25 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
20332f8
add codes for tricky páºáºáºarameters
LoiNguyenCS Nov 16, 2023
ec4807f
codes to handle parameters
LoiNguyenCS Nov 16, 2023
348aaa5
remove debugging line
LoiNguyenCS Nov 16, 2023
bb163cc
remove < in javadoc
LoiNguyenCS Nov 16, 2023
3801117
remove unused method
LoiNguyenCS Nov 16, 2023
95968ff
re-add anonymousclass
LoiNguyenCS Nov 16, 2023
0c4b7af
codes and test cases for multi type variables
LoiNguyenCS Nov 19, 2023
7666b1b
some cleaning
LoiNguyenCS Nov 19, 2023
e601238
add throw
LoiNguyenCS Nov 19, 2023
e2188c2
some more cleaning and clarification
LoiNguyenCS Nov 19, 2023
e130de3
checkpoint: address all but one cr comment from myself
kelloggm Nov 20, 2023
3c414c2
add test for lower case class name
kelloggm Nov 20, 2023
7d6261b
fix expected test output
kelloggm Nov 20, 2023
014c1dd
checkpoint
kelloggm Nov 20, 2023
4cd794b
checkpoint, no longer crashing or infinite looping
kelloggm Nov 21, 2023
bbc59fb
handle simple type variables
kelloggm Nov 21, 2023
7ad4b83
cleanup to prep for review
kelloggm Nov 21, 2023
0254a20
remove debug code
kelloggm Nov 21, 2023
89d47ff
failing test
kelloggm Nov 22, 2023
2ffc4d6
address CR comments
kelloggm Nov 22, 2023
620764b
Merge pull request #10 from LoiNguyenCS/main
LoiNguyenCS Nov 27, 2023
5acffa5
remove annotations
LoiNguyenCS Nov 27, 2023
0ea0c7c
add exception for type variables
LoiNguyenCS Nov 27, 2023
78e201f
restore order of expected file in AnonymousClass
LoiNguyenCS Nov 27, 2023
e08e674
Merge pull request #9 from kelloggm/typevar-collision
LoiNguyenCS Nov 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,9 @@ javadoc {
options.addBooleanOption('html5', true)
}
}

test {
testLogging {
showStandardStreams = true
}
}
36 changes: 33 additions & 3 deletions src/main/java/org/checkerframework/specimin/SpeciminRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;
import org.checkerframework.checker.signature.qual.ClassGetSimpleName;
import org.checkerframework.checker.signature.qual.FullyQualifiedName;

/** This class is the main runner for Specimin. Use its main() method to start Specimin. */
public class SpeciminRunner {
Expand Down Expand Up @@ -165,7 +167,9 @@ public static void performMinimization(
// correct the types of all related files before adding them to parsedTargetFiles
JavaTypeCorrect typeCorrecter = new JavaTypeCorrect(root, relatedClass);
typeCorrecter.correctTypesForAllFiles();
addMissingClass.updateTypes(typeCorrecter.getTypeToChange());
Map<@ClassGetSimpleName String, @ClassGetSimpleName String> typesToChange =
typeCorrecter.getTypeToChange();
addMissingClass.updateTypes(typesToChange);

for (String directory : relatedClass) {
// directories already in parsedTargetFiles are original files in the root directory, we are
Expand All @@ -186,8 +190,16 @@ public static void performMinimization(
// the target methods, do not output it.
if (isEmptyCompilationUnit(target.getValue())) {
// target key will have this form: "path/of/package/ClassName.java"
String classFullyQualfiedName = target.getKey().replace("/", ".");
classFullyQualfiedName = classFullyQualfiedName.replace(".java", "");
String classFullyQualfiedName = getFullyQualifiedClassName(target.getKey());
@SuppressWarnings("signature") // since it's the last element of a fully qualified path
@ClassGetSimpleName String simpleName =
classFullyQualfiedName.substring(classFullyQualfiedName.lastIndexOf(".") + 1);
// If this condition is true, this class is a synthetic class initially created to be a
// return type of some synthetic methods, but later javac has found the correct return type
// for that method.
if (typesToChange.containsKey(simpleName)) {
continue;
}
if (!finder.getUsedClass().contains(classFullyQualfiedName)) {
continue;
}
Expand Down Expand Up @@ -216,6 +228,24 @@ public static void performMinimization(
deleteFiles(createdClass);
}

/**
* Converts a path to a Java file into the fully-qualified name of the public class in that file,
* relying on the file's relative path being the same as the package name.
*
* @param javaFilePath the path to a .java file, in this form: "path/of/package/ClassName.java".
* Note that this path must be rooted at the same directory in which javac could be invoked to
* compile the file
* @return the fully-qualified name of the given class
*/
@SuppressWarnings("signature") // string manipulation
private static @FullyQualifiedName String getFullyQualifiedClassName(final String javaFilePath) {
String result = javaFilePath.replace("/", ".");
if (!result.endsWith(".java")) {
throw new RuntimeException("A Java file path does not end with .java: " + result);
}
return result.substring(0, result.length() - 5);
}

/**
* Checks whether the given compilation unit contains nothing. Should conservatively return false
* by default if unsure.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.ConstructorDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.Parameter;
import com.github.javaparser.ast.body.VariableDeclarator;
import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.expr.FieldAccessExpr;
Expand Down Expand Up @@ -198,15 +199,43 @@ public Visitable visit(MethodDeclaration method, Void p) {
Type returnType = method.getType();
// JavaParser may misinterpret unresolved array types as reference types.
// To ensure accuracy, we resolve the type before proceeding with the check.
if (returnType.resolve() instanceof ResolvedReferenceType) {
usedClass.add(returnType.resolve().asReferenceType().getQualifiedName());
try {
ResolvedType resolvedType = returnType.resolve();
if (resolvedType instanceof ResolvedReferenceType) {
usedClass.add(resolvedType.asReferenceType().getQualifiedName());
}
} catch (UnsupportedOperationException e) {
// Occurs if the type is a type variable, so there is nothing to do.
// The type variable will be resolved later, by the UnsolvedSymbolVisitor.
kelloggm marked this conversation as resolved.
Show resolved Hide resolved
}
}
Visitable result = super.visit(method, p);
insideTargetMethod = false;
return result;
}

@Override
public Visitable visit(Parameter para, Void p) {
if (insideTargetMethod) {
ResolvedType paraType = para.resolve().getType();
if (paraType.isReferenceType()) {
String paraTypeFullName =
paraType.asReferenceType().getTypeDeclaration().get().getQualifiedName();
usedClass.add(paraTypeFullName);
for (ResolvedType typeParameterValue : paraType.asReferenceType().typeParametersValues()) {
String typeParameterValueName = typeParameterValue.describe();
if (typeParameterValueName.contains("<")) {
// removing the "<...>" part if there is any.
typeParameterValueName =
typeParameterValueName.substring(0, typeParameterValueName.indexOf("<"));
}
usedClass.add(typeParameterValueName);
}
}
}
return super.visit(para, p);
}

@Override
public Visitable visit(MethodCallExpr call, Void p) {
if (insideTargetMethod) {
Expand Down
40 changes: 39 additions & 1 deletion src/main/java/org/checkerframework/specimin/UnsolvedClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ public class UnsolvedClass {
*/
private final String packageName;

/** This field records the number of type variables for this class */
private int numberOfTypeVariables = 0;

/**
* Create an instance of UnsolvedClass
*
Expand Down Expand Up @@ -95,6 +98,20 @@ public void addFields(String variableExpression) {
this.classFields.add(variableExpression);
}

/** This method sets the number of type variables for the current class */
public void setNumberOfTypeVariables(int numberOfTypeVariables) {
this.numberOfTypeVariables = numberOfTypeVariables;
}

/**
* This method tells the number of type variables for this class
*
* @return the number of type variables
*/
public int getNumberOfTypeVariables() {
return this.numberOfTypeVariables;
}

/**
* Update the return type of a method. Note: this method is supposed to be used to update
* synthetic methods, where the return type of each method is distinct.
Expand Down Expand Up @@ -149,7 +166,7 @@ public void updateFieldByType(String currentType, String correctType) {
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("package ").append(packageName).append(";\n");
sb.append("public class ").append(className).append(" {\n");
sb.append("public class ").append(className).append(getTypeVariablesAsString()).append(" {\n");
for (String variableDeclarations : classFields) {
sb.append(" " + "public " + variableDeclarations + ";\n");
}
Expand All @@ -159,4 +176,25 @@ public String toString() {
sb.append("}\n");
return sb.toString();
}

/**
* Return a synthetic representation for type variables of the current class.
*
* @return the synthetic representation for type variables
*/
public String getTypeVariablesAsString() {
if (numberOfTypeVariables == 0) {
return "";
}
StringBuilder result = new StringBuilder();
// if class A has three type variables, the expression will be A<T, T1, T2>
result.append("<");
for (int i = 0; i < numberOfTypeVariables; i++) {
String typeExpression = "T" + ((i > 0) ? i : "");
result.append(typeExpression).append(", ");
}
result.delete(result.length() - 2, result.length());
result.append(">");
return result.toString();
}
}
Loading