├── .github
└── workflows
│ └── maven.yml
├── .gitignore
├── .travis-settings.xml
├── .travis.yml
├── CITATION.cff
├── README.md
├── count.py
├── pom.xml
├── src
├── evaluation
│ └── java
│ │ └── fr
│ │ └── inria
│ │ └── spirals
│ │ └── npefix
│ │ ├── AbstractEvaluation.java
│ │ ├── SafeMonoEvaluation.java
│ │ ├── main
│ │ └── MainEvaluation.java
│ │ └── resi
│ │ ├── AbstractNPEDataset.java
│ │ ├── BenchmarkPaper.java
│ │ ├── NPEDataset.java
│ │ ├── NPEFixTemplateEvaluation.java
│ │ ├── PaperProjects.java
│ │ └── selector
│ │ ├── AbstractSelectorEvaluation.java
│ │ ├── DomSelectorEvaluation.java
│ │ ├── ExplorationSelectorEvaluation.java
│ │ ├── GreedySelectorEvaluation.java
│ │ ├── MonoExplorationEvaluation.java
│ │ └── RandomSelectorEvaluation.java
├── main
│ ├── java
│ │ ├── fr
│ │ │ └── inria
│ │ │ │ └── spirals
│ │ │ │ └── npefix
│ │ │ │ ├── config
│ │ │ │ └── Config.java
│ │ │ │ ├── main
│ │ │ │ ├── DecisionServer.java
│ │ │ │ ├── ExecutionClient.java
│ │ │ │ ├── all
│ │ │ │ │ ├── DefaultRepairStrategy.java
│ │ │ │ │ ├── Launcher.java
│ │ │ │ │ ├── RepairStrategy.java
│ │ │ │ │ └── TryCatchRepairStrategy.java
│ │ │ │ ├── patch
│ │ │ │ │ └── SortPatch.java
│ │ │ │ ├── run
│ │ │ │ │ └── Main.java
│ │ │ │ └── spoon
│ │ │ │ │ └── MainSpoon.java
│ │ │ │ ├── patch
│ │ │ │ ├── DecisionElement.java
│ │ │ │ ├── PositionScanner.java
│ │ │ │ ├── generator
│ │ │ │ │ ├── PatchGenerator.java
│ │ │ │ │ ├── PatchesGenerator.java
│ │ │ │ │ └── Writer.java
│ │ │ │ └── sorter
│ │ │ │ │ ├── Experiment.java
│ │ │ │ │ ├── FileTokensCreator.java
│ │ │ │ │ ├── SingleFileTokenIterator.java
│ │ │ │ │ ├── StringTokenIterator.java
│ │ │ │ │ ├── StringTokensCreator.java
│ │ │ │ │ ├── Token.java
│ │ │ │ │ ├── TokenImpl.java
│ │ │ │ │ ├── Tokens.java
│ │ │ │ │ ├── algorithm
│ │ │ │ │ ├── Algorithm.java
│ │ │ │ │ ├── KneserNey.java
│ │ │ │ │ ├── Laplace.java
│ │ │ │ │ └── NGram.java
│ │ │ │ │ └── tokenizer
│ │ │ │ │ ├── AbstractTokenizer.java
│ │ │ │ │ ├── BinaryTokenizer.java
│ │ │ │ │ ├── FullTokenizer.java
│ │ │ │ │ ├── RenameIdentifierLiteralTokenizer.java
│ │ │ │ │ ├── RenameIdentifierTokenizer.java
│ │ │ │ │ ├── RenameLiteralTokenizer.java
│ │ │ │ │ ├── RenameOperatorTokenizer.java
│ │ │ │ │ ├── RenameSyntaxKeywordTokenizer.java
│ │ │ │ │ ├── RenameSyntaxTokenizer.java
│ │ │ │ │ ├── TokenTypeTokenizer.java
│ │ │ │ │ └── Tokenizer.java
│ │ │ │ ├── patchTemplate
│ │ │ │ ├── InstanceCreator.java
│ │ │ │ ├── ThisFinder.java
│ │ │ │ ├── VariableFinder.java
│ │ │ │ └── template
│ │ │ │ │ ├── PatchTemplate.java
│ │ │ │ │ ├── ReplaceGlobal.java
│ │ │ │ │ ├── ReplaceLocal.java
│ │ │ │ │ ├── SkipLine.java
│ │ │ │ │ └── SkipMethodReturn.java
│ │ │ │ ├── resi
│ │ │ │ ├── CallChecker.java
│ │ │ │ ├── ExceptionStack.java
│ │ │ │ ├── RandomGenerator.java
│ │ │ │ ├── context
│ │ │ │ │ ├── ConstructorContext.java
│ │ │ │ │ ├── Decision.java
│ │ │ │ │ ├── Lapse.java
│ │ │ │ │ ├── Location.java
│ │ │ │ │ ├── MethodContext.java
│ │ │ │ │ ├── NPEOutput.java
│ │ │ │ │ ├── TryContext.java
│ │ │ │ │ └── instance
│ │ │ │ │ │ ├── AbstractInstance.java
│ │ │ │ │ │ ├── ArrayReadInstance.java
│ │ │ │ │ │ ├── Instance.java
│ │ │ │ │ │ ├── InstanceFactory.java
│ │ │ │ │ │ ├── NewArrayInstance.java
│ │ │ │ │ │ ├── NewInstance.java
│ │ │ │ │ │ ├── PrimitiveInstance.java
│ │ │ │ │ │ ├── StaticVariableInstance.java
│ │ │ │ │ │ └── VariableInstance.java
│ │ │ │ ├── exception
│ │ │ │ │ ├── AbnormalExecutionError.java
│ │ │ │ │ ├── ErrorInitClass.java
│ │ │ │ │ ├── ForceReturn.java
│ │ │ │ │ ├── NPEFixError.java
│ │ │ │ │ ├── NoMoreDecision.java
│ │ │ │ │ ├── ReturnNotSupported.java
│ │ │ │ │ └── VarNotFound.java
│ │ │ │ ├── oracle
│ │ │ │ │ ├── AbstractOracle.java
│ │ │ │ │ ├── ExceptionOracle.java
│ │ │ │ │ ├── Oracle.java
│ │ │ │ │ └── TestOracle.java
│ │ │ │ ├── selector
│ │ │ │ │ ├── AbstractSelector.java
│ │ │ │ │ ├── DomSelector.java
│ │ │ │ │ ├── ExplorerSelector.java
│ │ │ │ │ ├── GreedySelector.java
│ │ │ │ │ ├── MonoExplorerSelector.java
│ │ │ │ │ ├── NoMoreDecisionException.java
│ │ │ │ │ ├── RandomSelector.java
│ │ │ │ │ ├── RegressionSelector.java
│ │ │ │ │ ├── SafeMonoSelector.java
│ │ │ │ │ └── Selector.java
│ │ │ │ └── strategies
│ │ │ │ │ ├── AbstractStrategy.java
│ │ │ │ │ ├── ArrayReadFirst.java
│ │ │ │ │ ├── ArrayReadLast.java
│ │ │ │ │ ├── ArrayReadReturnNull.java
│ │ │ │ │ ├── NoStrat.java
│ │ │ │ │ ├── ReturnType.java
│ │ │ │ │ ├── Strat1.java
│ │ │ │ │ ├── Strat1A.java
│ │ │ │ │ ├── Strat1B.java
│ │ │ │ │ ├── Strat2.java
│ │ │ │ │ ├── Strat2A.java
│ │ │ │ │ ├── Strat2B.java
│ │ │ │ │ ├── Strat3.java
│ │ │ │ │ ├── Strat4.java
│ │ │ │ │ └── Strategy.java
│ │ │ │ └── transformer
│ │ │ │ ├── processors
│ │ │ │ ├── AddImplicitCastChecker.java
│ │ │ │ ├── ArrayRead.java
│ │ │ │ ├── BeforeDerefAdder.java
│ │ │ │ ├── BlockCoverage.java
│ │ │ │ ├── CheckNotNull.java
│ │ │ │ ├── ConstructorEncapsulation.java
│ │ │ │ ├── ConstructorTryCatchRepair.java
│ │ │ │ ├── ForceNullInit.java
│ │ │ │ ├── IfSplitter.java
│ │ │ │ ├── MethodEncapsulation.java
│ │ │ │ ├── NotNullTracer.java
│ │ │ │ ├── ProcessorUtility.java
│ │ │ │ ├── RemoveNPECheckProcessor.java
│ │ │ │ ├── RemoveNullCheckProcessor.java
│ │ │ │ ├── TargetModifier.java
│ │ │ │ ├── TernarySplitter.java
│ │ │ │ ├── TryCatchRepair.java
│ │ │ │ ├── TryRegister.java
│ │ │ │ ├── VarRetrieveAssign.java
│ │ │ │ ├── VarRetrieveInit.java
│ │ │ │ └── VariableFor.java
│ │ │ │ └── utils
│ │ │ │ ├── CtThrowGenerated.java
│ │ │ │ ├── CtTryGenerated.java
│ │ │ │ └── IConstants.java
│ │ └── utils
│ │ │ ├── TestClassesFinder.java
│ │ │ ├── org
│ │ │ └── eclipse
│ │ │ │ └── core
│ │ │ │ └── internal
│ │ │ │ └── localstore
│ │ │ │ ├── ILocalStoreConstants.java
│ │ │ │ └── SafeChunkyInputStream.java
│ │ │ └── sacha
│ │ │ ├── classloader
│ │ │ ├── enrich
│ │ │ │ └── EnrichableClassloader.java
│ │ │ └── factory
│ │ │ │ └── ClassloaderFactory.java
│ │ │ ├── finder
│ │ │ ├── classes
│ │ │ │ ├── ClassFinder.java
│ │ │ │ └── impl
│ │ │ │ │ ├── ClassloaderFinder.java
│ │ │ │ │ ├── ClasspathFinder.java
│ │ │ │ │ ├── ProjectFinder.java
│ │ │ │ │ └── SourceFolderFinder.java
│ │ │ ├── filters
│ │ │ │ ├── ClassFilter.java
│ │ │ │ ├── impl
│ │ │ │ │ ├── AcceptAllFilter.java
│ │ │ │ │ └── TestFilter.java
│ │ │ │ └── utils
│ │ │ │ │ └── TestType.java
│ │ │ ├── main
│ │ │ │ ├── Main.java
│ │ │ │ ├── TestClassFinder.java
│ │ │ │ ├── TestInClasspath.java
│ │ │ │ ├── TestInFolder.java
│ │ │ │ ├── TestInURLClassloader.java
│ │ │ │ └── TestMain.java
│ │ │ └── processor
│ │ │ │ └── Processor.java
│ │ │ ├── impl
│ │ │ ├── AbstractConfigurator.java
│ │ │ ├── DefaultSpooner.java
│ │ │ ├── GeneralToJavaCore.java
│ │ │ ├── TestFinderCore.java
│ │ │ ├── TestRunnerCore.java
│ │ │ └── TestSuiteCreatorCore.java
│ │ │ ├── interfaces
│ │ │ ├── IEclipseConfigurable.java
│ │ │ ├── IGeneralToJava.java
│ │ │ ├── IRunner.java
│ │ │ ├── ISpooner.java
│ │ │ └── ITestResult.java
│ │ │ ├── mains
│ │ │ ├── CheckLoopMain.java
│ │ │ ├── EclipseGeneralToJavaProject.java
│ │ │ ├── MergeMavenProjects.java
│ │ │ ├── RepairLoop1.java
│ │ │ ├── RunSpoonWithClasspath.java
│ │ │ ├── TestFinderMain.java
│ │ │ ├── TestRunnerMain.java
│ │ │ └── TestSuiteGeneratorMain.java
│ │ │ ├── project
│ │ │ └── utils
│ │ │ │ ├── IMavenMerger.java
│ │ │ │ └── MavenModulesMerger.java
│ │ │ ├── runner
│ │ │ ├── main
│ │ │ │ ├── TestRunner.java
│ │ │ │ └── TestRunnerMain.java
│ │ │ └── utils
│ │ │ │ └── TestInfo.java
│ │ │ └── utils
│ │ │ └── SachaDocumentationGenerator.java
│ └── resources
│ │ └── config.ini
└── test
│ ├── java
│ └── fr
│ │ └── inria
│ │ └── spirals
│ │ └── npefix
│ │ ├── main
│ │ └── all
│ │ │ ├── End2EndTest.java
│ │ │ └── LauncherTest.java
│ │ ├── patch
│ │ └── PatchesGeneratorTest.java
│ │ ├── patchTemplate
│ │ ├── ReplaceGlobalTest.java
│ │ ├── ReplaceLocalTest.java
│ │ ├── SkipLineTest.java
│ │ ├── SkipMethodReturnTest.java
│ │ ├── VariableFinderTest.java
│ │ └── testClasses
│ │ │ ├── ChildClassSamePackage.java
│ │ │ └── ParentClass.java
│ │ └── transformer
│ │ ├── TryCatchRepairModelTest.java
│ │ └── processors
│ │ ├── ArrayAccessTest.java
│ │ ├── BeforeDerefAdderTest.java
│ │ ├── CheckNotNullTest.java
│ │ ├── ConstructorEncapsulationTest.java
│ │ ├── ImplicitCastCheckerTest.java
│ │ ├── TargetModifierTest.java
│ │ └── TernarySplitterTest.java
│ └── resources
│ ├── bar
│ └── src
│ │ ├── main
│ │ └── java
│ │ │ └── Coneflower.java
│ │ └── test
│ │ └── java
│ │ └── ConeflowerTest.java
│ └── foo
│ └── src
│ ├── main
│ └── java
│ │ ├── Foo.java
│ │ ├── Foo2.java
│ │ ├── FooArrayAccess.java
│ │ ├── FooTernary.java
│ │ └── ImplicitCast.java
│ └── test
│ └── java
│ ├── FooArrayAccessTest.java
│ └── FooClassTest.java
└── targets
/.github/workflows/maven.yml:
--------------------------------------------------------------------------------
1 | name: CI with Maven
2 |
3 | on:
4 | push:
5 | branches: [ "master" ]
6 | pull_request:
7 | branches: [ "master" ]
8 |
9 | jobs:
10 | build:
11 |
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - uses: actions/checkout@v4
16 | - name: Set up Java
17 | uses: actions/setup-java@v4
18 | with:
19 | java-version: '17'
20 | distribution: 'temurin'
21 | cache: maven
22 | - name: Build with Maven
23 | run: mvn -B package --file pom.xml
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | output/
3 | gh-pages
4 | pom.xml.tag
5 | pom.xml.releaseBackup
6 | pom.xml.versionsBackup
7 | pom.xml.next
8 | release.properties
9 | dependency-reduced-pom.xml
10 | buildNumber.properties
11 | .mvn/timing.properties
12 |
13 | bin
14 | target
15 | *.iml
16 | .idea
17 |
--------------------------------------------------------------------------------
/.travis-settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | github
5 | ${env.GITHUB_PASSWORD}
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | sudo: false
3 | script:
4 | - mvn test && mvn jacoco:report coveralls:report --fail-never
5 | jdk:
6 | - openjdk8
7 | cache:
8 | directories:
9 | - "$HOME/.m2"
10 | after_success:
11 | - '[[ $TRAVIS_BRANCH == "master" ]] && [[ $TRAVIS_JDK_VERSION == "openjdk8" ]] &&
12 | { mvn deploy --settings .travis-settings.xml -DskipTests=true -B; };'
13 | env:
14 | global:
15 | secure: fWu7zFEdkwLNOiEHG+sT6jdPqAOYijQcKK/BtTOuDdPBWHQ4ppmKC309RVuljkCx5xXwo6tNa5cA4O7EC/+WvhhRGpyMOqc2v8wxwCy1aWuuZS0pVu7UE8o2Vfu8PKg5KdvhNvvRA8qNldhnqdgqmdvwficcTOpGcEXWyfNxaBFCw7WpZEvxyybkmGhZBn+EOERTS4B7Cp/9iIT9pXTlkazAMimLCcKGbuRnJ7mcD6LV12hanjWvqaECwfYYPeeDAXFejkdpRVKogYhBybc4tqTour5qee4YzeOclOlZgHLw4gCUhMPJ/zx/odTN7jrSesoqDdLz5FfCcxxR67CwL9Eyw3B2vNhM5Hur+JHPAv/x3rWLipwjZXEqoFsNgVut9Z5nMZeCIqxdcM94ZMHREn/jaQ8AG+XGaWMqmHTSPB23yf2x7cfXCZL42RLWD/rvV7xh7zNyrAYpx1S3t0RE/KV0lCfE0oCI6Jgvylcmmo360mV6x0hezuinP+8aFPFScUeUHcN/EsQOpOfZG5MPBkagIfq7SGWvhcGrlHVrAIkZctMwxZwi5p+8bZRIXXzHPhzQc34HPXvnSMEgMKlikCNmkZ6wwH+mguwYYD0ZGtcPHej1h0sZMas4PrtknXlwtnm+J7te/zFdH78aG1YyGLfI3wZPZ1J3RKFh4aFXMek=
16 |
--------------------------------------------------------------------------------
/CITATION.cff:
--------------------------------------------------------------------------------
1 | cff-version: 1.2.0
2 | preferred-citation:
3 | title: "Dynamic Patch Generation for Null Pointer Exceptions Using Metaprogramming"
4 | doi: "10.1109/SANER.2017.7884635"
5 | year: "2017"
6 | type: conference-paper
7 | conference: "IEEE International Conference on Software Analysis, Evolution and Reengineering"
8 | authors:
9 | - family-names: Durieux
10 | given-names: Thomas
11 | - family-names: Cornu
12 | given-names: Benoit
13 | - family-names: Seinturier
14 | given-names: Lionel
15 | - family-names: Monperrus
16 | given-names: Martin
17 |
--------------------------------------------------------------------------------
/count.py:
--------------------------------------------------------------------------------
1 | import csv
2 |
3 | counterPerLocation = {}
4 |
5 | total = 0
6 |
7 | with open('instrumentation-output.csv', 'rb') as csvfile:
8 | mutations_csv = csv.reader(csvfile, delimiter='\t', quotechar='|')
9 | for row in mutations_csv:
10 | location = row[0] + ':' + row[2]
11 | if not location in counterPerLocation:
12 | counterPerLocation[location] = [0,0]
13 | if row[1] == 'false':
14 | counterPerLocation[location][1] += 1
15 | else:
16 | counterPerLocation[location][0] += 1
17 | total += 1
18 |
19 | print total, " total number of executions"
20 |
21 | listNotDiverse=[]
22 | listDiverse=[]
23 |
24 | for record in counterPerLocation:
25 | if counterPerLocation[record][0] == 0 or \
26 | counterPerLocation[record][1] == 0:
27 | listNotDiverse.append(record)
28 | else:
29 | listDiverse.append(record)
30 |
31 | print len(listDiverse), " number of location that have both values"
32 | acc = 0
33 | for record in listDiverse:
34 | print str(counterPerLocation[record][0] + counterPerLocation[record][1]), record, str(counterPerLocation[record])
35 | acc += counterPerLocation[record][0] + counterPerLocation[record][1]
36 | print acc, " total number of execution with both values"
37 |
38 | print "=" * 30
39 |
40 | print len(listNotDiverse), " number of location with single value"
41 | acc = 0
42 | for record in listNotDiverse:
43 | print str(counterPerLocation[record][0] + counterPerLocation[record][1]), record, str(counterPerLocation[record])
44 | acc += counterPerLocation[record][0] + counterPerLocation[record][1]
45 | print acc, " total number of execution with single value"
46 |
47 |
--------------------------------------------------------------------------------
/src/evaluation/java/fr/inria/spirals/npefix/SafeMonoEvaluation.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.resi.selector;
2 |
3 | import org.junit.Before;
4 |
5 | import fr.inria.spirals.npefix.config.Config;
6 | import fr.inria.spirals.npefix.resi.CallChecker;
7 | import fr.inria.spirals.npefix.resi.RandomGenerator;
8 |
9 | // safe mode for NpeFix, see https://github.com/Spirals-Team/npefix/issues/10
10 | public class SafeMonoEvaluation extends AbstractSelectorEvaluation {
11 |
12 | @Before
13 | public void setup() {
14 | RandomGenerator.reset();
15 | CallChecker.clear();
16 | Config.CONFIG.setMultiPoints(false);
17 | setSelector(new SafeMonoSelector());
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/evaluation/java/fr/inria/spirals/npefix/resi/selector/DomSelectorEvaluation.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.resi.selector;
2 |
3 | import fr.inria.spirals.npefix.resi.CallChecker;
4 | import fr.inria.spirals.npefix.resi.RandomGenerator;
5 | import fr.inria.spirals.npefix.resi.strategies.ReturnType;
6 | import fr.inria.spirals.npefix.resi.strategies.Strat4;
7 | import org.junit.Before;
8 |
9 | public class DomSelectorEvaluation extends AbstractSelectorEvaluation {
10 |
11 | @Before
12 | public void setup() {
13 | RandomGenerator.reset();
14 | CallChecker.clear();
15 | setSelector(new DomSelector());
16 | DomSelector.strategy = new Strat4(ReturnType.VAR);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/evaluation/java/fr/inria/spirals/npefix/resi/selector/ExplorationSelectorEvaluation.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.resi.selector;
2 |
3 | import fr.inria.spirals.npefix.resi.CallChecker;
4 | import fr.inria.spirals.npefix.resi.RandomGenerator;
5 | import org.junit.Before;
6 |
7 | public class ExplorationSelectorEvaluation extends AbstractSelectorEvaluation {
8 |
9 | @Before
10 | public void setup() {
11 | RandomGenerator.reset();
12 | CallChecker.clear();
13 | setSelector(new ExplorerSelector());
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/evaluation/java/fr/inria/spirals/npefix/resi/selector/GreedySelectorEvaluation.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.resi.selector;
2 |
3 | import fr.inria.spirals.npefix.resi.CallChecker;
4 | import fr.inria.spirals.npefix.resi.RandomGenerator;
5 | import org.junit.Before;
6 |
7 | /**
8 | * Created by thomas on 13/10/15.
9 | */
10 | public class GreedySelectorEvaluation extends AbstractSelectorEvaluation {
11 |
12 | @Before
13 | public void setup() {
14 | RandomGenerator.reset();
15 | CallChecker.clear();
16 | setSelector(new GreedySelector());
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/evaluation/java/fr/inria/spirals/npefix/resi/selector/MonoExplorationEvaluation.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.resi.selector;
2 |
3 | import fr.inria.spirals.npefix.config.Config;
4 | import fr.inria.spirals.npefix.resi.CallChecker;
5 | import fr.inria.spirals.npefix.resi.RandomGenerator;
6 | import org.junit.Before;
7 |
8 | public class MonoExplorationEvaluation extends AbstractSelectorEvaluation {
9 |
10 | @Before
11 | public void setup() {
12 | RandomGenerator.reset();
13 | CallChecker.clear();
14 | Config.CONFIG.setMultiPoints(false);
15 | setSelector(new MonoExplorerSelector());
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/evaluation/java/fr/inria/spirals/npefix/resi/selector/RandomSelectorEvaluation.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.resi.selector;
2 |
3 | import fr.inria.spirals.npefix.resi.CallChecker;
4 | import fr.inria.spirals.npefix.resi.RandomGenerator;
5 | import org.junit.Before;
6 |
7 | /**
8 | * Created by thomas on 13/10/15.
9 | */
10 | public class RandomSelectorEvaluation extends AbstractSelectorEvaluation {
11 |
12 | @Before
13 | public void setup() {
14 | RandomGenerator.reset();
15 | CallChecker.clear();
16 | setSelector(new RandomSelector());
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/main/DecisionServer.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.main;
2 |
3 | import fr.inria.spirals.npefix.config.Config;
4 | import fr.inria.spirals.npefix.resi.selector.ExplorerSelector;
5 | import fr.inria.spirals.npefix.resi.selector.Selector;
6 | import fr.inria.spirals.npefix.resi.strategies.ReturnType;
7 | import fr.inria.spirals.npefix.resi.strategies.Strat4;
8 |
9 | import java.rmi.RemoteException;
10 | import java.rmi.registry.LocateRegistry;
11 | import java.rmi.registry.Registry;
12 | import java.rmi.server.UnicastRemoteObject;
13 |
14 | public class DecisionServer {
15 |
16 | private Thread thread;
17 |
18 | public static void main(String[] args) {
19 | try {
20 |
21 | Selector selector = new ExplorerSelector(new Strat4(ReturnType.NULL), new Strat4(ReturnType.VAR), new Strat4(ReturnType.NEW), new Strat4(ReturnType.VOID));
22 | System.out.println("Start selector " + selector);
23 |
24 | startRMI(selector);
25 | } catch (Exception e) {
26 | e.printStackTrace();
27 | }
28 | }
29 |
30 | private static Registry startRMI(Selector selector) {
31 | Registry registry;
32 |
33 | int port = Config.CONFIG.getServerPort();
34 | String host = Config.CONFIG.getServerHost();
35 |
36 | Selector skeleton;
37 | try {
38 | skeleton = (Selector) UnicastRemoteObject.exportObject(selector, port);
39 | } catch (RemoteException e) {
40 | throw new RuntimeException(e);
41 | }
42 | try{
43 | LocateRegistry.getRegistry(host, port).list();
44 | registry = LocateRegistry.getRegistry(host, port);
45 | }catch(Exception ex){
46 | try{
47 | registry = LocateRegistry.createRegistry(port);
48 | } catch(Exception e){
49 | throw new RuntimeException(e);
50 | }
51 | }
52 | try {
53 | registry.rebind(Config.CONFIG.getServerName(), skeleton);
54 | } catch (RemoteException e) {
55 | throw new RuntimeException(e);
56 | }
57 | return registry;
58 | }
59 |
60 | private Selector selector;
61 | private int port = Config.CONFIG.getServerPort();
62 | private String host = Config.CONFIG.getServerHost();
63 |
64 | public DecisionServer(Selector selector) {
65 | this.selector = selector;
66 | }
67 |
68 | public void startServer() {
69 | this.thread = new Thread(new Runnable() {
70 | Registry registry;
71 |
72 | @Override
73 | public void run() {
74 | startRMI(selector);
75 | }
76 |
77 |
78 | });
79 | thread.run();
80 | }
81 |
82 | public void stopServer() {
83 | thread.interrupt();
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/main/ExecutionClient.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.main;
2 |
3 | import fr.inria.spirals.npefix.config.Config;
4 | import fr.inria.spirals.npefix.resi.CallChecker;
5 | import fr.inria.spirals.npefix.resi.context.Lapse;
6 | import fr.inria.spirals.npefix.resi.oracle.ExceptionOracle;
7 | import fr.inria.spirals.npefix.resi.oracle.TestOracle;
8 | import fr.inria.spirals.npefix.resi.selector.Selector;
9 | import org.junit.runner.Request;
10 | import org.junit.runner.Result;
11 | import utils.sacha.runner.main.TestRunner;
12 |
13 | import java.rmi.RemoteException;
14 | import java.rmi.registry.LocateRegistry;
15 | import java.rmi.registry.Registry;
16 | import java.util.concurrent.Callable;
17 | import java.util.concurrent.ExecutionException;
18 | import java.util.concurrent.ExecutorService;
19 | import java.util.concurrent.Executors;
20 | import java.util.concurrent.Future;
21 | import java.util.concurrent.TimeUnit;
22 | import java.util.concurrent.TimeoutException;
23 |
24 | public class ExecutionClient {
25 |
26 | public static void main(String[] args) {
27 | ExecutionClient executionClient = new ExecutionClient(args[0], args[1], new String[0]);
28 | Config.CONFIG.setRandomSeed(Integer.parseInt(args[2]));
29 | executionClient.run();
30 | }
31 |
32 | private String classTestName;
33 | private String testName;
34 | private int port = Config.CONFIG.getServerPort();
35 | private String host = Config.CONFIG.getServerHost();
36 | private String[] inputSources;
37 |
38 | public ExecutionClient(String classTestName, String testName, String[] inputSources) {
39 | this.classTestName = classTestName;
40 | this.testName = testName;
41 | this.inputSources = inputSources;
42 | }
43 |
44 | /**
45 | * Get the selector instantiated in the RMI server.
46 | * @return
47 | */
48 | private Selector getSelector() {
49 | try {
50 | Registry registry = LocateRegistry.getRegistry(host, port);
51 | return (Selector) registry.lookup("Selector");
52 | } catch (Exception e) {
53 | // if the decision server is not available exit the execution
54 | throw new RuntimeException(e);
55 | }
56 | }
57 |
58 | private void run() {
59 | Selector selector = getSelector();
60 | Lapse lapse = new Lapse(selector, inputSources);
61 | lapse.setTestClassName(classTestName);
62 | lapse.setTestName(testName);
63 |
64 | try {
65 | if(!selector.startLaps(lapse)) {
66 | return;
67 | }
68 | } catch (RemoteException e) {
69 | throw new RuntimeException(e);
70 | }
71 | //CallChecker.strategySelector = selector;
72 | CallChecker.currentClassLoader = getClass().getClassLoader();
73 | final TestRunner testRunner = new TestRunner();
74 | try {
75 | Class> testClass = getClass().forName(classTestName);
76 | final Request request = Request.method(testClass, testName);
77 |
78 | ExecutorService executor = Executors.newSingleThreadExecutor();
79 |
80 | final Future handler = executor.submit(new Callable() {
81 | @Override
82 | public Result call() throws Exception {
83 | return testRunner.run(request);
84 | }
85 | });
86 |
87 | try {
88 | executor.shutdownNow();
89 | Result result = handler.get(25, TimeUnit.SECONDS);
90 | lapse = getSelector().getCurrentLapse();
91 | lapse.setOracle(new TestOracle(result));
92 | } catch (TimeoutException e) {
93 | lapse = getSelector().getCurrentLapse();
94 | lapse.setOracle(new ExceptionOracle(e));
95 | e.printStackTrace();
96 | handler.cancel(true);
97 | } catch (ExecutionException e) {
98 | lapse = getSelector().getCurrentLapse();
99 | lapse.setOracle(new ExceptionOracle(e));
100 | e.printStackTrace();
101 | handler.cancel(true);
102 | }
103 |
104 |
105 | selector.restartTest(lapse);
106 | System.out.println(lapse);
107 | System.exit(0);
108 | } catch (Exception e) {
109 | throw new RuntimeException(e);
110 | }
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/main/all/RepairStrategy.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.main.all;
2 |
3 | import fr.inria.spirals.npefix.resi.context.NPEOutput;
4 | import fr.inria.spirals.npefix.resi.selector.Selector;
5 | import spoon.processing.AbstractProcessor;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | * Created by Benjamin DANGLOT
11 | * benjamin.danglot@inria.fr
12 | * on 11/07/17
13 | */
14 | public interface RepairStrategy {
15 |
16 | List getListOfProcessors();
17 |
18 | NPEOutput run(Selector selector, List methodTests);
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/main/all/TryCatchRepairStrategy.java:
--------------------------------------------------------------------------------
1 |
2 | package fr.inria.spirals.npefix.main.all;
3 |
4 | import fr.inria.spirals.npefix.resi.context.NPEOutput;
5 | import fr.inria.spirals.npefix.resi.selector.Selector;
6 | import fr.inria.spirals.npefix.transformer.processors.AddImplicitCastChecker;
7 | import fr.inria.spirals.npefix.transformer.processors.CheckNotNull;
8 | import fr.inria.spirals.npefix.transformer.processors.ConstructorTryCatchRepair;
9 | import fr.inria.spirals.npefix.transformer.processors.ForceNullInit;
10 | import fr.inria.spirals.npefix.transformer.processors.TryCatchRepair;
11 | import fr.inria.spirals.npefix.transformer.processors.VarRetrieveAssign;
12 | import fr.inria.spirals.npefix.transformer.processors.VarRetrieveInit;
13 | import fr.inria.spirals.npefix.transformer.processors.VariableFor;
14 |
15 | import java.util.ArrayList;
16 | import java.util.List;
17 |
18 | /**
19 | * Created by Benjamin DANGLOT
20 | * benjamin.danglot@inria.fr
21 | * on 11/07/17
22 | */
23 | @SuppressWarnings("all")
24 | public class TryCatchRepairStrategy extends DefaultRepairStrategy {
25 | private static Selector selector;
26 |
27 | public TryCatchRepairStrategy(String[] inputSources) {
28 | super(inputSources);
29 | processors = new ArrayList<>();
30 | processors.add(new CheckNotNull());//
31 | processors.add(new ForceNullInit());//
32 | processors.add(new AddImplicitCastChecker());//
33 | processors.add(new VarRetrieveAssign());//
34 | processors.add(new VarRetrieveInit());//
35 | processors.add(new TryCatchRepair());
36 | processors.add(new ConstructorTryCatchRepair());
37 | processors.add(new VariableFor());//
38 | }
39 |
40 | public NPEOutput run(Selector selector, List methodTests) {
41 | TryCatchRepairStrategy.selector = selector;
42 | return super.run(selector, methodTests);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/main/spoon/MainSpoon.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.main.spoon;
2 |
3 | import fr.inria.spirals.npefix.transformer.processors.BeforeDerefAdder;
4 | import fr.inria.spirals.npefix.transformer.processors.ForceNullInit;
5 | import fr.inria.spirals.npefix.transformer.processors.IfSplitter;
6 | import fr.inria.spirals.npefix.transformer.processors.MethodEncapsulation;
7 | import fr.inria.spirals.npefix.transformer.processors.TargetModifier;
8 | import fr.inria.spirals.npefix.transformer.processors.TryRegister;
9 | import fr.inria.spirals.npefix.transformer.processors.VarRetrieveAssign;
10 | import fr.inria.spirals.npefix.transformer.processors.VarRetrieveInit;
11 | import fr.inria.spirals.npefix.transformer.processors.VariableFor;
12 | import utils.sacha.impl.DefaultSpooner;
13 | import utils.sacha.interfaces.ISpooner;
14 |
15 | import javax.swing.*;
16 | import java.io.BufferedReader;
17 | import java.io.File;
18 | import java.io.FileInputStream;
19 | import java.io.InputStreamReader;
20 | import java.util.ArrayList;
21 | import java.util.Collections;
22 | import java.util.HashMap;
23 | import java.util.List;
24 | import java.util.Map;
25 |
26 |
27 | public class MainSpoon {
28 |
29 | public static void main(String[] args) {
30 | try{
31 | BufferedReader br = null;
32 | Object selection = null;
33 | String[] arg = null;
34 | try {
35 | File targetsFile = new File("targets");
36 | if(targetsFile.exists()){
37 | Map targets = new HashMap();
38 | List options = new ArrayList<>();
39 | br = new BufferedReader(new InputStreamReader(
40 | new FileInputStream(targetsFile)));
41 | String line;
42 | while ((line = br.readLine()) != null) {
43 | if(line.startsWith("#"))continue;
44 | String[] lineB = line.split(":",2);
45 | String[] arguments = lineB[1].split("\\s");
46 | targets.put(lineB[0],arguments);
47 | options.add(lineB[0]);
48 | }
49 | Collections.sort(options);
50 | Object[] selectionValues = options.toArray();
51 | selection = JOptionPane.showInputDialog(null, "Which project?", "spoon",
52 | JOptionPane.QUESTION_MESSAGE, null, selectionValues, "test");
53 | arg=targets.get(selection);
54 | }
55 | } finally {
56 | if(br!=null)
57 | br.close();
58 | }
59 | ISpooner spooner = new DefaultSpooner();
60 | //project config
61 | spooner.setEclipseProject(arg[0]);
62 | spooner.setEclipseMetadataFolder("/home/thomas/workspace/.metadata");
63 | String[] srcs = arg[1].split(":");
64 | //spoon config
65 | spooner.setSourceFolder(srcs);
66 | spooner.setProcessors(
67 | IfSplitter.class,
68 | ForceNullInit.class,
69 | BeforeDerefAdder.class,
70 | TargetModifier.class,
71 | TryRegister.class,
72 | MethodEncapsulation.class,
73 | VariableFor.class,
74 | VarRetrieveAssign.class,
75 | VarRetrieveInit.class
76 | );
77 | spooner.setOutputFolder(arg[2]);
78 | if(arg[0].equals("test"))
79 | spooner.setGraphicalOutput(true);
80 | cleanOutput(new File(arg[2]));
81 |
82 | spooner.spoon();
83 | System.err.println("spoon done");
84 | }catch(Throwable t){
85 | t.printStackTrace();
86 | }
87 | }
88 |
89 | private static void cleanOutput(File outputFolder) {
90 | if (outputFolder.exists()) {
91 | recursifDeleteJavaFiles(outputFolder);
92 | }
93 | }
94 |
95 | private static boolean recursifDeleteJavaFiles(File file) {
96 | boolean delete = true;
97 | if (file.exists()) {
98 | if (file.isDirectory())
99 | for (File child : file.listFiles()) {
100 | delete &= recursifDeleteJavaFiles(child);
101 | }
102 | if(!delete || (file.isFile() && !file.getName().endsWith(".java"))){
103 | return false;
104 | }
105 | file.delete();
106 | }
107 | return delete;
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/DecisionElement.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch;
2 |
3 | import fr.inria.spirals.npefix.resi.context.Decision;
4 | import spoon.reflect.declaration.CtElement;
5 |
6 | public class DecisionElement {
7 | private CtElement element;
8 | private Decision decision;
9 | private String classContent;
10 |
11 | public DecisionElement(CtElement element, Decision decision) {
12 | this.element = element;
13 | this.decision = decision;
14 | }
15 |
16 | public CtElement getElement() {
17 | return element;
18 | }
19 |
20 | public void setElement(CtElement element) {
21 | this.element = element;
22 | }
23 |
24 | public Decision getDecision() {
25 | return decision;
26 | }
27 |
28 | public void setDecision(Decision decision) {
29 | this.decision = decision;
30 | }
31 |
32 | public String getClassContent() {
33 | return classContent;
34 | }
35 |
36 | public void setClassContent(String classContent) {
37 | this.classContent = classContent;
38 | }
39 | }
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/PositionScanner.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch;
2 |
3 | import fr.inria.spirals.npefix.resi.context.Location;
4 | import spoon.reflect.cu.SourcePosition;
5 | import spoon.reflect.cu.position.NoSourcePosition;
6 | import spoon.reflect.declaration.CtElement;
7 | import spoon.reflect.visitor.CtScanner;
8 |
9 | public class PositionScanner extends CtScanner {
10 | private final Location location;
11 | private CtElement result;
12 |
13 | public PositionScanner(Location location) {
14 | this.location = location;
15 | }
16 |
17 | @Override
18 | public void scan(CtElement e) {
19 | if (e == null) {
20 | return;
21 | }
22 | SourcePosition position = e.getPosition();
23 | if (position instanceof NoSourcePosition) {
24 | if (e.isImplicit()) {
25 | super.scan(e);
26 | }
27 | return;
28 | }
29 | if (position.getLine() == location.getLine() &&
30 | position.getSourceEnd() == location.getSourceEnd() &&
31 | position.getSourceStart() == location.getSourceStart()) {
32 | result = e;
33 | throw new RuntimeException("Stop");
34 | } else if (position.getSourceEnd() >= location.getSourceEnd() &&
35 | position.getSourceStart() <= location.getSourceStart()) {
36 | super.scan(e);
37 | }
38 | }
39 |
40 | public CtElement getResult() {
41 | return result;
42 | }
43 | }
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/generator/Writer.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch.generator;
2 |
3 | import spoon.reflect.declaration.CtElement;
4 |
5 | public class Writer {
6 | private StringBuilder content = new StringBuilder();
7 | String currentIndentation = "";
8 | private final String indentation;
9 |
10 | Writer(String indentationInit, String indentation) {
11 | this.currentIndentation = indentationInit;
12 | this.indentation = indentation;
13 | this.write(indentationInit);
14 | }
15 |
16 | public Writer write(CtElement element) {
17 | this.content.append(element.toString());
18 | return this;
19 | }
20 |
21 | public Writer write(String content) {
22 | this.content.append(content);
23 | return this;
24 | }
25 |
26 | public Writer write(char content) {
27 | this.content.append(content);
28 | return this;
29 | }
30 |
31 | public Writer tab() {
32 | currentIndentation += indentation;
33 | return this.line();
34 | }
35 |
36 | public Writer line() {
37 | this.write("\n");
38 | return this.write(currentIndentation);
39 | }
40 |
41 | public Writer untab() {
42 | currentIndentation = currentIndentation.substring(0, currentIndentation.length() - indentation.length());
43 | return this.line();
44 | }
45 |
46 | public String addIndentationToString(String content) {
47 | Writer sb = new Writer(currentIndentation, indentation);
48 | String[] split = content.split("\n");
49 | for (int i = 0; i < split.length; i++) {
50 | String s = split[i].trim();
51 | String next = null;
52 | if (i < split.length - 1) {
53 | next = split[i + 1].trim();
54 | }
55 | sb.write(s);
56 | if (s.endsWith("{")) {
57 | sb.tab();
58 | } else if (next != null && next.startsWith("}")) {
59 | sb.untab();
60 | } else if (next != null) {
61 | sb.line();
62 | }
63 | }
64 | return sb.toString().trim();
65 | }
66 |
67 | @Override
68 | public String toString() {
69 | return content.toString();
70 | }
71 | }
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/sorter/Experiment.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch.sorter;
2 |
3 | import fr.inria.spirals.npefix.patch.sorter.algorithm.Laplace;
4 | import fr.inria.spirals.npefix.patch.sorter.tokenizer.Tokenizer;
5 |
6 | import java.io.File;
7 |
8 | public class Experiment {
9 |
10 | /**
11 | * collects all n-grams and returns them
12 | */
13 | public double probabilityPatch(
14 | int n,
15 | Tokens corpusTokens,
16 | String patch) {
17 | Tokenizer tokenizer = corpusTokens.getTokenizer();
18 | StringTokensCreator stringTokensCreator = new StringTokensCreator(patch, n, tokenizer);
19 | Tokens patchTokens = stringTokensCreator.getTokens();
20 | double[] probabilities = probability (patchTokens, corpusTokens, n);
21 | double probability = 1;
22 | for (int i = 0; i < probabilities.length; i++) {
23 | double p = probabilities[i];
24 | //System.out.println(String.format("%15s: %f", patchTokens.get(i), p));
25 | probability *= p;
26 | }
27 | if (probability == 0) {
28 | return Double.MAX_VALUE;
29 | }
30 | // perplexity.
31 | probability = Math.pow(probability, - 1 / (double) probabilities.length);
32 | return probability;
33 | }
34 |
35 | /**
36 | * collects all n-grams and returns them
37 | */
38 | public double probabilityPatch(File source,
39 | int n,
40 | Tokenizer tokenizer,
41 | String patch) {
42 | FileTokensCreator creator = new FileTokensCreator(source, n, tokenizer);
43 | Tokens corpusTokens = creator.getTokens();
44 | return probabilityPatch(n, corpusTokens, patch);
45 | }
46 |
47 | private double[] probability(Tokens patchTokens, final Tokens corpusTokens, int n) {
48 | double[] result = new double[patchTokens.fullSize()];
49 | for (int i = 0; i < patchTokens.fullSize(); i++) {
50 | Token token = patchTokens.get(i);
51 | Tokens predicate = patchTokens.subList(Math.max(i - n + 1, 0), Math.max(i, 0));
52 | if (predicate.isEmpty()) {
53 | result[i] = 1;
54 | } else {
55 | //result[i] = new NGram(token, predicate, corpusTokens).perform();
56 | //result[i] = new KneserNey(token, predicate, corpusTokens).perform();
57 | result[i] = new Laplace(token, predicate, corpusTokens).perform();
58 | }
59 | }
60 | return result;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/sorter/FileTokensCreator.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch.sorter;
2 |
3 | import fr.inria.spirals.npefix.patch.sorter.tokenizer.Tokenizer;
4 | import org.apache.commons.io.FileUtils;
5 |
6 | import java.io.File;
7 | import java.io.IOException;
8 | import java.util.Iterator;
9 |
10 | /**
11 | * recursively iterates over a directory and enumerates all probabilityPatch of size n
12 | */
13 | public class FileTokensCreator {
14 | Iterator files;
15 | SingleFileTokenIterator it;
16 | int n;
17 | Tokens tokens;
18 |
19 | public FileTokensCreator(File f, int n, Tokenizer tokenizer) {
20 | files = FileUtils.listFiles(f, new String[] { "java" }, true).iterator();
21 | tokens = new Tokens(tokenizer);
22 | this.n = n;
23 | nextFile();
24 | }
25 |
26 | private void nextFile() {
27 | try {
28 | it = createTokenIterator(files.next(), n);
29 | } catch (Exception e) {
30 | throw new RuntimeException(e);
31 | }
32 | }
33 |
34 | private SingleFileTokenIterator createTokenIterator(File f, int n) {
35 | try {
36 | return new SingleFileTokenIterator(f, n);
37 | } catch (IOException e) {
38 | throw new RuntimeException(e);
39 | }
40 | }
41 |
42 | private boolean hasNext() {
43 | while (!it.hasNext() && files.hasNext()) {
44 | nextFile();
45 | }
46 | return it.hasNext();
47 | }
48 |
49 | private Token next() {
50 | while (!it.hasNext() && files.hasNext()) {
51 | nextFile();
52 | }
53 | Token token = it.next();
54 | tokens.add(token);
55 | return token;
56 | }
57 |
58 | public Tokens getTokens() {
59 | while (hasNext()) {
60 | next();
61 | }
62 | return tokens;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/sorter/SingleFileTokenIterator.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch.sorter;
2 |
3 | import org.apache.commons.io.FileUtils;
4 |
5 | import java.io.File;
6 | import java.io.IOException;
7 |
8 | /**
9 | * iterates over the probabilityPatch of size n in a given file
10 | */
11 | public class SingleFileTokenIterator extends StringTokenIterator {
12 | public SingleFileTokenIterator(File f, int n) throws IOException {
13 | super(FileUtils.readFileToString(f), n);
14 | if (f.isDirectory()) {
15 | throw new RuntimeException("oops,should be a regular file");
16 | }
17 | }
18 |
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/sorter/StringTokensCreator.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch.sorter;
2 |
3 | import fr.inria.spirals.npefix.patch.sorter.tokenizer.Tokenizer;
4 |
5 | /**
6 | * recursively iterates over a directory and enumerates all probabilityPatch of size n
7 | */
8 | public class StringTokensCreator {
9 | StringTokenIterator it;
10 | int n;
11 | Tokens tokens;
12 |
13 | public StringTokensCreator(String f, int n, Tokenizer tokenizer) {
14 | this.n = n;
15 | it = new StringTokenIterator(f, n);
16 | tokens = new Tokens(tokenizer);
17 | }
18 |
19 | public Tokens getTokens() {
20 | while (it.hasNext()) {
21 | tokens.add(it.next());
22 | }
23 | return tokens;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/sorter/Token.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch.sorter;
2 |
3 | public interface Token {
4 | /**
5 | * the value of the token, e.g. "{"
6 | */
7 | String getValue();
8 |
9 | /**
10 | * the type the token, from JDT
11 | */
12 | int getType();
13 |
14 | /**
15 | * returns true if the token is a literal or an identifier (e.g. a class name
16 | */
17 | boolean isText();
18 |
19 | /**
20 | * returns true if the token is a literal
21 | */
22 | boolean isLiteral();
23 |
24 | boolean isSyntax();
25 |
26 | boolean isKeyword();
27 |
28 | boolean isOperator();
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/sorter/TokenImpl.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch.sorter;
2 |
3 | /**
4 | * encapsulates a JDT token
5 | */
6 | public class TokenImpl implements Token {
7 | final int type;
8 | final String value;
9 |
10 | public TokenImpl(int type, String value) {
11 | this.type = type;
12 | this.value = value;
13 | }
14 |
15 | @Override
16 | public String getValue() {
17 | return value;
18 | }
19 |
20 | @Override
21 | public int getType() {
22 | return type;
23 | }
24 |
25 | @Override
26 | public boolean isText() {
27 | return SingleFileTokenIterator.isText(type);
28 | }
29 |
30 | @Override
31 | public boolean isLiteral() {
32 | return SingleFileTokenIterator.isLiteral(type);
33 | }
34 |
35 | @Override
36 | public boolean isSyntax() {
37 | return SingleFileTokenIterator.isSyntax(type);
38 | }
39 |
40 | @Override
41 | public boolean isKeyword() {
42 | return SingleFileTokenIterator.isKeyword(type);
43 | }
44 |
45 | @Override
46 | public boolean isOperator() {
47 | return SingleFileTokenIterator.isOperator(type);
48 | }
49 |
50 | @Override
51 | public boolean equals(Object o) {
52 | if (this == o)
53 | return true;
54 | if (o == null || getClass() != o.getClass())
55 | return false;
56 |
57 | TokenImpl token = (TokenImpl) o;
58 |
59 | if (getType() != token.getType())
60 | return false;
61 | return getValue() != null ?
62 | getValue().equals(token.getValue()) :
63 | token.getValue() == null;
64 |
65 | }
66 |
67 | @Override
68 | public int hashCode() {
69 | int result = getType();
70 | result = 31 * result + (getValue() != null ? getValue().hashCode() : 0);
71 | return result;
72 | }
73 |
74 | @Override
75 | public String toString() {
76 | return value;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/sorter/algorithm/Algorithm.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch.sorter.algorithm;
2 |
3 | import fr.inria.spirals.npefix.patch.sorter.Token;
4 | import fr.inria.spirals.npefix.patch.sorter.Tokens;
5 |
6 | public abstract class Algorithm {
7 | private final Token token;
8 | private final Tokens predicate;
9 | private final Tokens corpus;
10 |
11 | public Algorithm(Token token, Tokens predicate, Tokens corpus) {
12 | this.token = token;
13 | this.predicate = predicate;
14 | this.corpus = corpus;
15 | }
16 |
17 | public Token getToken() {
18 | return token;
19 | }
20 |
21 | public Tokens getPredicate() {
22 | return predicate;
23 | }
24 |
25 | public Tokens getCorpus() {
26 | return corpus;
27 | }
28 |
29 | public abstract double perform();
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/sorter/algorithm/KneserNey.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch.sorter.algorithm;
2 |
3 | import fr.inria.spirals.npefix.patch.sorter.Token;
4 | import fr.inria.spirals.npefix.patch.sorter.Tokens;
5 |
6 | import java.util.Set;
7 |
8 | /**
9 | * The Kneser-Ney smoothing algorithm has a notion of continuation probability
10 | * which helps with these sorts of cases.
11 | * It also saves you from having to recalculate all your counts using Good-Turing smoothing.
12 | */
13 | public class KneserNey extends Algorithm {
14 | private final Set allBiGram;
15 | private double d = 0.1;
16 |
17 | public KneserNey(Token token, Tokens predicate, Tokens corpus) {
18 | super(token, predicate, corpus);
19 | this.allBiGram = getCorpus().getAllNGram(2);
20 | }
21 |
22 | public double perform() {
23 | return perform(getPredicate());
24 | }
25 |
26 | private double perform(Tokens predicate) {
27 | double countPrefix = getCorpus().count(predicate.get(predicate.fullSize() - 1));
28 | double count = getCorpus().count(getToken(), predicate);
29 | double countWordCanFollowPredicate = getCorpus().countWordCanFollow(predicate);
30 |
31 | // [ max( countkn( wi-n+1i ) - d, 0) ] / [ countkn( wi-n+1i-1 ) ]
32 | double probability = Math.max(count - d, 0) / countPrefix;
33 | // d * [ Num words that can follow wi-1 ] } / [ count( wi-1 )
34 | double normalisation = d * countWordCanFollowPredicate / countPrefix;
35 | double recursive;
36 | if (predicate.fullSize() == 1) {
37 | int countWordCanPrefixToken = getCorpus().countWordCanPrefix(getToken());
38 | int countBigram = allBiGram.size();
39 | // This is the number of bigrams where wi followed by wi-1,
40 | // divided by the total number of bigrams that appear with a frequency > 0.
41 | recursive = countWordCanPrefixToken / (double) countBigram;
42 | } else {
43 | // Pkn( wi | wi-n+2i-1 )
44 | recursive = perform(predicate.subList(1, predicate.fullSize()));
45 | }
46 | return probability + normalisation * recursive;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/sorter/algorithm/Laplace.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch.sorter.algorithm;
2 |
3 | import fr.inria.spirals.npefix.patch.sorter.Token;
4 | import fr.inria.spirals.npefix.patch.sorter.Tokens;
5 |
6 | public class Laplace extends Algorithm {
7 | public Laplace(Token token, Tokens predicate, Tokens corpus) {
8 | super(token, predicate, corpus);
9 | }
10 |
11 | public double perform() {
12 | int countWithPredicate = getCorpus().count(getToken(), getPredicate());
13 | int countTotal = countWithPredicate;
14 | if (!getPredicate().isEmpty()) {
15 | countTotal = getCorpus().nbWordCanFollow(getPredicate()) + getCorpus().size();
16 | }
17 | return (countWithPredicate + 1) / (double) countTotal;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/sorter/algorithm/NGram.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch.sorter.algorithm;
2 |
3 | import fr.inria.spirals.npefix.patch.sorter.Token;
4 | import fr.inria.spirals.npefix.patch.sorter.Tokens;
5 |
6 | public class NGram extends Algorithm {
7 | public NGram(Token token, Tokens predicate, Tokens corpus) {
8 | super(token, predicate, corpus);
9 | }
10 |
11 | public double perform() {
12 | int countWithPredicate = getCorpus().count(getToken(), getPredicate());
13 | int countTotal = countWithPredicate;
14 | if (!getPredicate().isEmpty()) {
15 | countTotal = getCorpus().count(getPredicate().get(getPredicate().fullSize() - 1), getPredicate().subList(0, getPredicate().fullSize() - 1));
16 | }
17 | if (countTotal == 0) {
18 | return 0.0;
19 | }
20 | return countWithPredicate / (double) countTotal;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/sorter/tokenizer/AbstractTokenizer.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch.sorter.tokenizer;
2 |
3 | public abstract class AbstractTokenizer implements Tokenizer {
4 |
5 |
6 | public AbstractTokenizer() {
7 | }
8 |
9 | @Override
10 | public String toString() {
11 | return getClass().getSimpleName().replace("Tokenizer", "");
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/sorter/tokenizer/BinaryTokenizer.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch.sorter.tokenizer;
2 |
3 | import fr.inria.spirals.npefix.patch.sorter.Token;
4 |
5 | /**
6 | * a suite of IDs or Java keywords
7 | */
8 | public class BinaryTokenizer extends AbstractTokenizer {
9 |
10 | @Override
11 | public String computeRepresentation(Token token) {
12 | if (token.isOperator() || token.isKeyword()) {
13 | return "JAVA$";
14 | }
15 | return "ID$";
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/sorter/tokenizer/FullTokenizer.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch.sorter.tokenizer;
2 |
3 | import fr.inria.spirals.npefix.patch.sorter.Token;
4 |
5 | /**
6 | * the unmodified list of token
7 | */
8 | public class FullTokenizer extends AbstractTokenizer {
9 |
10 | @Override
11 | public String computeRepresentation(Token token) {
12 | return token.getValue();
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/sorter/tokenizer/RenameIdentifierLiteralTokenizer.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch.sorter.tokenizer;
2 |
3 | import fr.inria.spirals.npefix.patch.sorter.Token;
4 |
5 | /**
6 | * identifiers and literals are abstracted as ID$1,ID$2, etc
7 | */
8 | public class RenameIdentifierLiteralTokenizer extends AbstractTokenizer {
9 |
10 |
11 | @Override
12 | public String computeRepresentation(Token token) {
13 | if (token.isText()) {
14 | return ("ID$");
15 | }
16 | return token.getValue();
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/sorter/tokenizer/RenameIdentifierTokenizer.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch.sorter.tokenizer;
2 |
3 | import fr.inria.spirals.npefix.patch.sorter.Token;
4 | import org.eclipse.jdt.core.compiler.ITerminalSymbols;
5 |
6 | /**
7 | * identifiers are abstracted as ID$1,ID$2, etc
8 | */
9 | public class RenameIdentifierTokenizer extends AbstractTokenizer {
10 |
11 | @Override
12 | public String computeRepresentation(Token token) {
13 | if (token.getType() == ITerminalSymbols.TokenNameIdentifier) {
14 | return ("ID$");
15 | }
16 | return token.getValue();
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/sorter/tokenizer/RenameLiteralTokenizer.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch.sorter.tokenizer;
2 |
3 | import fr.inria.spirals.npefix.patch.sorter.Token;
4 |
5 | /**
6 | * literals are abstracted as LIT$1,LIT$2, etc
7 | */
8 | public class RenameLiteralTokenizer extends AbstractTokenizer {
9 |
10 | @Override
11 | public String computeRepresentation(Token token) {
12 | if (token.isLiteral()) {
13 | return ("LIT$");
14 | }
15 | return token.getValue();
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/sorter/tokenizer/RenameOperatorTokenizer.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch.sorter.tokenizer;
2 |
3 | import fr.inria.spirals.npefix.patch.sorter.Token;
4 | /**
5 | * literals are abstracted as LIT$1,LIT$2, etc
6 | */
7 | public class RenameOperatorTokenizer extends AbstractTokenizer {
8 |
9 | @Override
10 | public String computeRepresentation(Token token) {
11 | if (token.isOperator()) {
12 | return ("OP");
13 | }
14 | return token.getValue();
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/sorter/tokenizer/RenameSyntaxKeywordTokenizer.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch.sorter.tokenizer;
2 |
3 | import fr.inria.spirals.npefix.patch.sorter.Token;
4 |
5 | /**
6 | * literals are abstracted as LIT$1,LIT$2, etc
7 | */
8 | public class RenameSyntaxKeywordTokenizer extends AbstractTokenizer {
9 |
10 | @Override
11 | public String computeRepresentation(Token token) {
12 | if (token.isSyntax()) {
13 | return "SYN$";
14 | }
15 | if (token.isKeyword()) {
16 | return "KEY$";
17 | }
18 | if (token.isOperator()) {
19 | return "OP$";
20 | }
21 | return token.getValue();
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/sorter/tokenizer/RenameSyntaxTokenizer.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch.sorter.tokenizer;
2 |
3 | import fr.inria.spirals.npefix.patch.sorter.Token;
4 |
5 | /**
6 | * literals are abstracted as LIT$1,LIT$2, etc
7 | */
8 | public class RenameSyntaxTokenizer extends AbstractTokenizer {
9 |
10 | @Override
11 | public String computeRepresentation(Token token) {
12 | if (token.isSyntax()) {
13 | return ("SYN$");
14 | }
15 | return token.getValue();
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/sorter/tokenizer/TokenTypeTokenizer.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch.sorter.tokenizer;
2 |
3 | import fr.inria.spirals.npefix.patch.sorter.Token;
4 |
5 | /**
6 | * a list of token types, ect PAREN, ID, OPERATOR
7 | */
8 | public class TokenTypeTokenizer extends AbstractTokenizer {
9 |
10 | @Override
11 | public String computeRepresentation(Token token) {
12 | return token.getType() + "";
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patch/sorter/tokenizer/Tokenizer.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patch.sorter.tokenizer;
2 |
3 | import fr.inria.spirals.npefix.patch.sorter.Token;
4 |
5 | public interface Tokenizer {
6 |
7 | String computeRepresentation(Token token);
8 | }
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patchTemplate/ThisFinder.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patchTemplate;
2 |
3 | import spoon.reflect.code.CtExpression;
4 | import spoon.reflect.declaration.CtClass;
5 | import spoon.reflect.declaration.CtElement;
6 | import spoon.reflect.declaration.CtType;
7 | import spoon.reflect.declaration.CtTypeMember;
8 | import spoon.reflect.declaration.ModifierKind;
9 | import spoon.reflect.reference.CtTypeReference;
10 | import spoon.reflect.visitor.CtInheritanceScanner;
11 |
12 | import java.util.ArrayList;
13 | import java.util.Collections;
14 | import java.util.List;
15 |
16 | import static fr.inria.spirals.npefix.patchTemplate.VariableFinder.isAssignableFrom;
17 |
18 | /**
19 | * Find this variable access
20 | */
21 | public class ThisFinder {
22 |
23 | private final boolean isStaticContext;
24 | private CtElement expression;
25 |
26 | public ThisFinder(CtElement expression) {
27 | this.expression = expression;
28 | CtTypeMember parent = this.expression.getParent(CtTypeMember.class);
29 | if (parent != null) {
30 | isStaticContext = parent.hasModifier(ModifierKind.STATIC);
31 | } else {
32 | isStaticContext = false;
33 | }
34 | }
35 |
36 | public List find() {
37 | if (expression.isParentInitialized() && !isStaticContext) {
38 | return getThis(expression.getParent());
39 | }
40 | return Collections.emptyList();
41 | }
42 |
43 | public List find(CtTypeReference type) {
44 | List output = new ArrayList<>();
45 | List ctExpressions = find();
46 |
47 | for (int i = 0; i < ctExpressions.size(); i++) {
48 | CtExpression ctExpression = ctExpressions.get(i);
49 | if (isAssignableFrom(type, ctExpression.getType())){
50 | output.add(ctExpression);
51 | }
52 | }
53 | return output;
54 | }
55 |
56 | public List find(CtType type) {
57 | return find(type.getReference());
58 | }
59 |
60 | private List getThis(final CtElement parent) {
61 | final List expressions = new ArrayList<>();
62 | if (parent == null) {
63 | return expressions;
64 | }
65 | class ThisScanner extends CtInheritanceScanner {
66 |
67 | @Override
68 | public void visitCtClass(CtClass ctClass) {
69 | expressions.add(ctClass.getFactory().Code().createThisAccess(ctClass.getReference()));
70 | }
71 | }
72 |
73 | new ThisScanner().scan(parent);
74 |
75 | if (parent.isParentInitialized()) {
76 | expressions.addAll(getThis(parent.getParent()));
77 | }
78 |
79 | return expressions;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patchTemplate/template/PatchTemplate.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patchTemplate.template;
2 |
3 | import spoon.reflect.code.CtExpression;
4 | import spoon.reflect.declaration.CtElement;
5 |
6 | public interface PatchTemplate {
7 |
8 | /**
9 | * Apply a patch template on the null element nullElement.
10 | *
11 | * @param nullElement the null element to patch
12 | * @return the modified element
13 | * @throws RuntimeException when the patch cannot be applied
14 | */
15 | CtElement apply(CtExpression nullElement);
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patchTemplate/template/ReplaceGlobal.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patchTemplate.template;
2 |
3 | import spoon.reflect.code.BinaryOperatorKind;
4 | import spoon.reflect.code.CtAssignment;
5 | import spoon.reflect.code.CtBinaryOperator;
6 | import spoon.reflect.code.CtExpression;
7 | import spoon.reflect.code.CtIf;
8 | import spoon.reflect.code.CtStatement;
9 | import spoon.reflect.code.CtVariableAccess;
10 | import spoon.reflect.declaration.CtClass;
11 | import spoon.reflect.declaration.CtVariable;
12 | import spoon.reflect.declaration.ModifierKind;
13 | import spoon.reflect.factory.Factory;
14 | import spoon.reflect.visitor.filter.LineFilter;
15 |
16 | /**
17 | * Skip the line that contains the null element
18 | */
19 | public class ReplaceGlobal implements PatchTemplate {
20 |
21 | private CtExpression newExpression;
22 |
23 | public ReplaceGlobal(CtExpression newExpression) {
24 | this.newExpression = newExpression;
25 | }
26 |
27 | public ReplaceGlobal(CtClass ctClass, CtExpression...args) {
28 | this.newExpression = ctClass.getFactory().Code().createConstructorCall(ctClass.getReference(), args);
29 | }
30 |
31 | public ReplaceGlobal(CtVariable variable) {
32 | this.newExpression = variable.getFactory().Code().createVariableRead(variable.getReference(), variable.hasModifier(ModifierKind.STATIC));
33 | }
34 |
35 | @Override
36 | public CtIf apply(CtExpression nullExpression) {
37 | if (!(nullExpression instanceof CtVariableAccess)) {
38 | return null;
39 | }
40 | CtStatement superLine = nullExpression.getParent(new LineFilter());
41 |
42 | Factory factory = nullExpression.getFactory();
43 |
44 | CtIf anIf = factory.Core().createIf();
45 | CtBinaryOperator condition = factory.Code().createBinaryOperator(nullExpression.clone(), factory.Code().createLiteral(null), BinaryOperatorKind.EQ);
46 |
47 | anIf.setCondition(condition);
48 |
49 | boolean isStatic = ((CtVariableAccess) nullExpression).getVariable().getDeclaration().hasModifier(ModifierKind.STATIC);
50 | CtAssignment variableAssignment = factory.Code().createVariableAssignment(((CtVariableAccess)nullExpression).getVariable(), isStatic, newExpression);
51 |
52 | anIf.setThenStatement(variableAssignment);
53 |
54 | superLine.insertBefore(anIf);
55 | return anIf;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patchTemplate/template/ReplaceLocal.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patchTemplate.template;
2 |
3 | import spoon.reflect.code.BinaryOperatorKind;
4 | import spoon.reflect.code.CtAssignment;
5 | import spoon.reflect.code.CtBinaryOperator;
6 | import spoon.reflect.code.CtExpression;
7 | import spoon.reflect.code.CtIf;
8 | import spoon.reflect.code.CtLocalVariable;
9 | import spoon.reflect.code.CtStatement;
10 | import spoon.reflect.declaration.CtClass;
11 | import spoon.reflect.declaration.CtVariable;
12 | import spoon.reflect.declaration.ModifierKind;
13 | import spoon.reflect.factory.Factory;
14 | import spoon.reflect.visitor.filter.LineFilter;
15 |
16 | /**
17 | * Skip the line that contains the null element
18 | */
19 | public class ReplaceLocal implements PatchTemplate {
20 |
21 | private CtExpression newExpression;
22 |
23 | public ReplaceLocal(CtExpression newExpression) {
24 | this.newExpression = newExpression;
25 | }
26 |
27 | public ReplaceLocal(CtClass ctClass, CtExpression...args) {
28 | this.newExpression = ctClass.getFactory().Code().createConstructorCall(ctClass.getReference(), args);
29 | }
30 |
31 | public ReplaceLocal(CtVariable variable) {
32 | this.newExpression = variable.getFactory().Code().createVariableRead(variable.getReference(), variable.hasModifier(ModifierKind.STATIC));
33 | }
34 |
35 | @Override
36 | public CtIf apply(CtExpression nullExpression) {
37 | CtStatement superLine = nullExpression.getParent(new LineFilter()).clone();
38 |
39 | Factory factory = nullExpression.getFactory();
40 |
41 | CtIf anIf = factory.Core().createIf();
42 | CtBinaryOperator condition = factory.Code().createBinaryOperator(nullExpression.clone(), factory.Code().createLiteral(null), BinaryOperatorKind.EQ);
43 |
44 | anIf.setCondition(condition);
45 |
46 | if (superLine instanceof CtLocalVariable) {
47 | CtAssignment variableAssignment = factory.Code().createVariableAssignment(((CtLocalVariable) superLine).getReference(), false, null);
48 | CtAssignment assignmentWhenNull = variableAssignment.clone();
49 | variableAssignment.setAssignment(((CtLocalVariable) superLine).getDefaultExpression());
50 | ((CtLocalVariable) superLine).setDefaultExpression(null);
51 |
52 | nullExpression.replace(newExpression);
53 |
54 | CtLocalVariable parent = (CtLocalVariable) nullExpression.getParent(new LineFilter());
55 | assignmentWhenNull.setAssignment(parent.getDefaultExpression().clone());
56 | anIf.setThenStatement(assignmentWhenNull);
57 | anIf.setElseStatement(variableAssignment);
58 |
59 | parent.insertBefore(superLine);
60 |
61 | parent.replace(anIf);
62 | } else {
63 | nullExpression.replace(newExpression);
64 |
65 | CtStatement parent = nullExpression.getParent(new LineFilter());
66 | anIf.setThenStatement(parent.clone());
67 | anIf.setElseStatement(superLine);
68 | parent.replace(anIf);
69 | }
70 |
71 | return anIf;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patchTemplate/template/SkipLine.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patchTemplate.template;
2 |
3 | import spoon.reflect.code.BinaryOperatorKind;
4 | import spoon.reflect.code.CtAssignment;
5 | import spoon.reflect.code.CtBinaryOperator;
6 | import spoon.reflect.code.CtExpression;
7 | import spoon.reflect.code.CtFor;
8 | import spoon.reflect.code.CtIf;
9 | import spoon.reflect.code.CtLocalVariable;
10 | import spoon.reflect.code.CtStatement;
11 | import spoon.reflect.factory.Factory;
12 | import spoon.reflect.visitor.filter.LineFilter;
13 |
14 | /**
15 | * Skip the line that contains the null element
16 | */
17 | public class SkipLine implements PatchTemplate {
18 |
19 | @Override
20 | public CtIf apply(CtExpression nullExpression) {
21 | Factory factory = nullExpression.getFactory();
22 |
23 | CtIf anIf = factory.Core().createIf();
24 |
25 | // if (nullExpression != null) {}
26 | CtBinaryOperator condition = factory.Code().createBinaryOperator(nullExpression.clone(), factory.Code().createLiteral(null), BinaryOperatorKind.NE);
27 |
28 | anIf.setCondition(condition);
29 |
30 | CtStatement superLine = nullExpression.getParent(new LineFilter());
31 | if (superLine instanceof CtFor) {
32 | throw new RuntimeException("Unsupported patch");
33 | }
34 | superLine = extractLocalVariable(superLine);
35 |
36 | anIf.setThenStatement(superLine.clone());
37 | anIf.getThenStatement().setImplicit(false);
38 |
39 | superLine.replace(anIf);
40 | return anIf;
41 | }
42 |
43 | private CtStatement extractLocalVariable(CtStatement statement) {
44 | if (!(statement instanceof CtLocalVariable)) {
45 | return statement;
46 | }
47 | Factory factory = statement.getFactory();
48 |
49 | CtLocalVariable variable = (CtLocalVariable) statement;
50 |
51 | CtAssignment variableAssignment = factory.Code()
52 | .createVariableAssignment(variable.getReference(), false,
53 | variable.getDefaultExpression());
54 |
55 | variable.setDefaultExpression(null);
56 |
57 | statement.insertAfter(variableAssignment);
58 |
59 | return variableAssignment;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/patchTemplate/template/SkipMethodReturn.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.patchTemplate.template;
2 |
3 | import spoon.reflect.code.BinaryOperatorKind;
4 | import spoon.reflect.code.CtBinaryOperator;
5 | import spoon.reflect.code.CtBlock;
6 | import spoon.reflect.code.CtExpression;
7 | import spoon.reflect.code.CtIf;
8 | import spoon.reflect.code.CtReturn;
9 | import spoon.reflect.code.CtStatement;
10 | import spoon.reflect.declaration.CtConstructor;
11 | import spoon.reflect.declaration.CtMethod;
12 | import spoon.reflect.declaration.CtTypeMember;
13 | import spoon.reflect.factory.Factory;
14 | import spoon.reflect.visitor.filter.LineFilter;
15 |
16 | /**
17 | * Skip the line that contains the null element
18 | */
19 | public class SkipMethodReturn implements PatchTemplate {
20 |
21 | private CtExpression newInstance;
22 |
23 | public SkipMethodReturn(CtExpression newInstance){
24 | this.newInstance = newInstance;
25 | }
26 | public SkipMethodReturn(){
27 | this.newInstance = null;
28 | }
29 |
30 | @Override
31 | public CtIf apply(CtExpression nullExpression) {
32 | if (newInstance == null) {
33 | return applyVoid(nullExpression);
34 | }
35 | Factory factory = nullExpression.getFactory();
36 |
37 | CtIf anIf = factory.Core().createIf();
38 |
39 |
40 | CtBinaryOperator condition = factory.Code().createBinaryOperator(nullExpression.clone(), factory.Code().createLiteral(null), BinaryOperatorKind.EQ);
41 |
42 | anIf.setCondition(condition);
43 |
44 | CtStatement superLine = nullExpression.getParent(new LineFilter());
45 |
46 | CtTypeMember method = nullExpression.getParent(CtTypeMember.class);
47 | if (method instanceof CtMethod) {
48 | // if (nullExpression == null) {return variable;}
49 | CtReturn aReturn = factory.Core().createReturn();
50 |
51 | aReturn.setReturnedExpression(newInstance);
52 | anIf.setThenStatement(aReturn);
53 | superLine.insertBefore(anIf);
54 | } else {
55 | throw new RuntimeException("Unsupported patch");
56 | }
57 | return anIf;
58 | }
59 |
60 | private CtIf applyVoid(CtExpression nullExpression) {
61 | Factory factory = nullExpression.getFactory();
62 |
63 | CtIf anIf = factory.Core().createIf();
64 |
65 |
66 | CtBinaryOperator condition = factory.Code().createBinaryOperator(nullExpression.clone(), factory.Code().createLiteral(null), BinaryOperatorKind.EQ);
67 |
68 | anIf.setCondition(condition);
69 |
70 | CtStatement superLine = nullExpression.getParent(new LineFilter());
71 |
72 |
73 |
74 | CtTypeMember method = nullExpression.getParent(CtTypeMember.class);
75 | if (method instanceof CtMethod) {
76 | // if (nullExpression == null) {return;}
77 | CtReturn aReturn = factory.Core().createReturn();
78 | if (((CtMethod) method).getType().equals(factory.Type().voidPrimitiveType())) {
79 | aReturn.setReturnedExpression(null);
80 | } else if (((CtMethod) method).getType().isPrimitive()) {
81 | // cannot return null with primitive
82 | throw new RuntimeException("Unsupported patch");
83 | } else {
84 | aReturn.setReturnedExpression(factory.Code().createLiteral(null));
85 | }
86 | anIf.setThenStatement(aReturn);
87 | superLine.insertBefore(anIf);
88 | } else if (method instanceof CtConstructor) {
89 | // if (nullExpression != null) {}
90 | condition.setKind(BinaryOperatorKind.NE);
91 | CtBlock body = ((CtConstructor) method).getBody();
92 | int size = body.getStatements().size();
93 | anIf.setThenStatement(body.clone());
94 | int index = body.getStatements().indexOf(superLine);
95 | for (int i = 0; i < index; i++) {
96 | ((CtBlock)anIf.getThenStatement()).removeStatement(body.getStatement(i));
97 | }
98 | CtBlock bodyClone = body.clone();
99 | for (int i = index; i < size; i++) {
100 | body.removeStatement(bodyClone.getStatement(i));
101 | }
102 | if (index > 0) {
103 | body.getStatement(index - 1).insertAfter(anIf);
104 | } else {
105 | body.addStatement(anIf);
106 | }
107 | } else {
108 | throw new RuntimeException("Unsupported patch");
109 | }
110 | return anIf;
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/resi/ExceptionStack.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.resi;
2 |
3 | import fr.inria.spirals.npefix.resi.context.TryContext;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | public class ExceptionStack {
9 |
10 | private static List tryContexts = new ArrayList<>();
11 |
12 | public static void register(TryContext tc) {
13 | tryContexts.add(tc);
14 | }
15 |
16 | public static void unregister(TryContext tc){
17 | if(tryContexts.isEmpty())
18 | return;
19 | if(tryContexts.get(tryContexts.size()-1).equals(tc)){
20 | tryContexts.remove(tryContexts.size()-1);
21 | }else{
22 | //System.err.println("oops?");
23 | }
24 | }
25 |
26 | public static boolean isStoppable(Class extends Exception> c){
27 | for (TryContext tryContext : tryContexts) {
28 | if (tryContext == null) {
29 | continue;
30 | }
31 | for (Class clazz : tryContext.getTypes()) {
32 | if(clazz.isAssignableFrom(c)){
33 | return true;
34 | }
35 | }
36 | }
37 | return false;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/resi/RandomGenerator.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.resi;
2 |
3 | import fr.inria.spirals.npefix.config.Config;
4 |
5 | import java.util.Random;
6 |
7 | public class RandomGenerator {
8 | public static long seed = Config.CONFIG.getRandomSeed();
9 |
10 | private static Random generator = new Random(seed);
11 |
12 | public static int nextInt(){
13 | return generator.nextInt();
14 | }
15 |
16 | public static int nextInt(int max){
17 | return generator.nextInt(max);
18 | }
19 |
20 | public static int nextInt(int min, int max){
21 | return generator.nextInt(max - min) + min;
22 | }
23 |
24 | public static double nextDouble() {
25 | return generator.nextDouble();
26 | }
27 |
28 | public static void reset() {
29 | generator = new Random(seed);
30 | }
31 |
32 | public static Random getGenerator() {
33 | return generator;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/resi/context/ConstructorContext.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.resi.context;
2 |
3 | public class ConstructorContext extends MethodContext {
4 | public ConstructorContext(Class c, int line, int sourceStart, int sourceEnd) {
5 | super(c, line, sourceStart, sourceEnd);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/resi/context/Location.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.resi.context;
2 |
3 | import org.json.JSONObject;
4 |
5 | import java.io.Serializable;
6 |
7 | public class Location implements Comparable, Serializable {
8 |
9 | private static final long serialVersionUID = 1L;
10 |
11 | private String className;
12 | private int line;
13 | private int sourceStart;
14 | private int sourceEnd;
15 |
16 | public Location(String className, int line, int sourceStart, int sourceEnd) {
17 | this.className = className;
18 | this.line = line;
19 | this.sourceStart = sourceStart;
20 | this.sourceEnd = sourceEnd;
21 | }
22 |
23 | public void setLine(int line) {
24 | this.line = line;
25 | }
26 |
27 | public String getClassName() {
28 | return className;
29 | }
30 |
31 | public void setClassName(String className) {
32 | this.className = className;
33 | }
34 |
35 | public int getLine() {
36 | return line;
37 | }
38 |
39 | public int getSourceStart() {
40 | return sourceStart;
41 | }
42 |
43 | public void setSourceStart(int sourceStart) {
44 | this.sourceStart = sourceStart;
45 | }
46 |
47 | public int getSourceEnd() {
48 | return sourceEnd;
49 | }
50 |
51 | public void setSourceEnd(int sourceEnd) {
52 | this.sourceEnd = sourceEnd;
53 | }
54 |
55 | @Override
56 | public boolean equals(Object o) {
57 | if (this == o)
58 | return true;
59 | if (o == null || getClass() != o.getClass())
60 | return false;
61 |
62 | Location location = (Location) o;
63 |
64 | if (line != location.line)
65 | return false;
66 | if (sourceStart != location.sourceStart)
67 | return false;
68 | if (sourceEnd != location.sourceEnd)
69 | return false;
70 | if (className != null ?
71 | !className.equals(location.className) :
72 | location.className != null)
73 | return false;
74 |
75 | return true;
76 | }
77 |
78 | @Override
79 | public int compareTo(Location location) {
80 | if(this.equals(location)) {
81 | return 0;
82 | }
83 | if(this.className.equals(location.className)) {
84 | if(this.line == (location.line)) {
85 | return this.sourceStart - location.sourceStart;
86 | } else {
87 | return this.line - (location.line);
88 | }
89 | } else {
90 | return this.className.compareTo(location.className);
91 | }
92 | }
93 |
94 | @Override
95 | public int hashCode() {
96 | int result = className != null ? className.hashCode() : 0;
97 | result = 31 * result + line;
98 | result = 31 * result + sourceStart;
99 | result = 31 * result + sourceEnd;
100 | return result;
101 | }
102 |
103 | @Override
104 | public String toString() {
105 | return className.replace("org.apache.commons.", "") + ":" + line;
106 | }
107 |
108 | public JSONObject toJSON() {
109 | JSONObject locationJSON = new JSONObject();
110 | locationJSON.put("class", this.getClassName());
111 | locationJSON.put("line", this.getLine());
112 | locationJSON.put("sourceStart", this.getSourceStart());
113 | locationJSON.put("sourceEnd", this.getSourceEnd());
114 | return locationJSON;
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/resi/context/MethodContext.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.resi.context;
2 |
3 | import fr.inria.spirals.npefix.resi.CallChecker;
4 |
5 | import java.util.HashMap;
6 |
7 | public class MethodContext {
8 |
9 | public static int idCount = 1;
10 | private final HashMap variables;
11 | private final Class methodType;
12 | private final String methodName;
13 | private final String className;
14 | private final int id;
15 | private Location location;
16 |
17 | public MethodContext(Class c) {
18 | this(c, -1, -1, -1);
19 | Thread thread = Thread.currentThread();
20 | StackTraceElement[] stackTraces = thread.getStackTrace();
21 | StackTraceElement stackTrace = stackTraces[2];
22 | int line = stackTrace.getLineNumber();
23 | this.location = new Location(stackTrace.getClassName(), line, -1, -1);
24 | }
25 |
26 | public MethodContext(Class c, int line, int sourceStart, int sourceEnd) {
27 | CallChecker.methodStart(this);
28 | this.methodType = c;
29 | this.variables = new HashMap();
30 |
31 | int stackPosition = 2;
32 | if (this.getLocation() != null) {
33 | stackPosition --;
34 | }
35 | Thread thread = Thread.currentThread();
36 | StackTraceElement[] stackTraces = thread.getStackTrace();
37 | StackTraceElement stackTrace = stackTraces[stackPosition];
38 | methodName = stackTrace.getMethodName();
39 | className = stackTrace.getClassName();
40 | this.location = new Location(stackTrace.getClassName(), line, sourceStart, sourceEnd);
41 | this.id = idCount++;
42 | }
43 |
44 | public void methodEnd() {
45 | CallChecker.methodEnd(this);
46 | }
47 |
48 | public HashMap getVariables() {
49 | return variables;
50 | }
51 |
52 | public void addVariable(String name, Object value) {
53 | variables.put(name, value);
54 | }
55 |
56 | public Class getMethodType() {
57 | return methodType;
58 | }
59 |
60 | public Location getLocation() {
61 | return location;
62 | }
63 |
64 | @Override
65 | public String toString() {
66 | return "#" + id + " " + className + "#" + methodName + " " + variables.size() + " variables at " + this.getLocation();
67 | }
68 |
69 | @Override
70 | public boolean equals(Object o) {
71 | if (this == o)
72 | return true;
73 | if (o == null || getClass() != o.getClass())
74 | return false;
75 |
76 | MethodContext that = (MethodContext) o;
77 |
78 | return this.id == that.id;
79 | }
80 |
81 | @Override
82 | public int hashCode() {
83 | int result = methodName != null ? methodName.hashCode() : 0;
84 | result = 31 * result + (className != null ? className.hashCode() : 0);
85 | return result;
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/resi/context/NPEOutput.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.resi.context;
2 |
3 | import fr.inria.spirals.npefix.resi.strategies.Strategy;
4 | import org.json.JSONObject;
5 | import spoon.Launcher;
6 |
7 | import java.util.ArrayList;
8 | import java.util.Date;
9 | import java.util.HashSet;
10 | import java.util.Set;
11 |
12 | public class NPEOutput extends ArrayList{
13 |
14 | private Date start;
15 | private Date end;
16 |
17 | public NPEOutput() {
18 | this.start = new Date();
19 | }
20 |
21 | public Set getTests() {
22 | Set output = new HashSet<>();
23 | for (int i = 0; i < this.size(); i++) {
24 | Lapse lapse = this.get(i);
25 | output.add(lapse.getTestClassName() + "#" + lapse.getTestName());
26 | }
27 | return output;
28 | }
29 |
30 | public Set getRanStrategies() {
31 | Set output = new HashSet<>();
32 | for (int i = 0; i < this.size(); i++) {
33 | Lapse lapse = this.get(i);
34 | for (int j = 0; j < lapse.getDecisions().size(); j++) {
35 | Decision decision = lapse.getDecisions().get(j);
36 | output.add(decision.getStrategy());
37 | }
38 | }
39 | return output;
40 | }
41 |
42 | public NPEOutput getExecutionsForStrategy(Strategy strategy) {
43 | NPEOutput output = new NPEOutput();
44 | for (int i = 0; i < this.size(); i++) {
45 | Lapse lapse = this.get(i);
46 | for (int j = 0; j < lapse.getDecisions().size(); j++) {
47 | Decision decision = lapse.getDecisions().get(j);
48 | if(decision.getStrategy().equals(strategy)) {
49 | output.add(lapse);
50 | }
51 | }
52 | }
53 | return output;
54 | }
55 |
56 | public int getFailureCount() {
57 | int output = 0;
58 | for (int i = 0; i < this.size(); i++) {
59 | Lapse lapse = this.get(i);
60 | if(!lapse.getOracle().isValid()) {
61 | output += 1;
62 | }
63 | }
64 | return output;
65 | }
66 |
67 | public int getFailureCount(Strategy strategy) {
68 | int output = 0;
69 | NPEOutput executionsForStrategy = getExecutionsForStrategy(strategy);
70 | for (int i = 0; i < executionsForStrategy.size(); i++) {
71 | Lapse lapse = executionsForStrategy.get(i);
72 | if(!lapse.getOracle().isValid()) {
73 | output += 1;
74 | }
75 | }
76 | return output;
77 | }
78 |
79 | public NPEOutput getExecutionsForLocation(Location location) {
80 | NPEOutput output = new NPEOutput();
81 | for (int i = 0; i < this.size(); i++) {
82 | Lapse lapse = this.get(i);
83 | if(lapse.getLocations().contains(location)) {
84 | output.add(lapse);
85 | }
86 | }
87 | return output;
88 | }
89 |
90 | public Date getStart() {
91 | return start;
92 | }
93 |
94 | public Date getEnd() {
95 | return end;
96 | }
97 |
98 | public void setStart(Date start) {
99 | this.start = start;
100 | }
101 |
102 | public void setEnd(Date end) {
103 | this.end = end;
104 | }
105 |
106 | public JSONObject toJSON(Launcher spoon) {
107 | JSONObject output = new JSONObject();
108 | output.put("start", start.getTime());
109 | for (int i = 0; i < this.size(); i++) {
110 | Lapse lapse = this.get(i);
111 | if (!lapse.getDecisions().isEmpty()) {
112 | boolean isAllUsed = true;
113 | for (int j = 0; j < lapse.getDecisions().size() && isAllUsed; j++) {
114 | Decision decision = lapse.getDecisions().get(j);
115 | isAllUsed = isAllUsed && decision.isUsed();
116 | }
117 | if (isAllUsed) {
118 | output.append("executions", lapse.toJSON(spoon));
119 | }
120 | }
121 | }
122 | if (end == null) {
123 | end = new Date();
124 | }
125 | output.put("end", end.getTime());
126 | return output;
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/resi/context/TryContext.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.resi.context;
2 |
3 | import fr.inria.spirals.npefix.resi.ExceptionStack;
4 |
5 | public class TryContext {
6 |
7 | private int id = -1;
8 | private Class>[] types;
9 | private Class> context;
10 |
11 | public TryContext(int id, Class> context, String... types) {
12 | this.id=id;
13 | this.types = new Class[types.length];
14 | this.context = context;
15 | int i=0;
16 | ClassLoader classLoader = context.getClassLoader();
17 | for (String str : types) {
18 | try {
19 | this.types[i++] = classLoader.loadClass(str);
20 | } catch (ClassNotFoundException e) {
21 | System.out.println(e);
22 | //throw new RuntimeException(e);
23 | }
24 | }
25 | ExceptionStack.register(this);
26 | }
27 |
28 | public void catchStart(int i) {
29 | ExceptionStack.unregister(this);
30 | }
31 |
32 | public void finallyStart(int i) {
33 | ExceptionStack.unregister(this);
34 | }
35 |
36 | @Override
37 | public boolean equals(Object o) {
38 | if(!(o instanceof TryContext))return false;
39 | return this.id == ((TryContext)o).id;
40 | }
41 |
42 | public Class[] getTypes() {
43 | return types;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/resi/context/instance/AbstractInstance.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.resi.context.instance;
2 |
3 | import fr.inria.spirals.npefix.resi.CallChecker;
4 | import org.json.JSONObject;
5 |
6 | public abstract class AbstractInstance implements Instance {
7 |
8 | public Class getClassFromString (String className) {
9 | if(className.equals("int")) {
10 | return int.class;
11 | }
12 | if(className.equals("int[]")) {
13 | return int[].class;
14 | }
15 | if(className.equals("long")) {
16 | return long.class;
17 | }
18 | if(className.equals("long[]")) {
19 | return long[].class;
20 | }
21 | if(className.equals("float")) {
22 | return float.class;
23 | }
24 | if(className.equals("float[]")) {
25 | return float[].class;
26 | }
27 | if(className.equals("double")) {
28 | return double.class;
29 | }
30 | if(className.equals("double[]")) {
31 | return double[].class;
32 | }
33 | if(className.equals("byte")) {
34 | return byte.class;
35 | }
36 | if(className.equals("byte[]")) {
37 | return byte[].class;
38 | }
39 | if(className.equals("char")) {
40 | return char.class;
41 | }
42 | if(className.equals("char[]")) {
43 | return char[].class;
44 | }
45 | if(className.equals("boolean")) {
46 | return boolean.class;
47 | }
48 | if(className.equals("boolean[]")) {
49 | return boolean[].class;
50 | }
51 | try {
52 | return getClass().forName(className);
53 | } catch (ClassNotFoundException e) {
54 | try {
55 | return CallChecker.currentClassLoader.loadClass(className);
56 | } catch (Exception e1) {
57 | throw new RuntimeException(e1);
58 | }
59 | }
60 | }
61 |
62 | public abstract JSONObject toJSON();
63 |
64 | @Override
65 | public int compareTo(Object o) {
66 | if (this instanceof PrimitiveInstance) {
67 | return -5;
68 | }
69 | if (this instanceof VariableInstance) {
70 | return -4;
71 | }
72 | if (this instanceof StaticVariableInstance) {
73 | return -3;
74 | }
75 | if (this instanceof NewInstance) {
76 | return -2;
77 | }
78 | if (this instanceof NewArrayInstance) {
79 | return -1;
80 | }
81 | return 0;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/resi/context/instance/ArrayReadInstance.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.resi.context.instance;
2 |
3 | import fr.inria.spirals.npefix.resi.CallChecker;
4 | import org.json.JSONObject;
5 | import spoon.reflect.code.CtArrayRead;
6 | import spoon.reflect.factory.Factory;
7 | import spoon.reflect.reference.CtLocalVariableReference;
8 |
9 | public class ArrayReadInstance extends AbstractInstance {
10 |
11 | private String variableName;
12 | private int index;
13 |
14 | public ArrayReadInstance(String variableName, int index) {
15 | this.variableName = variableName;
16 | this.index = index;
17 | }
18 |
19 | @Override
20 | public T getValue() {
21 | Object o = CallChecker.getCurrentMethodContext().getVariables().get(variableName);
22 | return (T) o;
23 | }
24 |
25 |
26 |
27 | @Override
28 | public int hashCode() {
29 | return variableName != null ? variableName.hashCode() : 0;
30 | }
31 |
32 | @Override
33 | public String toString() {
34 | return variableName;
35 | }
36 |
37 | @Override
38 | public JSONObject toJSON() {
39 | JSONObject output = new JSONObject();
40 | output.put("instanceType", getClass().getSimpleName().replace("Instance", ""));
41 | output.put("variableName", variableName);
42 | output.put("index", index);
43 | return output;
44 | }
45 |
46 | @Override
47 | public CtArrayRead toCtExpression(Factory factory) {
48 | CtArrayRead> variableRead = factory.Core().createArrayRead();
49 | CtLocalVariableReference> localVariableReference = factory.Core().createLocalVariableReference();
50 | localVariableReference.setSimpleName(variableName);
51 | variableRead.setTarget(factory.createVariableRead(localVariableReference, false));
52 | variableRead.setIndexExpression(factory.createLiteral(index));
53 | return variableRead;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/resi/context/instance/Instance.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.resi.context.instance;
2 |
3 | import org.json.JSONObject;
4 | import spoon.reflect.code.CtExpression;
5 | import spoon.reflect.factory.Factory;
6 |
7 | import java.io.Serializable;
8 |
9 | public interface Instance extends Serializable, Comparable {
10 | T getValue();
11 |
12 | CtExpression toCtExpression(Factory factory);
13 |
14 | JSONObject toJSON();
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/resi/context/instance/InstanceFactory.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.resi.context.instance;
2 |
3 | import spoon.reflect.code.CtConstructorCall;
4 | import spoon.reflect.code.CtExpression;
5 | import spoon.reflect.code.CtLiteral;
6 | import spoon.reflect.code.CtThisAccess;
7 | import spoon.reflect.code.CtVariableAccess;
8 | import spoon.reflect.declaration.CtField;
9 | import spoon.reflect.declaration.CtVariable;
10 | import spoon.reflect.declaration.ModifierKind;
11 | import spoon.reflect.reference.CtTypeReference;
12 |
13 | import java.util.ArrayList;
14 | import java.util.List;
15 |
16 | public class InstanceFactory {
17 |
18 | public static Instance fromCtExpression(CtExpression expression) {
19 | Instance instance = null;
20 |
21 | if (expression == null) {
22 | instance = new PrimitiveInstance(null);
23 | } else if (expression instanceof CtLiteral) {
24 | instance = new PrimitiveInstance(((CtLiteral) expression).getValue());
25 | } else if (expression instanceof CtVariableAccess) {
26 | CtVariable declaration = ((CtVariableAccess) expression).getVariable().getDeclaration();
27 | if (declaration != null && declaration.hasModifier(ModifierKind.STATIC)) {
28 | instance = new StaticVariableInstance(((CtField)declaration).getDeclaringType().getQualifiedName(), declaration.getSimpleName());
29 | } else {
30 | instance = new VariableInstance(expression.toString());
31 | }
32 | } else if (expression instanceof CtConstructorCall) {
33 | String classname = (expression).getType().getQualifiedName();
34 | List parameters = ((CtConstructorCall) expression).getExecutable().getParameters();
35 | List constructorArguments = ((CtConstructorCall) expression).getArguments();
36 |
37 | String[] parameterTypes = new String[parameters.size()];
38 | List arguments = new ArrayList<>();
39 |
40 | for (int i = 0; i < parameters.size(); i++) {
41 | CtTypeReference ctParameter = parameters.get(i);
42 | parameterTypes[i] = ctParameter.getQualifiedName();
43 |
44 | arguments.add(fromCtExpression(constructorArguments.get(i)));
45 | }
46 | instance = new NewInstance(classname, parameterTypes, arguments);
47 | } else if (expression instanceof CtThisAccess) {
48 | instance = new VariableInstance(expression.toString());
49 | } else {
50 | instance = new PrimitiveInstance(expression.toString());
51 | System.err.println(expression.getType() + " not handled");
52 | }
53 | return instance;
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/resi/context/instance/PrimitiveInstance.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.resi.context.instance;
2 |
3 | import org.json.JSONObject;
4 | import spoon.reflect.code.CtLiteral;
5 | import spoon.reflect.factory.Factory;
6 |
7 | public class PrimitiveInstance extends AbstractInstance {
8 |
9 | public T value;
10 |
11 | public PrimitiveInstance(T value) {
12 | this.value = value;
13 | }
14 |
15 | @Override
16 | public T getValue() {
17 | return value;
18 | }
19 |
20 | @Override
21 | public String toString() {
22 | return "" + value;
23 | }
24 |
25 | @Override
26 | public boolean equals(Object o) {
27 | if (this == o)
28 | return true;
29 | if (o == null || getClass() != o.getClass())
30 | return false;
31 |
32 | PrimitiveInstance> that = (PrimitiveInstance>) o;
33 |
34 | if (value != null ? !value.equals(that.value) : that.value != null)
35 | return false;
36 |
37 | return true;
38 | }
39 |
40 | @Override
41 | public int hashCode() {
42 | return value != null ? value.hashCode() : 0;
43 | }
44 |
45 | @Override
46 | public JSONObject toJSON() {
47 | JSONObject output = new JSONObject();
48 | output.put("instanceType", getClass().getSimpleName().replace("Instance", ""));
49 | if (value == null) {
50 | output.put("class", "null");
51 | output.put("value", "null");
52 | } else {
53 | output.put("class", value.getClass());
54 | output.put("value", value);
55 | }
56 | return output;
57 | }
58 |
59 | public CtLiteral toCtExpression(Factory factory) {
60 | return factory.Code().createLiteral(value);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/fr/inria/spirals/npefix/resi/context/instance/StaticVariableInstance.java:
--------------------------------------------------------------------------------
1 | package fr.inria.spirals.npefix.resi.context.instance;
2 |
3 | import fr.inria.spirals.npefix.resi.CallChecker;
4 | import fr.inria.spirals.npefix.resi.exception.VarNotFound;
5 | import org.json.JSONObject;
6 | import spoon.reflect.code.CtFieldRead;
7 | import spoon.reflect.factory.Factory;
8 | import spoon.reflect.reference.CtFieldReference;
9 | import spoon.reflect.reference.CtTypeReference;
10 |
11 | import java.lang.reflect.Field;
12 |
13 | public class StaticVariableInstance extends AbstractInstance {
14 |
15 | private final String clazz;
16 | private String fieldName;
17 |
18 | public StaticVariableInstance(String clazz, String fieldName) {
19 | this.clazz = clazz;
20 | this.fieldName = fieldName;
21 | }
22 | @Override
23 | public T getValue() {
24 | try {
25 | Field field = CallChecker.currentClassLoader.loadClass(clazz).getField(fieldName);
26 | field.setAccessible(true);
27 | Object o = field.get(null);
28 | return (T) o;
29 | } catch (Exception e) {
30 | throw new VarNotFound("Unable to get the fied of " + clazz);
31 | }
32 | }
33 |
34 | @Override
35 | public boolean equals(Object o) {
36 | if (this == o)
37 | return true;
38 | if (o == null || getClass() != o.getClass())
39 | return false;
40 |
41 | StaticVariableInstance> that = (StaticVariableInstance>) o;
42 |
43 | if (clazz != null ? !clazz.equals(that.clazz) : that.clazz != null)
44 | return false;
45 | if (fieldName != null ?
46 | !fieldName.equals(that.fieldName) :
47 | that.fieldName != null)
48 | return false;
49 |
50 | return true;
51 | }
52 |
53 | @Override
54 | public int hashCode() {
55 | int result = clazz != null ? clazz.hashCode() : 0;
56 | result = 31 * result + (fieldName != null ? fieldName.hashCode() : 0);
57 | return result;
58 | }
59 |
60 | @Override
61 | public String toString() {
62 | return clazz + "." + fieldName;
63 | }
64 |
65 | @Override
66 | public JSONObject toJSON() {
67 | JSONObject output = new JSONObject();
68 | output.put("instanceType", getClass().getSimpleName().replace("Instance", ""));
69 | output.put("class", clazz);
70 | output.put("fieldName", fieldName);
71 | return output;
72 | }
73 |
74 | public CtFieldRead toCtExpression(Factory factory) {
75 | CtFieldRead