Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 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: 'adopt'
Copy link
Member

Choose a reason for hiding this comment

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

Nit: 'adopt' is out of date, use 'temurin'

Copy link
Member Author

@nimakarimipour nimakarimipour Nov 18, 2022

Choose a reason for hiding this comment

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

- name: Build with Gradle
run: ./gradlew :core:test --scan --no-daemon -Pnullaway-test-version=0
Copy link
Member

Choose a reason for hiding this comment

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

Probably don't need --no-daemon here?

Copy link
Member Author

@nimakarimipour nimakarimipour Nov 18, 2022

Choose a reason for hiding this comment

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

Yes, that doesn't seem necessary. 08d9e2c

18 changes: 17 additions & 1 deletion core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,15 @@ dependencies {
testImplementation deps.build.commonsio
}

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

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 All @@ -74,3 +77,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-test-version")){
return
}
NULLAWAY_TEST = nullawayVersionMap.get((project.getProperty("nullaway-test-version")) as int)
println "NullAway Test version changed to: " + NULLAWAY_TEST

// exclude unsupported tests below...
}
tasks.test.dependsOn("configureNullAwayVersion")
25 changes: 10 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 @@ -48,7 +48,6 @@
import edu.ucr.cs.riple.injector.changes.AddMarkerAnnotation;
import edu.ucr.cs.riple.injector.changes.AddSingleElementAnnotation;
import edu.ucr.cs.riple.injector.location.OnField;
import edu.ucr.cs.riple.scanner.Serializer;
import java.util.List;
import java.util.Objects;
import java.util.Set;
Expand Down Expand Up @@ -104,8 +103,7 @@ private void preprocess() {
.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 @@ -119,9 +117,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 @@ -213,9 +211,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 @@ -246,7 +243,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 @@ -257,9 +254,9 @@ private void forceResolveRemainingErrors(
Set<AddAnnotation> nullUnMarkedAnnotations =
remainingErrors.stream()
// filter non-method regions.
.filter(error -> !error.encMethod().equals("null"))
.filter(error -> error.getRegion().isOnMethod())
// find the corresponding method nodes.
.map(error -> tree.findNode(error.encMethod(), error.encClass()))
.map(error -> tree.findNode(error.encMember(), error.encClass()))
// impossible, just sanity check or future nullness checker hints
.filter(Objects::nonNull)
.map(node -> new AddMarkerAnnotation(node.location, config.nullUnMarkedAnnotation))
Expand All @@ -275,7 +272,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 @@ -296,8 +293,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);
}
Expand Down
37 changes: 37 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.Adapter;
import edu.ucr.cs.riple.core.adapters.NullAwayAdapterVersion0;
import edu.ucr.cs.riple.core.adapters.NullAwayAdapterVersion1;
import edu.ucr.cs.riple.core.log.Log;
import edu.ucr.cs.riple.core.util.Utility;
import java.io.BufferedWriter;
Expand Down Expand Up @@ -131,6 +134,8 @@ public class Config {
public final Log log;
public final int depth;

public final Adapter adapter;

/**
* Builds config from command line arguments.
*
Expand Down Expand Up @@ -385,6 +390,8 @@ public Config(String[] args) {
this.moduleCounterID = 0;
this.log = new Log();
this.log.reset();
this.adapter = initializeAdapter(globalDir);
;
}

/**
Expand Down Expand Up @@ -463,9 +470,39 @@ public Config(Path configPath) {
getValueFromKey(jsonObject, "ANNOTATION:NULL_UNMARKED", String.class)
.orElse("org.jspecify.nullness.NullUnmarked");
this.log = new Log();
this.adapter = initializeAdapter(globalDir);
log.reset();
}

/**
* Initializes NullAway serialization adapter according to the serialized version.
*
* @param globalDir Root path where the serialized version can be located.
* @return The corresponding adapter.
*/
private Adapter initializeAdapter(Path globalDir) {
Path serializationVersionPath = globalDir.resolve("serialization_version.txt");
if (!serializationVersionPath.toFile().exists()) {
// Older versions of NullAway.
return new NullAwayAdapterVersion0(this);
}
try {
List<String> lines = Files.readAllLines(serializationVersionPath);
int version = Integer.parseInt(lines.get(0));
switch (version) {
case 0:
return new NullAwayAdapterVersion0(this);
case 1:
return new NullAwayAdapterVersion1(this);
default:
throw new RuntimeException("Unrecognized NullAway serialization version: " + version);
}
} catch (IOException e) {
throw new RuntimeException(
"Could not read serialization version at path: " + serializationVersionPath, e);
}
}

/**
* Returns the latest id associated to a module, used to create unique ids for each module and
* increments it.
Expand Down
77 changes: 77 additions & 0 deletions core/src/main/java/edu/ucr/cs/riple/core/adapters/Adapter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* 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 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.location.Location;
import edu.ucr.cs.riple.injector.location.OnField;
import java.util.Set;

/**
* Responsible for performing tasks related to NullAway / Type Annotator Scanner serialization
* features.
*/
public interface Adapter {
Copy link
Member

Choose a reason for hiding this comment

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

Let's be more verbose here and call this NullAwayVersionAdapter

Copy link
Member Author

@nimakarimipour nimakarimipour Nov 18, 2022

Choose a reason for hiding this comment

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


/**
* Deserializes values produced by NullAway in a tsv file and creates a corresponding {@link Fix}
* instance.
*
* @param location Location of the targeted element.
* @param values Values in row of a TSV file.
* @return Corresponding Error instance with the passed values.
*/
Fix deserializeFix(Location location, String[] values);

/**
* Deserializes values produced by NullAway in a tsv file and creates a corresponding {@link
* Error} instance.
*
* @param values Values in row of a TSV file.
* @return Corresponding Error instance with the passed values.
*/
Error deserializeError(String[] values);

/**
* Deserializes values produced by Type Annotator Scanner in a tsv file and creates a
* corresponding {@link TrackerNode} instance.
*
* @param values Values in row of a TSV file.
* @return Corresponding Error instance with the passed values.
*/
TrackerNode deserializeTrackerNode(String[] values);

/**
* Returns a set of regions enclosed by a field. Returns a set since there can multiple inline
* field declarations.
*
* @param onField The target field.
* @return Set of regions enclosed by the passed location.
*/
Set<Region> getFieldRegionScope(OnField onField);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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 edu.ucr.cs.riple.core.Config;

/** Base class for all adapters. */
public abstract class AdapterAbstractClass implements Adapter {
Copy link
Member

Choose a reason for hiding this comment

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

I don't think it's worth creating this abstract class just to hold a single protected field. I would get rid of it.

Copy link
Member Author

@nimakarimipour nimakarimipour Nov 18, 2022

Choose a reason for hiding this comment

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

Deleted in: b51475a


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

public AdapterAbstractClass(Config config) {
this.config = config;
}
}
Loading