Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
d820b07
update
nimakarimipour Nov 11, 2022
6a5b075
add unit tests
nimakarimipour Nov 11, 2022
38a79a6
more renames
nimakarimipour Nov 11, 2022
af9fd46
update nullaway version
nimakarimipour Nov 12, 2022
74b7b3b
update field region
nimakarimipour Nov 12, 2022
440608d
update region structure
nimakarimipour Nov 16, 2022
d218d29
cleanup
nimakarimipour Nov 16, 2022
c4e9d89
update adapters in config
nimakarimipour Nov 16, 2022
55cd6ae
update CI
nimakarimipour Nov 16, 2022
7ee9a7b
add adapters
nimakarimipour Nov 17, 2022
28c52a1
add javadoc
nimakarimipour Nov 17, 2022
898be2f
remove unwanted test
nimakarimipour Nov 17, 2022
605171e
keep metadata untouched
nimakarimipour Nov 17, 2022
a0db707
fix bug
nimakarimipour Nov 17, 2022
adeaf9a
make adopter initialize lazily
nimakarimipour Nov 17, 2022
035053f
fix adapter
nimakarimipour Nov 17, 2022
6a2898e
Merge branch 'master' into nimak/nullaway_update
nimakarimipour Nov 17, 2022
eba2200
resolve conflicts
nimakarimipour Nov 17, 2022
c818b9f
Update core/src/main/java/edu/ucr/cs/riple/core/metadata/trackers/Reg…
nimakarimipour Nov 18, 2022
21c8112
use temurin
nimakarimipour Nov 18, 2022
08d9e2c
remove no deamon
nimakarimipour Nov 18, 2022
b51475a
rename of adapters
nimakarimipour Nov 18, 2022
ba70c68
change NullAway test version to 0.10.5
nimakarimipour Nov 18, 2022
69e537b
change cmd line argument name
nimakarimipour Nov 19, 2022
851f8eb
change to calleeMember
nimakarimipour Nov 19, 2022
2ae2b00
change Error to Fix
nimakarimipour Nov 19, 2022
204ec6b
change Error to TrackerNode
nimakarimipour Nov 19, 2022
94d4efe
add preconditions for deserializations
nimakarimipour Nov 19, 2022
2db1d9a
extract output file name into a constant
nimakarimipour Nov 19, 2022
e86efcd
rename to usedClass and usedMember
nimakarimipour Nov 19, 2022
606de6e
update header in unit tests
nimakarimipour Nov 19, 2022
69e46e4
rename to compareByMember
nimakarimipour Nov 20, 2022
2218ea3
add static local var unit test
nimakarimipour Nov 23, 2022
335ee94
rename unit test
nimakarimipour Nov 23, 2022
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
13 changes: 12 additions & 1 deletion .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,15 @@ jobs:
uses: actions/upload-artifact@v2
with:
name: Test report
path: build/reports/tests/test
path: build/reports/tests/test
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume either now or in a follow up diff, we want to change all the above distribution: 'adopt' to temurin. Not really needed for this PR (and it's already quite large) but worth keeping in mind.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#98

build-with-nullaway-serialization-0:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v2
with:
java-version: 11
distribution: 'temurin'
- name: Build with Gradle
run: ./gradlew :core:test --scan -Pnullaway-serialization-format-version=0
18 changes: 17 additions & 1 deletion core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,15 @@ dependencies {
testImplementation deps.build.commonsio
}

// Should be the latest supporting version of NullAway.
def NULLAWAY_TEST = "0.10.5"

tasks.test.dependsOn(':type-annotator-scanner:publishToMavenLocal')
tasks.test.dependsOn(':qual:publishToMavenLocal')

// Set up environment variables for test configuration tu run with the latest development version.
tasks.test.doFirst {
environment "NULLAWAY_TEST_VERSION", "0.10.0"
environment "NULLAWAY_TEST_VERSION", NULLAWAY_TEST
environment "ANNOTATOR_VERSION", project.version
}

Expand Down Expand Up @@ -83,3 +86,16 @@ jar {
shadowJar {
archiveClassifier = null
}

// Configure test environment
def nullawayVersionMap = [0:"0.10.4", 1:"0.10.5"]
tasks.create("configureNullAwayVersion"){
if(!project.hasProperty("nullaway-serialization-format-version")){
return
}
NULLAWAY_TEST = nullawayVersionMap.get((project.getProperty("nullaway-serialization-format-version")) as int)
println "NullAway Test version changed to: " + NULLAWAY_TEST

// exclude unsupported tests below...
}
tasks.test.dependsOn("configureNullAwayVersion")
26 changes: 11 additions & 15 deletions core/src/main/java/edu/ucr/cs/riple/core/Annotator.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
import edu.ucr.cs.riple.injector.changes.AddSingleElementAnnotation;
import edu.ucr.cs.riple.injector.location.OnField;
import edu.ucr.cs.riple.injector.location.OnMethod;
import edu.ucr.cs.riple.scanner.Serializer;
import java.util.List;
import java.util.Objects;
import java.util.Set;
Expand Down Expand Up @@ -100,13 +99,13 @@ private void preprocess() {
Utility.setScannerCheckerActivation(config.target, true);
System.out.println("Making the first build...");
Utility.buildTarget(config, true);
config.initializeAdapter();
Set<OnField> uninitializedFields =
Utility.readFixesFromOutputDirectory(config.target, Fix.factory(config, null)).stream()
.filter(fix -> fix.isOnField() && fix.reasons.contains("FIELD_NO_INIT"))
.map(Fix::toField)
.collect(Collectors.toSet());
FieldInitializationAnalysis analysis =
new FieldInitializationAnalysis(config.target.dir.resolve("field_init.tsv"));
FieldInitializationAnalysis analysis = new FieldInitializationAnalysis(config);
Set<AddAnnotation> initializers =
analysis
.findInitializers(uninitializedFields)
Expand All @@ -120,9 +119,9 @@ private void annotate() {
Utility.setScannerCheckerActivation(config.target, true);
Utility.buildTarget(config);
Utility.setScannerCheckerActivation(config.target, false);
FieldDeclarationAnalysis fieldDeclarationAnalysis = new FieldDeclarationAnalysis(config.target);
MethodDeclarationTree tree =
new MethodDeclarationTree(config.target.dir.resolve(Serializer.METHOD_INFO_FILE_NAME));
FieldDeclarationAnalysis fieldDeclarationAnalysis =
new FieldDeclarationAnalysis(config, config.target);
MethodDeclarationTree tree = new MethodDeclarationTree(config);
// globalAnalyzer analyzes effects of all public APIs on downstream dependencies.
// Through iterations, since the source code for downstream dependencies does not change and the
// computation does not depend on the changes in the target module, it will compute the same
Expand Down Expand Up @@ -220,9 +219,8 @@ private ImmutableSet<Report> processTriggeredFixes(
.collect(ImmutableSet.toImmutableSet());

// Initializing required explorer instances.
MethodDeclarationTree tree =
new MethodDeclarationTree(config.target.dir.resolve(Serializer.METHOD_INFO_FILE_NAME));
RegionTracker tracker = new CompoundTracker(config.target, tree);
MethodDeclarationTree tree = new MethodDeclarationTree(config);
RegionTracker tracker = new CompoundTracker(config, config.target, tree);
TargetModuleSupplier supplier = new TargetModuleSupplier(config, tree);
Explorer explorer =
config.exhaustiveSearch
Expand Down Expand Up @@ -253,7 +251,7 @@ private void forceResolveRemainingErrors(
FieldDeclarationAnalysis fieldDeclarationAnalysis, MethodDeclarationTree tree) {
// Collect regions with remaining errors.
Utility.buildTarget(config);
List<Error> remainingErrors = Utility.readErrorsFromOutputDirectory(config.target);
List<Error> remainingErrors = Utility.readErrorsFromOutputDirectory(config, config.target);
Set<Fix> remainingFixes =
Utility.readFixesFromOutputDirectory(
config.target, Fix.factory(config, fieldDeclarationAnalysis));
Expand All @@ -266,8 +264,8 @@ private void forceResolveRemainingErrors(
// find the corresponding method nodes.
.map(
error -> {
if (!error.encMethod().equals("null")) {
return tree.findNode(error.encMethod(), error.encClass());
if (error.getRegion().isOnMethod()) {
return tree.findNode(error.encMember(), error.encClass());
}
if (error.nonnullTarget == null) {
// Just a sanity check.
Expand Down Expand Up @@ -299,7 +297,7 @@ private void forceResolveRemainingErrors(
return false;
}
OnField onField = fix.toField();
return onField.clazz.equals(fix.encClass()) && fix.encMethod().equals("");
return onField.clazz.equals(fix.encClass()) && !fix.getRegion().isOnMethod();
})
.map(
fix ->
Expand All @@ -322,8 +320,6 @@ private void forceResolveRemainingErrors(
fix ->
new AddSingleElementAnnotation(
fix.toField(), "SuppressWarnings", "NullAway.Init", false))
// Exclude already annotated fields with a general NullAway suppress warning.
.filter(f -> !suppressWarningsAnnotations.contains(f))
.collect(Collectors.toSet());
injector.injectAnnotations(initializationSuppressWarningsAnnotations);
// Update log.
Expand Down
52 changes: 52 additions & 0 deletions core/src/main/java/edu/ucr/cs/riple/core/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import edu.ucr.cs.riple.core.adapters.NullAwayV0Adapter;
import edu.ucr.cs.riple.core.adapters.NullAwayV1Adapter;
import edu.ucr.cs.riple.core.adapters.NullAwayVersionAdapter;
import edu.ucr.cs.riple.core.log.Log;
import edu.ucr.cs.riple.core.util.Utility;
import java.io.BufferedWriter;
Expand Down Expand Up @@ -138,6 +141,12 @@ public class Config {
*/
public final boolean inferenceActivated;

/**
* This adapter is initialized lazily as it requires build of target to serialize its using
* NullAway serialization version.
*/
private NullAwayVersionAdapter adapter;

/**
* Builds config from command line arguments.
*
Expand Down Expand Up @@ -483,6 +492,49 @@ public Config(Path configPath) {
log.reset();
}

/** Initializes NullAway serialization adapter according to the serialized version. */
public void initializeAdapter() {
if (adapter != null) {
// adapter is already initialized.
return;
}
Path serializationVersionPath = target.dir.resolve("serialization_version.txt");
if (!serializationVersionPath.toFile().exists()) {
// Older versions of NullAway.
this.adapter = new NullAwayV0Adapter(this);
return;
}
try {
List<String> lines = Files.readAllLines(serializationVersionPath);
int version = Integer.parseInt(lines.get(0));
switch (version) {
case 0:
this.adapter = new NullAwayV0Adapter(this);
break;
case 1:
this.adapter = new NullAwayV1Adapter(this);
break;
default:
throw new RuntimeException("Unrecognized NullAway serialization version: " + version);
}
} catch (IOException e) {
throw new RuntimeException(
"Could not read serialization version at path: " + serializationVersionPath, e);
}
}

/**
* Getter for adapter.
*
* @return adapter.
*/
public NullAwayVersionAdapter getAdapter() {
if (adapter == null) {
throw new IllegalStateException("Adapter is not initialized.");
}
return adapter;
}

/**
* Returns the latest id associated to a module, used to create unique ids for each module and
* increments it.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* MIT License
*
* Copyright (c) 2022 Nima Karimipour
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package edu.ucr.cs.riple.core.adapters;

import com.google.common.base.Preconditions;
import edu.ucr.cs.riple.core.Config;
import edu.ucr.cs.riple.core.metadata.index.Error;
import edu.ucr.cs.riple.core.metadata.index.Fix;
import edu.ucr.cs.riple.core.metadata.trackers.Region;
import edu.ucr.cs.riple.core.metadata.trackers.TrackerNode;
import edu.ucr.cs.riple.injector.changes.AddMarkerAnnotation;
import edu.ucr.cs.riple.injector.location.Location;
import edu.ucr.cs.riple.injector.location.OnField;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;

/**
* Adapter working with versions below:
*
* <ul>
* <li>NullAway: Serialization version 0
* <li>Type Annotator Scanner: 1.3.3 or below
* </ul>
*/
public class NullAwayV0Adapter implements NullAwayVersionAdapter {

/** Annotator config. */
private final Config config;

public NullAwayV0Adapter(Config config) {
this.config = config;
}

@Override
public Fix deserializeFix(Location location, String[] values) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be a good idea to have an initial precondition here (and in all similar methods taking String[] values) checking for the number of elements in values? Presumably different serialization formats will have different number of fields?

Copy link
Member Author

@nimakarimipour nimakarimipour Nov 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, sounds good. 94d4efe

Preconditions.checkArgument(
values.length == 10,
"Expected 10 values to create Fix instance in NullAway serialization version 0 but found: "
+ values.length);
Preconditions.checkArgument(
values[7].equals("nullable"), "unsupported annotation: " + values[7]);
String encMember = !Region.getType(values[9]).equals(Region.Type.METHOD) ? "null" : values[9];
return new Fix(
new AddMarkerAnnotation(location, config.nullableAnnot),
values[6],
new Region(values[8], encMember),
true);
}

@Override
public Error deserializeError(String[] values) {
Preconditions.checkArgument(
values.length == 10,
"Expected 10 values to create Error instance in NullAway serialization version 0 but found: "
+ values.length);
String encMember = !Region.getType(values[3]).equals(Region.Type.METHOD) ? "null" : values[3];
return new Error(
values[0],
values[1],
new Region(values[2], encMember),
Location.createLocationFromArrayInfo(Arrays.copyOfRange(values, 4, 10)));
}

@Override
public TrackerNode deserializeTrackerNode(String[] values) {
Preconditions.checkArgument(
values.length == 4,
"Expected 4 values to create TrackerNode instance in NullAway serialization version 0 but found: "
+ values.length);
String encMember = !Region.getType(values[1]).equals(Region.Type.METHOD) ? "null" : values[1];
return new TrackerNode(values[0], encMember, values[2], values[3]);
}

@Override
public Set<Region> getFieldRegionScope(OnField onField) {
return Collections.singleton(new Region(onField.clazz, "null"));
}
}
Loading