├── .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 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 fieldRead = factory.Core().createFieldRead(); 76 | CtFieldReference fieldReference = factory.Core().createFieldReference(); 77 | CtTypeReference reference = factory.Class().createReference(clazz); 78 | fieldReference.setStatic(true); 79 | fieldReference.setSimpleName(fieldName); 80 | fieldReference.setDeclaringType(reference); 81 | fieldRead.setVariable(fieldReference); 82 | return fieldRead; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/context/instance/VariableInstance.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.CtVariableAccess; 6 | import spoon.reflect.code.CtVariableRead; 7 | import spoon.reflect.factory.Factory; 8 | import spoon.reflect.reference.CtLocalVariableReference; 9 | 10 | public class VariableInstance extends AbstractInstance { 11 | 12 | private String variableName; 13 | public VariableInstance(String variableName) { 14 | this.variableName = variableName; 15 | } 16 | @Override 17 | public T getValue() { 18 | Object o = CallChecker.getCurrentMethodContext().getVariables().get(variableName); 19 | return (T) o; 20 | } 21 | 22 | @Override 23 | public boolean equals(Object o) { 24 | if (this == o) 25 | return true; 26 | if (o == null || getClass() != o.getClass()) 27 | return false; 28 | 29 | VariableInstance that = (VariableInstance) o; 30 | 31 | if (variableName != null ? 32 | !variableName.equals(that.variableName) : 33 | that.variableName != null) 34 | return false; 35 | 36 | return true; 37 | } 38 | 39 | @Override 40 | public int hashCode() { 41 | return variableName != null ? variableName.hashCode() : 0; 42 | } 43 | 44 | @Override 45 | public String toString() { 46 | return variableName; 47 | } 48 | 49 | @Override 50 | public JSONObject toJSON() { 51 | JSONObject output = new JSONObject(); 52 | output.put("instanceType", getClass().getSimpleName().replace("Instance", "")); 53 | output.put("variableName", variableName); 54 | return output; 55 | } 56 | 57 | public CtVariableAccess toCtExpression(Factory factory) { 58 | CtVariableRead variableRead = factory.Core().createVariableRead(); 59 | CtLocalVariableReference localVariableReference = factory.Core().createLocalVariableReference(); 60 | localVariableReference.setSimpleName(variableName); 61 | variableRead.setVariable(localVariableReference); 62 | return variableRead; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/exception/AbnormalExecutionError.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.exception; 2 | 3 | public class AbnormalExecutionError extends NPEFixError { 4 | 5 | public AbnormalExecutionError(){ 6 | super(); 7 | } 8 | 9 | public AbnormalExecutionError(String string) { 10 | super(string); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/exception/ErrorInitClass.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.exception; 2 | 3 | /** 4 | * Created by thomas on 15/10/15. 5 | */ 6 | public class ErrorInitClass extends NPEFixError { 7 | public ErrorInitClass(){ 8 | super(); 9 | } 10 | 11 | public ErrorInitClass(String string) { 12 | super(string); 13 | } 14 | public ErrorInitClass(String string, Throwable t) { 15 | super(string, t); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/exception/ForceReturn.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.exception; 2 | 3 | import fr.inria.spirals.npefix.resi.context.Decision; 4 | 5 | public class ForceReturn extends RuntimeException { 6 | private Decision decision; 7 | 8 | public ForceReturn(Decision decision) { 9 | this.decision = decision; 10 | } 11 | 12 | public Decision getDecision() { 13 | return decision; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/exception/NPEFixError.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.exception; 2 | 3 | public class NPEFixError extends Error { 4 | 5 | public NPEFixError(){ 6 | super(); 7 | } 8 | 9 | public NPEFixError(String string) { 10 | super(string); 11 | } 12 | 13 | public NPEFixError(String string, Throwable t) { 14 | super(string, t); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/exception/NoMoreDecision.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.exception; 2 | 3 | /** 4 | * Created by thomas on 15/10/15. 5 | */ 6 | public class NoMoreDecision extends NPEFixError { 7 | public NoMoreDecision(){ 8 | super(); 9 | } 10 | 11 | public NoMoreDecision(String string) { 12 | super(string); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/exception/ReturnNotSupported.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.exception; 2 | 3 | /** 4 | * Created by thomas on 15/10/15. 5 | */ 6 | public class ReturnNotSupported extends NPEFixError { 7 | public ReturnNotSupported(){ 8 | super(); 9 | } 10 | 11 | public ReturnNotSupported(String string) { 12 | super(string); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/exception/VarNotFound.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.exception; 2 | 3 | /** 4 | * Created by thomas on 15/10/15. 5 | */ 6 | public class VarNotFound extends NPEFixError { 7 | public VarNotFound(){ 8 | super(); 9 | } 10 | 11 | public VarNotFound(String string) { 12 | super(string); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/oracle/AbstractOracle.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.oracle; 2 | 3 | import org.json.JSONObject; 4 | 5 | public class AbstractOracle implements Oracle { 6 | private boolean isValid; 7 | private String error; 8 | private String type = "test"; 9 | 10 | public AbstractOracle(String type, boolean isValid) { 11 | this.isValid = isValid; 12 | this.type = type; 13 | } 14 | 15 | @Override 16 | public boolean isValid() { 17 | return isValid; 18 | } 19 | 20 | public void setValid(boolean valid) { 21 | isValid = valid; 22 | } 23 | 24 | public void setError(String error) { 25 | this.error = error; 26 | } 27 | 28 | public String getError() { 29 | return error; 30 | } 31 | 32 | @Override 33 | public JSONObject toJSON() { 34 | JSONObject resultJSON = new JSONObject(); 35 | resultJSON.put("success", isValid); 36 | resultJSON.put("error", error); 37 | resultJSON.put("type", type); 38 | return resultJSON; 39 | } 40 | 41 | /** 42 | * Print the stack trace of an exception 43 | * @param exception 44 | * @return 45 | */ 46 | protected String printException(Throwable exception) { 47 | StringBuilder output = new StringBuilder(); 48 | output.append(exception.getClass() + ": " + exception.getMessage() + "\n"); 49 | for (int i = 0; i < exception.getStackTrace().length && i < 25; i++) { 50 | StackTraceElement trace = exception.getStackTrace()[i]; 51 | output.append(" at " + trace.getClassName() + '.' + trace.getMethodName()); 52 | output.append('(' + trace.getFileName() + ':' + trace.getLineNumber() + ")\n"); 53 | } 54 | if(exception.getCause() != null) { 55 | output.append("Caused By:\n"); 56 | output.append(printException(exception.getCause())); 57 | } 58 | return output.toString(); 59 | } 60 | 61 | @Override 62 | public String toString() { 63 | return error ; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/oracle/ExceptionOracle.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.oracle; 2 | 3 | public class ExceptionOracle extends AbstractOracle { 4 | 5 | public ExceptionOracle(Exception e) { 6 | super("exception", false); 7 | setError(printException(e)); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/oracle/Oracle.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.oracle; 2 | 3 | import org.json.JSONObject; 4 | 5 | import java.io.Serializable; 6 | 7 | public interface Oracle extends Serializable { 8 | boolean isValid(); 9 | 10 | String getError(); 11 | 12 | JSONObject toJSON(); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/oracle/TestOracle.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.oracle; 2 | 3 | import org.junit.runner.Result; 4 | import org.junit.runner.notification.Failure; 5 | 6 | import java.util.List; 7 | 8 | public class TestOracle extends AbstractOracle { 9 | 10 | public TestOracle(Result r) { 11 | super("test", r.wasSuccessful()); 12 | if(!isValid()) { 13 | setError(toStringFailures(r)); 14 | } 15 | } 16 | 17 | /** 18 | * Get the string representation of the failure of a junit result 19 | * @param r the junit result 20 | * @return the string representation of the failures 21 | */ 22 | protected String toStringFailures(Result r) { 23 | StringBuilder output = new StringBuilder(); 24 | List failures = r.getFailures(); 25 | for (int j = 0; j < failures.size(); j++) { 26 | Failure failure = failures.get(j); 27 | Throwable exception = failure.getException(); 28 | output.append(failure.toString() + "\n"); 29 | if(exception != null) { 30 | output.append(printException(exception)); 31 | output.append("\n\n"); 32 | } 33 | } 34 | 35 | return output.toString(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/selector/AbstractSelector.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.selector; 2 | 3 | import fr.inria.spirals.npefix.resi.context.Lapse; 4 | import fr.inria.spirals.npefix.resi.strategies.NoStrat; 5 | import fr.inria.spirals.npefix.resi.strategies.ReturnType; 6 | import fr.inria.spirals.npefix.resi.strategies.Strat1A; 7 | import fr.inria.spirals.npefix.resi.strategies.Strat1B; 8 | import fr.inria.spirals.npefix.resi.strategies.Strat2A; 9 | import fr.inria.spirals.npefix.resi.strategies.Strat2B; 10 | import fr.inria.spirals.npefix.resi.strategies.Strat3; 11 | import fr.inria.spirals.npefix.resi.strategies.Strat4; 12 | import fr.inria.spirals.npefix.resi.strategies.Strategy; 13 | 14 | import java.rmi.RemoteException; 15 | import java.util.ArrayList; 16 | import java.util.Arrays; 17 | import java.util.Date; 18 | import java.util.List; 19 | 20 | /** 21 | * Created by thomas on 09/11/15. 22 | */ 23 | public abstract class AbstractSelector implements Selector { 24 | 25 | private Lapse currentLapse; 26 | private List lapses = new ArrayList<>(); 27 | 28 | protected static final Strategy[] strategies = new Strategy[]{ 29 | new NoStrat(), 30 | new Strat1A(), 31 | new Strat1B(), 32 | new Strat2A(), 33 | new Strat2B(), 34 | new Strat3(), 35 | new Strat4(ReturnType.NULL), 36 | new Strat4(ReturnType.VAR), 37 | new Strat4(ReturnType.NEW), 38 | new Strat4(ReturnType.VOID) 39 | }; 40 | 41 | @Override 42 | public boolean startLaps(Lapse lapse) throws RemoteException { 43 | this.currentLapse = lapse; 44 | lapse.setFinished(false); 45 | return false; 46 | } 47 | 48 | @Override 49 | public Lapse getCurrentLapse() { 50 | return currentLapse; 51 | } 52 | 53 | @Override 54 | public Lapse updateCurrentLapse(Lapse updatedLapse) { 55 | if (currentLapse == null || currentLapse.equals(updatedLapse)) { 56 | currentLapse = updatedLapse; 57 | } 58 | return currentLapse; 59 | } 60 | 61 | public List getAllStrategies() { 62 | return Arrays.asList(strategies); 63 | } 64 | 65 | @Override 66 | public List getLapses() { 67 | return lapses; 68 | } 69 | 70 | @Override 71 | public boolean restartTest(Lapse lapse) { 72 | lapse.setFinished(true); 73 | if (!lapse.getDecisions().isEmpty()) { 74 | lapses.add(lapse); 75 | } 76 | lapse.setEndDate(new Date()); 77 | return false; 78 | } 79 | 80 | @Override 81 | public void reset() throws RemoteException { 82 | currentLapse = null; 83 | lapses = new ArrayList<>(); 84 | } 85 | 86 | @Override 87 | public String toString() { 88 | return getClass().getSimpleName(); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/selector/DomSelector.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.selector; 2 | 3 | import fr.inria.spirals.npefix.resi.context.Decision; 4 | import fr.inria.spirals.npefix.resi.context.Lapse; 5 | import fr.inria.spirals.npefix.resi.strategies.NoStrat; 6 | import fr.inria.spirals.npefix.resi.strategies.Strategy; 7 | 8 | import java.rmi.RemoteException; 9 | import java.util.Arrays; 10 | import java.util.HashSet; 11 | import java.util.List; 12 | import java.util.Set; 13 | 14 | public class DomSelector extends AbstractSelector { 15 | 16 | public static Strategy strategy = new NoStrat(); 17 | public int currentIndex = 0; 18 | private Set decisions = new HashSet<>(); 19 | 20 | @Override 21 | public boolean startLaps(Lapse lapse) throws RemoteException { 22 | super.startLaps(lapse); 23 | return true; 24 | } 25 | 26 | @Override 27 | public Decision select(List> decisions) { 28 | this.decisions.addAll(decisions); 29 | return decisions.get(currentIndex); 30 | } 31 | 32 | @Override 33 | public boolean restartTest(Lapse lapse) { 34 | super.restartTest(lapse); 35 | if(currentIndex < decisions.size() - 1) { 36 | return true; 37 | } 38 | return false; 39 | } 40 | 41 | @Override 42 | public List getStrategies() { 43 | return Arrays.asList(strategy); 44 | } 45 | 46 | @Override 47 | public Set getSearchSpace() { 48 | return decisions; 49 | } 50 | 51 | @Override 52 | public String toString() { 53 | return super.toString() + " " + strategy; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/selector/MonoExplorerSelector.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.selector; 2 | 3 | import fr.inria.spirals.npefix.resi.context.Decision; 4 | import fr.inria.spirals.npefix.resi.context.Lapse; 5 | import fr.inria.spirals.npefix.resi.context.Location; 6 | import fr.inria.spirals.npefix.resi.strategies.NoStrat; 7 | import fr.inria.spirals.npefix.resi.strategies.Strategy; 8 | 9 | import java.rmi.RemoteException; 10 | import java.util.ArrayList; 11 | import java.util.Collection; 12 | import java.util.HashMap; 13 | import java.util.HashSet; 14 | import java.util.Iterator; 15 | import java.util.List; 16 | import java.util.Map; 17 | import java.util.Set; 18 | 19 | public class MonoExplorerSelector extends AbstractSelector { 20 | 21 | private Map> usedDecisions = new HashMap<>(); 22 | private Map> decisions = new HashMap<>(); 23 | private String currentTestKey; 24 | 25 | @Override 26 | public boolean startLaps(Lapse lapse) throws RemoteException { 27 | super.startLaps(lapse); 28 | this.currentTestKey = getCurrentLapse().getTestClassName() + "#" + getCurrentLapse().getTestName(); 29 | if (!usedDecisions.containsKey(currentTestKey)) { 30 | usedDecisions.put(currentTestKey, new HashSet()); 31 | } 32 | return true; 33 | } 34 | 35 | private void initDecision(List> decisions) { 36 | for (int i = 0; i < decisions.size(); i++) { 37 | Decision decision = decisions.get(i); 38 | if(!this.decisions.containsKey(decision.getLocation())) { 39 | this.decisions.put(decision.getLocation(), new HashSet()); 40 | } 41 | if(!this.decisions.get(decision.getLocation()).contains(decision)) { 42 | this.decisions.get(decision.getLocation()).add(decision); 43 | } 44 | } 45 | } 46 | 47 | @Override 48 | public List getStrategies() { 49 | ArrayList strategies = new ArrayList<>(getAllStrategies()); 50 | strategies.remove(new NoStrat()); 51 | return strategies; 52 | } 53 | 54 | @Override 55 | public Set getSearchSpace() { 56 | HashSet decisions = new HashSet<>(); 57 | Collection> values = this.decisions.values(); 58 | for (Iterator> iterator = values.iterator(); iterator 59 | .hasNext(); ) { 60 | Set decisionSet = iterator.next(); 61 | decisions.addAll(decisionSet); 62 | } 63 | return decisions; 64 | } 65 | 66 | @Override 67 | public synchronized Decision select(List> decisions) { 68 | try { 69 | initDecision(decisions); 70 | 71 | getCurrentLapse().putMetadata("strategy_selection", "exploration"); 72 | 73 | for (Decision decision : decisions) { 74 | if (!usedDecisions.get(currentTestKey).contains(decision)) { 75 | decision.setDecisionType(Decision.DecisionType.NEW); 76 | return decision; 77 | } 78 | } 79 | throw new NoMoreDecisionException("No more available decision"); 80 | } catch (Throwable e) { 81 | //e.printStackTrace(); 82 | throw e; 83 | } 84 | } 85 | 86 | @Override 87 | public boolean restartTest(Lapse lapse) { 88 | super.restartTest(lapse); 89 | if(lapse.getDecisions().isEmpty()) { 90 | return false; 91 | } 92 | usedDecisions.get(currentTestKey).add(lapse.getDecisions().get(0)); 93 | return false; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/selector/NoMoreDecisionException.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.selector; 2 | 3 | /** 4 | * Created by thomas on 11/10/16. 5 | */ 6 | public class NoMoreDecisionException extends RuntimeException { 7 | public NoMoreDecisionException(String s) { 8 | super(s); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/selector/RandomSelector.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.selector; 2 | 3 | import fr.inria.spirals.npefix.resi.RandomGenerator; 4 | import fr.inria.spirals.npefix.resi.context.Decision; 5 | import fr.inria.spirals.npefix.resi.context.Lapse; 6 | import fr.inria.spirals.npefix.resi.strategies.NoStrat; 7 | import fr.inria.spirals.npefix.resi.strategies.Strategy; 8 | 9 | import java.rmi.RemoteException; 10 | import java.util.ArrayList; 11 | import java.util.HashSet; 12 | import java.util.List; 13 | import java.util.Set; 14 | 15 | public class RandomSelector extends AbstractSelector { 16 | 17 | private Set decisions = new HashSet<>(); 18 | 19 | @Override 20 | public boolean startLaps(Lapse lapse) throws RemoteException { 21 | super.startLaps(lapse); 22 | return true; 23 | } 24 | 25 | @Override 26 | public List getStrategies() { 27 | ArrayList strategies = new ArrayList<>(getAllStrategies()); 28 | strategies.remove(new NoStrat()); 29 | return strategies; 30 | } 31 | 32 | /** 33 | * Select randomly a strategy 34 | * @return a strategy 35 | * @param decisions 36 | */ 37 | @Override 38 | public Decision select(List> decisions) { 39 | this.decisions.addAll(decisions); 40 | int maxValue = decisions.size(); 41 | return decisions.get(RandomGenerator.nextInt(1, maxValue)); 42 | } 43 | 44 | @Override 45 | public boolean restartTest(Lapse lapse) { 46 | super.restartTest(lapse); 47 | return false; 48 | //return !laps.getOracle().wasSuccessful(); 49 | } 50 | 51 | @Override 52 | public Set getSearchSpace() { 53 | return decisions; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/selector/RegressionSelector.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.selector; 2 | 3 | import fr.inria.spirals.npefix.resi.context.Lapse; 4 | 5 | import java.rmi.RemoteException; 6 | 7 | public interface RegressionSelector extends Selector { 8 | void setLapse(Lapse lapse) throws RemoteException; 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/selector/SafeMonoSelector.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.selector; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import fr.inria.spirals.npefix.resi.strategies.ReturnType; 7 | import fr.inria.spirals.npefix.resi.strategies.Strat3; 8 | import fr.inria.spirals.npefix.resi.strategies.Strat4; 9 | import fr.inria.spirals.npefix.resi.strategies.Strategy; 10 | 11 | /** 12 | * An implementation of MonoExplorerSelector that should only utilise strategies 13 | * 3 and 4. 14 | * @author benjamin 15 | * 16 | */ 17 | 18 | public class SafeMonoSelector extends MonoExplorerSelector{ 19 | 20 | @Override 21 | public List getStrategies() { 22 | ArrayList strategies = new ArrayList<>(); 23 | strategies.add(new Strat3()); 24 | strategies.add(new Strat4(ReturnType.NULL)); 25 | strategies.add(new Strat4(ReturnType.VAR)); 26 | strategies.add(new Strat4(ReturnType.NEW)); 27 | strategies.add(new Strat4(ReturnType.VOID)); 28 | return strategies; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/selector/Selector.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.selector; 2 | 3 | import fr.inria.spirals.npefix.resi.context.Decision; 4 | import fr.inria.spirals.npefix.resi.context.Lapse; 5 | import fr.inria.spirals.npefix.resi.strategies.Strategy; 6 | 7 | import java.rmi.Remote; 8 | import java.rmi.RemoteException; 9 | import java.util.List; 10 | import java.util.Set; 11 | 12 | public interface Selector extends Remote { 13 | 14 | Decision select(List> decisions) throws RemoteException; 15 | 16 | boolean startLaps(Lapse lapse) throws RemoteException; 17 | 18 | boolean restartTest(Lapse lapse) throws RemoteException; 19 | 20 | List getStrategies() throws RemoteException; 21 | 22 | Set getSearchSpace() throws RemoteException; 23 | 24 | List getLapses() throws RemoteException; 25 | 26 | Lapse getCurrentLapse() throws RemoteException; 27 | 28 | Lapse updateCurrentLapse(Lapse updatedLapse) throws RemoteException; 29 | 30 | void reset() throws RemoteException; 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/strategies/ArrayReadFirst.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.strategies; 2 | 3 | import fr.inria.spirals.npefix.resi.context.Decision; 4 | import fr.inria.spirals.npefix.resi.context.Location; 5 | import fr.inria.spirals.npefix.resi.context.MethodContext; 6 | import fr.inria.spirals.npefix.resi.context.instance.Instance; 7 | import fr.inria.spirals.npefix.resi.context.instance.PrimitiveInstance; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * Replace null element by existing one 14 | * b.foo 15 | * @author bcornu 16 | * 17 | */ 18 | public class ArrayReadFirst extends AbstractStrategy { 19 | 20 | @Override 21 | public boolean collectData() { 22 | return true; 23 | } 24 | 25 | @Override 26 | public List> getSearchSpace(Object array, Class clazz, Location location, MethodContext context) { 27 | List> output = new ArrayList<>(); 28 | Instance instance = new PrimitiveInstance(1); 29 | output.add(new Decision<>(this, location, instance, clazz)); 30 | return output; 31 | } 32 | 33 | @Override 34 | public boolean isCompatibleAction(ACTION action) { 35 | return action.equals(ACTION.arrayAccess); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/strategies/ArrayReadLast.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.strategies; 2 | 3 | import fr.inria.spirals.npefix.resi.context.Decision; 4 | import fr.inria.spirals.npefix.resi.context.Location; 5 | import fr.inria.spirals.npefix.resi.context.MethodContext; 6 | import fr.inria.spirals.npefix.resi.context.instance.ArrayReadInstance; 7 | import fr.inria.spirals.npefix.resi.context.instance.Instance; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * Replace null element by existing one 14 | * b.foo 15 | * @author bcornu 16 | * 17 | */ 18 | public class ArrayReadLast extends AbstractStrategy { 19 | 20 | @Override 21 | public boolean collectData() { 22 | return true; 23 | } 24 | 25 | @Override 26 | public List> getSearchSpace(Object array, Class clazz, Location location, MethodContext context) { 27 | List> output = new ArrayList<>(); 28 | Instance instance = new ArrayReadInstance("", 0); 29 | output.add(new Decision<>(this, location, instance, clazz)); 30 | return output; 31 | } 32 | 33 | @Override 34 | public boolean isCompatibleAction(ACTION action) { 35 | return action.equals(ACTION.arrayAccess); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/strategies/ArrayReadReturnNull.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.strategies; 2 | 3 | import fr.inria.spirals.npefix.resi.context.Decision; 4 | import fr.inria.spirals.npefix.resi.context.Location; 5 | import fr.inria.spirals.npefix.resi.context.MethodContext; 6 | import fr.inria.spirals.npefix.resi.context.instance.Instance; 7 | import fr.inria.spirals.npefix.resi.context.instance.PrimitiveInstance; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * Replace null element by existing one 14 | * b.foo 15 | * @author bcornu 16 | * 17 | */ 18 | public class ArrayReadReturnNull extends AbstractStrategy { 19 | 20 | @Override 21 | public boolean collectData() { 22 | return true; 23 | } 24 | 25 | @Override 26 | public List> getSearchSpace(Object value, 27 | Class clazz, Location location, MethodContext context) { 28 | List> output = new ArrayList<>(); 29 | Instance instance = new PrimitiveInstance(null); 30 | output.add(new Decision<>(this, location, instance, clazz)); 31 | return output; 32 | } 33 | 34 | @Override 35 | public boolean isCompatibleAction(ACTION action) { 36 | return action.equals(ACTION.arrayAccess); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/strategies/NoStrat.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.strategies; 2 | 3 | import fr.inria.spirals.npefix.resi.context.Decision; 4 | import fr.inria.spirals.npefix.resi.context.Location; 5 | import fr.inria.spirals.npefix.resi.context.MethodContext; 6 | 7 | import java.util.Collections; 8 | import java.util.List; 9 | 10 | public class NoStrat extends AbstractStrategy { 11 | 12 | @Override 13 | public boolean isCompatibleAction(ACTION action) { 14 | return false; 15 | } 16 | 17 | @Override 18 | public List> getSearchSpace(Object value, 19 | Class clazz, 20 | Location location, 21 | MethodContext context) { 22 | return Collections.EMPTY_LIST; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/strategies/ReturnType.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.strategies; 2 | 3 | public enum ReturnType { 4 | NULL, NEW, VAR, VOID 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/strategies/Strat1.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.strategies; 2 | 3 | import fr.inria.spirals.npefix.resi.context.Decision; 4 | import fr.inria.spirals.npefix.resi.context.Location; 5 | import fr.inria.spirals.npefix.resi.context.MethodContext; 6 | import fr.inria.spirals.npefix.resi.context.instance.Instance; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Iterator; 10 | import java.util.List; 11 | import java.util.Map; 12 | import java.util.Set; 13 | 14 | /** 15 | * Replace null element by existing one 16 | * b.foo 17 | * @author bcornu 18 | * 19 | */ 20 | public abstract class Strat1 extends AbstractStrategy { 21 | 22 | @Override 23 | public boolean collectData() { 24 | return true; 25 | } 26 | 27 | @Override 28 | public List> getSearchSpace(Object value, 29 | Class clazz, Location location, MethodContext context) { 30 | List> output = new ArrayList<>(); 31 | Map> instances = obtain(clazz); 32 | Set strings = instances.keySet(); 33 | for (Iterator iterator = strings.iterator(); iterator 34 | .hasNext(); ) { 35 | String key = iterator.next(); 36 | Decision decision = new Decision<>(this, location, instances.get(key), clazz); 37 | output.add(decision); 38 | } 39 | return output; 40 | } 41 | 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/strategies/Strat1A.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.strategies; 2 | 3 | /** 4 | * b.foo 5 | * @author bcornu 6 | * 7 | */ 8 | public class Strat1A extends Strat1 { 9 | @Override 10 | public boolean isCompatibleAction(ACTION action) { 11 | return action.equals(ACTION.isCalled); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/strategies/Strat1B.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.strategies; 2 | 3 | /** 4 | * a=b 5 | * @author bcornu 6 | * 7 | */ 8 | public class Strat1B extends Strat1 { 9 | 10 | @Override 11 | public boolean isCompatibleAction(ACTION action) { 12 | return action.equals(ACTION.beforeCalled); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/strategies/Strat2.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.strategies; 2 | 3 | import fr.inria.spirals.npefix.resi.context.Decision; 4 | import fr.inria.spirals.npefix.resi.context.Location; 5 | import fr.inria.spirals.npefix.resi.context.MethodContext; 6 | import fr.inria.spirals.npefix.resi.context.instance.Instance; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Collections; 10 | import java.util.List; 11 | 12 | /** 13 | * new A.foo 14 | * @author bcornu 15 | * 16 | */ 17 | public abstract class Strat2 extends AbstractStrategy { 18 | 19 | @Override 20 | public List> getSearchSpace(Object value, 21 | Class clazz, 22 | Location location, 23 | MethodContext context) { 24 | List> output = new ArrayList<>(); 25 | List> instances = initNotNull(clazz); 26 | Collections.sort(instances); 27 | for (int i = 0; i < instances.size(); i++) { 28 | Instance instance = instances.get(i); 29 | Decision decision = new Decision<>(this, location, instance, clazz); 30 | output.add(decision); 31 | } 32 | return output; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/strategies/Strat2A.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.strategies; 2 | 3 | /** 4 | * new A.foo 5 | * @author bcornu 6 | * 7 | */ 8 | public class Strat2A extends Strat2 { 9 | 10 | @Override 11 | public boolean isCompatibleAction(ACTION action) { 12 | return action.equals(ACTION.isCalled); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/strategies/Strat2B.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.strategies; 2 | 3 | /** 4 | * a=new A 5 | * @author bcornu 6 | * 7 | */ 8 | public class Strat2B extends Strat2 { 9 | 10 | @Override 11 | public boolean isCompatibleAction(ACTION action) { 12 | return action.equals(ACTION.beforeCalled); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/strategies/Strat3.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.strategies; 2 | 3 | import fr.inria.spirals.npefix.resi.context.Decision; 4 | import fr.inria.spirals.npefix.resi.context.Location; 5 | import fr.inria.spirals.npefix.resi.context.MethodContext; 6 | import fr.inria.spirals.npefix.resi.context.instance.PrimitiveInstance; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | /** 12 | * if != null 13 | * @author bcornu 14 | * 15 | */ 16 | public class Strat3 extends AbstractStrategy { 17 | 18 | @Override 19 | public boolean isCompatibleAction(ACTION action) { 20 | return action.equals(ACTION.beforeDeref); 21 | } 22 | 23 | @Override 24 | public List> getSearchSpace(Object value, 25 | Class clazz, 26 | Location location, 27 | MethodContext context) { 28 | List> output = new ArrayList<>(); 29 | output.add(new Decision(this, location, new PrimitiveInstance(false), boolean.class)); 30 | return output; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/strategies/Strat4.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.strategies; 2 | 3 | import fr.inria.spirals.npefix.resi.context.ConstructorContext; 4 | import fr.inria.spirals.npefix.resi.context.Decision; 5 | import fr.inria.spirals.npefix.resi.context.Location; 6 | import fr.inria.spirals.npefix.resi.context.MethodContext; 7 | import fr.inria.spirals.npefix.resi.context.instance.Instance; 8 | import fr.inria.spirals.npefix.resi.context.instance.PrimitiveInstance; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import java.util.Map; 13 | import java.util.Set; 14 | 15 | /** 16 | * return null 17 | * @author bcornu 18 | * 19 | */ 20 | public class Strat4 extends AbstractStrategy { 21 | 22 | private ReturnType returnType; 23 | 24 | public Strat4(ReturnType returnType) { 25 | this.returnType = returnType; 26 | } 27 | 28 | @Override 29 | public boolean collectData() { 30 | return returnType.equals(ReturnType.VAR); 31 | } 32 | 33 | 34 | @Override 35 | public boolean isCompatibleAction(ACTION action) { 36 | return action.equals(ACTION.isCalled) || action.equals(ACTION.beforeDeref) || action.equals(ACTION.tryRepair); 37 | } 38 | 39 | @Override 40 | public List> getSearchSpace(Object value, 41 | Class clazz, 42 | Location location, 43 | MethodContext context) { 44 | clazz = context.getMethodType(); 45 | 46 | List> output = new ArrayList<>(); 47 | if (context instanceof ConstructorContext) { 48 | // constructor don't have expected return 49 | if (returnType == ReturnType.VOID) { 50 | output.add(new Decision(this, location, new PrimitiveInstance(null))); 51 | } 52 | return output; 53 | } 54 | if (clazz == null) { 55 | return output; 56 | } 57 | switch (returnType) { 58 | case VOID: 59 | if(void.class.equals(clazz)) { 60 | output.add(new Decision(this, location, new PrimitiveInstance(null), void.class)); 61 | } 62 | break; 63 | case NULL: 64 | if(!clazz.isPrimitive()) { 65 | output.add(new Decision(this, location, new PrimitiveInstance(null), clazz)); 66 | } 67 | break; 68 | case NEW: 69 | List> instances = initNotNull(clazz); 70 | for (int i = 0; i < instances.size(); i++) { 71 | Instance instance = instances.get(i); 72 | Decision decision = new Decision<>(this, location, instance, clazz); 73 | output.add(decision); 74 | } 75 | break; 76 | case VAR: 77 | Map> variables = obtain(clazz); 78 | Set strings = variables.keySet(); 79 | for (String key : strings) { 80 | Decision decision = new Decision<>(this, location, 81 | variables.get(key), clazz); 82 | output.add(decision); 83 | } 84 | break; 85 | } 86 | return output; 87 | } 88 | 89 | public ReturnType getReturnType() { 90 | return returnType; 91 | } 92 | 93 | @Override 94 | public int hashCode() { 95 | return this.getClass().getSimpleName().hashCode(); 96 | } 97 | 98 | @Override 99 | public boolean equals(Object obj) { 100 | return super.equals(obj) && returnType.equals(((Strat4)obj).returnType); 101 | } 102 | 103 | @Override 104 | public String toString() { 105 | return super.toString() + " " + returnType.name(); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/resi/strategies/Strategy.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.resi.strategies; 2 | 3 | import fr.inria.spirals.npefix.resi.context.Decision; 4 | import fr.inria.spirals.npefix.resi.context.Location; 5 | import fr.inria.spirals.npefix.resi.context.MethodContext; 6 | 7 | import java.io.Serializable; 8 | import java.util.List; 9 | 10 | public interface Strategy extends Comparable, Serializable{ 11 | 12 | enum ACTION implements Serializable { 13 | // initClass globally a variable 14 | beforeCalled, 15 | // 16 | isCalled, 17 | // skipLine 18 | beforeDeref, 19 | // 20 | arrayAccess, 21 | // 22 | tryRepair 23 | } 24 | 25 | boolean isCompatibleAction(ACTION action); 26 | 27 | boolean collectData(); 28 | 29 | List> getSearchSpace(Object value, Class clazz, Location location, MethodContext context); 30 | 31 | String getPatch (Decision decision); 32 | 33 | String getName(); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/transformer/processors/ArrayRead.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.transformer.processors; 2 | 3 | import fr.inria.spirals.npefix.resi.CallChecker; 4 | import spoon.reflect.code.CtArrayRead; 5 | import spoon.reflect.code.CtAssignment; 6 | import spoon.reflect.code.CtInvocation; 7 | import spoon.reflect.code.CtLiteral; 8 | 9 | /** 10 | * Encapsulate array access in our framework 11 | */ 12 | public class ArrayRead extends spoon.processing.AbstractProcessor { 13 | @Override 14 | public boolean isToBeProcessed(CtArrayRead candidate) { 15 | if (candidate.getParent() instanceof CtAssignment) { 16 | if (((CtAssignment) candidate.getParent()).getAssigned() == candidate) { 17 | return false; 18 | } 19 | } 20 | return super.isToBeProcessed(candidate); 21 | } 22 | 23 | @Override 24 | public void process(CtArrayRead e) { 25 | CtLiteral lineNumber = getFactory().Code().createLiteral(e.getPosition().getLine()); 26 | CtLiteral sourceStart = getFactory().Code().createLiteral(e.getPosition().getSourceStart()); 27 | CtLiteral sourceEnd = getFactory().Code().createLiteral(e.getPosition().getSourceEnd()); 28 | 29 | CtInvocation arrayAccess = ProcessorUtility.createStaticCall(getFactory(), 30 | CallChecker.class, 31 | "arrayAccess", 32 | e.getTarget().clone(), 33 | e.getIndexExpression(), 34 | ProcessorUtility.createCtTypeElement(e.getType()), 35 | lineNumber, 36 | sourceStart, 37 | sourceEnd); 38 | e.replace(arrayAccess); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/transformer/processors/ConstructorTryCatchRepair.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.transformer.processors; 2 | 3 | import fr.inria.spirals.npefix.resi.CallChecker; 4 | import spoon.reflect.code.CtBlock; 5 | import spoon.reflect.code.CtCatch; 6 | import spoon.reflect.code.CtCatchVariable; 7 | import spoon.reflect.code.CtExpression; 8 | import spoon.reflect.code.CtInvocation; 9 | import spoon.reflect.code.CtLocalVariable; 10 | import spoon.reflect.code.CtTry; 11 | import spoon.reflect.code.CtVariableAccess; 12 | import spoon.reflect.declaration.CtConstructor; 13 | import spoon.reflect.declaration.CtField; 14 | import spoon.reflect.declaration.CtType; 15 | import spoon.reflect.declaration.ModifierKind; 16 | import spoon.reflect.reference.CtExecutableReference; 17 | 18 | import java.util.Date; 19 | import java.util.List; 20 | 21 | /** 22 | * Created by Benjamin DANGLOT 23 | * benjamin.danglot@inria.fr 24 | * on 11/07/17 25 | */ 26 | @SuppressWarnings("all") 27 | public class ConstructorTryCatchRepair extends ConstructorEncapsulation { 28 | 29 | @Override 30 | public void processingDone() { 31 | System.out.println("ConstructorTryCatchRepair # Constructor: " + contructor + " in " + (new Date().getTime() - start.getTime()) + "ms"); 32 | } 33 | 34 | @Override 35 | protected CtTry createTry( 36 | CtConstructor ctConstructor, 37 | CtLocalVariable methodVar) { 38 | 39 | CtCatchVariable parameter = getFactory().Code().createCatchVariable(getFactory().Type().createReference(RuntimeException.class), "_bcornu_return_t"); 40 | parameter.setPosition(methodVar.getPosition()); 41 | 42 | CtCatch localCatch = getFactory().Core().createCatch(); 43 | localCatch.setParameter(parameter); 44 | localCatch.setBody(getFactory().Core().createBlock()); 45 | 46 | CtVariableAccess methodAccess = getFactory().createVariableRead(); 47 | methodAccess.setVariable(methodVar.getReference()); 48 | 49 | CtExpression typeMethod = ProcessorUtility.createCtTypeElement(getFactory().Type().voidPrimitiveType()); 50 | 51 | final CtInvocation invocation = ProcessorUtility.createStaticCall(getFactory(), 52 | CallChecker.class, 53 | "isToCatch", 54 | getFactory().createVariableRead().setVariable(parameter.getReference()), 55 | typeMethod 56 | ); 57 | localCatch.getBody().addStatement(invocation); 58 | 59 | localCatch.setPosition(methodVar.getPosition()); 60 | 61 | CtExecutableReference executableRef = getFactory().Core().createExecutableReference(); 62 | executableRef.setSimpleName("methodEnd"); 63 | 64 | CtInvocation invoc = getFactory().Core().createInvocation(); 65 | invoc.setExecutable(executableRef); 66 | invoc.setTarget(methodAccess); 67 | invoc.setPosition(methodVar.getPosition()); 68 | CtBlock finalizer = getFactory().Core().createBlock(); 69 | finalizer.addStatement(invoc); 70 | 71 | CtTry e = getFactory().Core().createTry(); 72 | boolean hasFinal = false; 73 | 74 | List fields = ctConstructor.getParent(CtType.class).getFields(); 75 | for (CtField field : fields) { 76 | hasFinal |= field.hasModifier(ModifierKind.FINAL) && field.getDefaultExpression() == null; 77 | } 78 | if (!hasFinal) { 79 | e.addCatcher(localCatch); 80 | } 81 | e.setFinalizer(finalizer); 82 | e.setPosition(methodVar.getPosition()); 83 | 84 | return e; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/transformer/processors/ForceNullInit.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.transformer.processors; 2 | 3 | import fr.inria.spirals.npefix.resi.CallChecker; 4 | import spoon.processing.AbstractProcessor; 5 | import spoon.reflect.code.CtExpression; 6 | import spoon.reflect.code.CtForEach; 7 | import spoon.reflect.code.CtInvocation; 8 | import spoon.reflect.code.CtLambda; 9 | import spoon.reflect.code.CtLocalVariable; 10 | import spoon.reflect.code.CtNewClass; 11 | import spoon.reflect.code.CtVariableRead; 12 | import spoon.reflect.declaration.ModifierKind; 13 | import spoon.reflect.reference.CtVariableReference; 14 | import spoon.reflect.visitor.filter.TypeFilter; 15 | 16 | import java.util.Date; 17 | import java.util.List; 18 | 19 | import static fr.inria.spirals.npefix.transformer.processors.ProcessorUtility.createCtTypeElement; 20 | 21 | /** 22 | * @author bcornu 23 | * 24 | */ 25 | @SuppressWarnings("all") 26 | public class ForceNullInit extends AbstractProcessor { 27 | 28 | private Date start; 29 | 30 | @Override 31 | public void init() { 32 | this.start = new Date(); 33 | } 34 | 35 | @Override 36 | public void processingDone() { 37 | System.out.println("ForceNullInit in " + (new Date().getTime() - start.getTime()) + "ms"); 38 | } 39 | 40 | @Override 41 | public boolean isToBeProcessed(CtLocalVariable element) { 42 | if (element.getDefaultExpression()!= null 43 | || element.getParent() instanceof CtForEach) 44 | return false; 45 | if (element.hasModifier(ModifierKind.FINAL) && variableInNewClass(element)){ 46 | return false; 47 | } 48 | if(element.getParent(CtLambda.class) != null) { 49 | return false; 50 | } 51 | return super.isToBeProcessed(element); 52 | } 53 | 54 | @Override 55 | public void process(CtLocalVariable element) { 56 | if(element.hasModifier(ModifierKind.FINAL)){ 57 | element.removeModifier(ModifierKind.FINAL); 58 | } 59 | 60 | CtExpression arg = createCtTypeElement(element.getType()); 61 | if(arg == null) { 62 | return; 63 | } 64 | 65 | CtInvocation invoc = ProcessorUtility.createStaticCall(getFactory(), CallChecker.class, "init", arg); 66 | element.setDefaultExpression(invoc); 67 | invoc.setPosition(element.getPosition()); 68 | invoc.setType(element.getType()); 69 | } 70 | 71 | private boolean variableInNewClass(final CtLocalVariable e) { 72 | List elements = e.getParent().getElements( 73 | new TypeFilter(CtVariableRead.class) { 74 | @Override 75 | public boolean matches(CtVariableRead element) { 76 | CtVariableReference variable = element.getVariable(); 77 | if (variable == null) { 78 | return false; 79 | } 80 | if (e.equals(variable.getDeclaration())) { 81 | return true; 82 | } 83 | return false; 84 | } 85 | }); 86 | CtNewClass refParent = e 87 | .getParent(new TypeFilter(CtNewClass.class)); 88 | for (int i = 0; i < elements.size(); i++) { 89 | CtVariableRead ctVariableRead = elements.get(i); 90 | CtNewClass parent = ctVariableRead 91 | .getParent(new TypeFilter(CtNewClass.class)); 92 | if (parent != null && parent != refParent) { 93 | return true; 94 | } 95 | } 96 | return false; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/transformer/processors/IfSplitter.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.transformer.processors; 2 | 3 | import spoon.processing.AbstractProcessor; 4 | import spoon.reflect.code.BinaryOperatorKind; 5 | import spoon.reflect.code.CtBinaryOperator; 6 | import spoon.reflect.code.CtBlock; 7 | import spoon.reflect.code.CtExpression; 8 | import spoon.reflect.code.CtIf; 9 | import spoon.reflect.code.CtStatement; 10 | 11 | /** 12 | * Split if condition into several if in order to add check not null before each section of the condition 13 | */ 14 | public class IfSplitter extends AbstractProcessor{ 15 | @Override 16 | public boolean isToBeProcessed(CtIf candidate) { 17 | if(!super.isToBeProcessed(candidate)) { 18 | return false; 19 | } 20 | CtExpression condition = candidate.getCondition(); 21 | if(condition instanceof CtBinaryOperator) { 22 | BinaryOperatorKind kind = ((CtBinaryOperator) condition).getKind(); 23 | return (kind.equals(BinaryOperatorKind.AND)) || kind.equals(BinaryOperatorKind.OR); 24 | } 25 | return false; 26 | } 27 | 28 | @Override 29 | public void process(CtIf ctIf) { 30 | CtBinaryOperator condition = (CtBinaryOperator) ctIf.getCondition(); 31 | CtExpression leftHandOperand = condition.getLeftHandOperand(); 32 | CtExpression rightHandOperand = condition.getRightHandOperand(); 33 | BinaryOperatorKind kind = condition.getKind(); 34 | 35 | CtIf anIf = getFactory().Core().createIf(); 36 | anIf.setPosition(ctIf.getPosition()); 37 | anIf.setParent(ctIf.getParent()); 38 | ctIf.replace(anIf); 39 | anIf.setCondition(leftHandOperand); 40 | ctIf.setCondition(rightHandOperand); 41 | CtStatement wrappedIf = wrapBlock(ctIf); 42 | if(kind.equals(BinaryOperatorKind.AND)) { 43 | CtStatement ctStatement = wrapBlock(getFactory().Core().clone(ctIf.getElseStatement())); 44 | if (ctStatement != null) { 45 | ctStatement.setParent(anIf); 46 | } 47 | anIf.setThenStatement(wrappedIf); 48 | anIf.setElseStatement(ctStatement); 49 | } else { 50 | CtStatement ctStatement = wrapBlock(getFactory().Core().clone(ctIf.getThenStatement())); 51 | if (ctStatement != null) { 52 | ctStatement.setParent(anIf); 53 | } 54 | anIf.setThenStatement(ctStatement); 55 | anIf.setElseStatement(wrappedIf); 56 | } 57 | 58 | 59 | if(isToBeProcessed(anIf)) { 60 | process(anIf); 61 | } 62 | } 63 | 64 | private CtStatement wrapBlock(CtStatement element) { 65 | if(element == null) { 66 | return null; 67 | } 68 | if(element instanceof CtBlock) { 69 | return element; 70 | } 71 | CtBlock ctBlock = getFactory().Code().createCtBlock(element); 72 | ctBlock.setPosition(element.getPosition()); 73 | ctBlock.setParent(element.getParent()); 74 | element.setParent(ctBlock); 75 | return ctBlock; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/transformer/processors/TryCatchRepair.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.transformer.processors; 2 | 3 | import fr.inria.spirals.npefix.resi.CallChecker; 4 | import spoon.reflect.code.CtBlock; 5 | import spoon.reflect.code.CtCatch; 6 | import spoon.reflect.code.CtCatchVariable; 7 | import spoon.reflect.code.CtExpression; 8 | import spoon.reflect.code.CtInvocation; 9 | import spoon.reflect.code.CtLocalVariable; 10 | import spoon.reflect.code.CtReturn; 11 | import spoon.reflect.code.CtTry; 12 | import spoon.reflect.code.CtVariableAccess; 13 | import spoon.reflect.declaration.CtMethod; 14 | import spoon.reflect.reference.CtExecutableReference; 15 | import spoon.reflect.reference.CtTypeReference; 16 | 17 | import java.util.Date; 18 | 19 | /** 20 | * Created by Benjamin DANGLOT 21 | * benjamin.danglot@inria.fr 22 | * on 11/07/17 23 | */ 24 | @SuppressWarnings("all") 25 | public class TryCatchRepair extends MethodEncapsulation { 26 | 27 | @Override 28 | public void processingDone() { 29 | System.out.println("TryCatchRepair # Method: " + MethodEncapsulation.methodNumber + " in " + (new Date().getTime() - start.getTime()) + "ms"); 30 | } 31 | 32 | @Override 33 | protected CtTry createTry(CtMethod ctMethode, 34 | CtLocalVariable methodVar, CtTypeReference tmpref) { 35 | 36 | CtCatchVariable parameter = getFactory().Code().createCatchVariable(getFactory().Type().createReference(RuntimeException.class), "_bcornu_return_t"); 37 | parameter.setPosition(methodVar.getPosition()); 38 | 39 | CtCatch localCatch = getFactory().Core().createCatch(); 40 | localCatch.setParameter(parameter); 41 | localCatch.setBody(getFactory().Core().createBlock()); 42 | 43 | CtVariableAccess methodAccess = getFactory().createVariableRead(); 44 | methodAccess.setVariable(methodVar.getReference()); 45 | 46 | CtReturn ret = getFactory().Core().createReturn(); 47 | ret.setPosition(methodVar.getPosition()); 48 | 49 | CtExpression typeMethod = ProcessorUtility.createCtTypeElement(tmpref); 50 | 51 | final CtInvocation invocation = ProcessorUtility.createStaticCall(getFactory(), 52 | CallChecker.class, 53 | "isToCatch", 54 | getFactory().createVariableRead().setVariable(parameter.getReference()), 55 | typeMethod 56 | ); 57 | 58 | 59 | 60 | CtTypeReference variableType = tmpref; 61 | if(tmpref.equals(getFactory().Type().VOID_PRIMITIVE)){ 62 | variableType = getFactory().Code().createCtTypeReference(Object.class); 63 | localCatch.getBody().addStatement(invocation); 64 | } else { 65 | invocation.addTypeCast(variableType.box()); 66 | ret.setReturnedExpression(invocation); 67 | } 68 | localCatch.getBody().addStatement(ret); 69 | 70 | localCatch.setPosition(methodVar.getPosition()); 71 | 72 | CtExecutableReference executableRef = getFactory().Core().createExecutableReference(); 73 | executableRef.setSimpleName("methodEnd"); 74 | 75 | CtInvocation invoc = getFactory().Core().createInvocation(); 76 | invoc.setExecutable(executableRef); 77 | invoc.setTarget(methodAccess); 78 | invoc.setPosition(methodVar.getPosition()); 79 | CtBlock finalizer = getFactory().Core().createBlock(); 80 | finalizer.addStatement(invoc); 81 | 82 | CtTry e = getFactory().Core().createTry(); 83 | e.addCatcher(localCatch); 84 | e.setFinalizer(finalizer); 85 | e.setPosition(methodVar.getPosition()); 86 | 87 | return e; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/transformer/processors/VariableFor.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.transformer.processors; 2 | 3 | import fr.inria.spirals.npefix.resi.CallChecker; 4 | import spoon.processing.AbstractProcessor; 5 | import spoon.reflect.code.CtBlock; 6 | import spoon.reflect.code.CtExpression; 7 | import spoon.reflect.code.CtFor; 8 | import spoon.reflect.code.CtForEach; 9 | import spoon.reflect.code.CtIf; 10 | import spoon.reflect.code.CtInvocation; 11 | import spoon.reflect.code.CtLiteral; 12 | import spoon.reflect.code.CtStatement; 13 | import spoon.reflect.code.CtVariableRead; 14 | import spoon.reflect.declaration.CtElement; 15 | import spoon.reflect.declaration.CtMethod; 16 | import spoon.reflect.reference.CtArrayTypeReference; 17 | import spoon.reflect.reference.CtTypeReference; 18 | 19 | import java.util.Date; 20 | 21 | /** 22 | * Verify that a variable is not null in a loop or a foreach loop if(varA !=null) for(a in varA) 23 | */ 24 | public class VariableFor extends AbstractProcessor> { 25 | 26 | private Date start; 27 | 28 | @Override 29 | public void init() { 30 | this.start = new Date(); 31 | } 32 | 33 | @Override 34 | public void processingDone() { 35 | System.out.println("VariableFor in " + (new Date().getTime() - start.getTime()) + "ms"); 36 | } 37 | 38 | @Override 39 | public boolean isToBeProcessed(CtVariableRead element) { 40 | CtElement parent = element.getParent(); 41 | if(!(parent instanceof CtForEach 42 | || parent instanceof CtFor)) 43 | return false; 44 | 45 | if(element.getVariable().getDeclaration() == null) { 46 | System.out.println(element.getVariable().getDeclaration()); 47 | return false; 48 | } 49 | 50 | // for variable declared in a for and used oin the declaration ex: for(boolean loop = true;loop;) 51 | if(element.getVariable().getDeclaration().getParent().equals(element.getParent())) { 52 | return false; 53 | } 54 | if (element.getMetadata("notnull") != null) { 55 | return false; 56 | } 57 | return true; 58 | } 59 | 60 | @Override 61 | public void process(CtVariableRead element) { 62 | CtElement parent = element.getParent(); 63 | 64 | CtLiteral lineNumber = getFactory().Code().createLiteral(element.getPosition().getLine()); 65 | CtLiteral sourceStart = getFactory().Code().createLiteral(element.getPosition().getSourceStart()); 66 | CtLiteral sourceEnd = getFactory().Code().createLiteral(element.getPosition().getSourceEnd()); 67 | 68 | CtMethod ctMethod = element.getParent(CtMethod.class); 69 | 70 | CtExpression methodType; 71 | if(ctMethod != null) { 72 | CtTypeReference tmpref = getFactory().Core().clone(ctMethod.getType()); 73 | if(tmpref instanceof CtArrayTypeReference 74 | && ((CtArrayTypeReference)tmpref).getComponentType() != null){ 75 | ((CtArrayTypeReference)tmpref).getComponentType().getActualTypeArguments().clear(); 76 | } 77 | methodType = ProcessorUtility.createCtTypeElement(tmpref); 78 | } else { 79 | methodType = getFactory().Code().createLiteral(null); 80 | } 81 | 82 | CtInvocation ifInvoc = ProcessorUtility.createStaticCall(getFactory(), 83 | CallChecker.class, 84 | "beforeDeref", 85 | element, 86 | methodType, 87 | lineNumber, 88 | sourceStart, 89 | sourceEnd); 90 | ifInvoc.setPosition(element.getPosition()); 91 | 92 | CtIf encaps = getFactory().Core().createIf(); 93 | encaps.setCondition(ifInvoc); 94 | encaps.setPosition(element.getPosition()); 95 | 96 | CtBlock thenBloc = getFactory().Core().createBlock(); 97 | 98 | ((CtStatement) parent).replace(encaps); 99 | encaps.setThenStatement(thenBloc); 100 | thenBloc.addStatement((CtStatement) parent); 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/transformer/utils/CtThrowGenerated.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.transformer.utils; 2 | 3 | import spoon.support.reflect.code.CtThrowImpl; 4 | 5 | public class CtThrowGenerated extends CtThrowImpl{ 6 | 7 | /** 8 | * generated 9 | */ 10 | private static final long serialVersionUID = 5737541619010329164L; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/fr/inria/spirals/npefix/transformer/utils/CtTryGenerated.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.transformer.utils; 2 | 3 | import spoon.support.reflect.code.CtTryImpl; 4 | 5 | public class CtTryGenerated extends CtTryImpl { 6 | 7 | /** 8 | * 9 | */ 10 | private static final long serialVersionUID = 1L; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/utils/org/eclipse/core/internal/localstore/ILocalStoreConstants.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2000, 2005 IBM Corporation and others. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v1.0 5 | * which accompanies this distribution, and is available at 6 | * http://www.eclipse.org/legal/epl-v10.html 7 | * 8 | * Contributors: 9 | * IBM Corporation - initial API and implementation 10 | *******************************************************************************/ 11 | package utils.org.eclipse.core.internal.localstore; 12 | 13 | public interface ILocalStoreConstants { 14 | 15 | /** Common constants for NPEFixExecution Store classes. */ 16 | public final static int SIZE_LASTMODIFIED = 8; 17 | public static final int SIZE_COUNTER = 1; 18 | public static final int SIZE_KEY_SUFFIX = SIZE_LASTMODIFIED + SIZE_COUNTER; 19 | 20 | /** constants for safe chunky streams */ 21 | 22 | // 40b18b8123bc00141a2596e7a393be1e 23 | public static final byte[] BEGIN_CHUNK = {64, -79, -117, -127, 35, -68, 0, 20, 26, 37, -106, -25, -93, -109, -66, 30}; 24 | 25 | // c058fbf323bc00141a51f38c7bbb77c6 26 | public static final byte[] END_CHUNK = {-64, 88, -5, -13, 35, -68, 0, 20, 26, 81, -13, -116, 123, -69, 119, -58}; 27 | 28 | /** chunk delimiter size */ 29 | // BEGIN_CHUNK and END_CHUNK must have the same length 30 | public static final int CHUNK_DELIMITER_SIZE = BEGIN_CHUNK.length; 31 | } -------------------------------------------------------------------------------- /src/main/java/utils/sacha/classloader/factory/ClassloaderFactory.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.classloader.factory; 2 | 3 | import utils.sacha.classloader.enrich.EnrichableClassloader; 4 | 5 | import java.net.MalformedURLException; 6 | import java.net.URL; 7 | import java.util.ArrayList; 8 | import java.util.Arrays; 9 | import java.util.List; 10 | 11 | public class ClassloaderFactory { 12 | 13 | public static EnrichableClassloader getEnrichableClassloader(){ 14 | String classPath = System.getProperty("java.class.path"); 15 | List urls = new ArrayList<>(); 16 | for (String classpathElement : splitClassPath(classPath)) { 17 | try { 18 | urls.add(new URL("file://"+classpathElement)); 19 | } catch (MalformedURLException e) { 20 | e.printStackTrace(); 21 | } 22 | } 23 | return new EnrichableClassloader(urls.toArray(new URL[0])); 24 | } 25 | 26 | private static List splitClassPath(String classPath) { 27 | final String separator = System.getProperty("path.separator"); 28 | return Arrays.asList(classPath.split(separator)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/finder/classes/ClassFinder.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.finder.classes; 2 | 3 | public interface ClassFinder { 4 | 5 | String[] getClasses(); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/finder/classes/impl/ClassloaderFinder.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.finder.classes.impl; 2 | 3 | import utils.sacha.finder.classes.ClassFinder; 4 | 5 | import java.io.File; 6 | import java.net.URL; 7 | import java.net.URLClassLoader; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | public class ClassloaderFinder implements ClassFinder { 12 | 13 | private URLClassLoader urlClassloader; 14 | public ClassloaderFinder(URLClassLoader urlClassloader) { 15 | this.urlClassloader = urlClassloader; 16 | } 17 | 18 | @Override 19 | public String[] getClasses() { 20 | List classes = new ArrayList<>(); 21 | for (URL url : urlClassloader.getURLs()) { 22 | if(new File(url.getPath()).isDirectory()) 23 | classes.addAll(utils.sacha.finder.classes.impl.SourceFolderFinder.getClassesLoc(new File(url.getPath()), null)); 24 | } 25 | return classes.toArray(new String[0]); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/finder/classes/impl/ClasspathFinder.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.finder.classes.impl; 2 | 3 | import utils.sacha.finder.classes.ClassFinder; 4 | 5 | import java.io.File; 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | import java.util.List; 9 | 10 | 11 | public class ClasspathFinder implements ClassFinder{ 12 | 13 | @Override 14 | public String[] getClasses() { 15 | String classPath = System.getProperty("java.class.path"); 16 | return findClassesInRoots(splitClassPath(classPath)).toArray(new String[0]); 17 | } 18 | 19 | private List splitClassPath(String classPath) { 20 | final String separator = System.getProperty("path.separator"); 21 | return Arrays.asList(classPath.split(separator)); 22 | } 23 | 24 | private List findClassesInRoots(List roots) { 25 | List classes = new ArrayList<>(); 26 | for (String root : roots) { 27 | if(new File(root).isDirectory()) 28 | classes.addAll(utils.sacha.finder.classes.impl.SourceFolderFinder.getClassesLoc(new File(root), null)); 29 | } 30 | return classes; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/finder/classes/impl/ProjectFinder.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.finder.classes.impl; 2 | 3 | import utils.sacha.classloader.enrich.EnrichableClassloader; 4 | import utils.sacha.finder.classes.ClassFinder; 5 | 6 | import java.io.File; 7 | import java.net.URL; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | public class ProjectFinder implements ClassFinder { 12 | 13 | private EnrichableClassloader urlClassloader; 14 | public ProjectFinder(EnrichableClassloader urlClassloader) { 15 | this.urlClassloader = urlClassloader; 16 | } 17 | 18 | @Override 19 | public String[] getClasses() { 20 | List classes = new ArrayList<>(); 21 | for (URL url : urlClassloader.getURLs()) { 22 | if(new File(url.getPath()).isDirectory()) 23 | classes.addAll(SourceFolderFinder.getClassesLoc(new File(url.getPath()), null)); 24 | } 25 | return classes.toArray(new String[0]); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/finder/classes/impl/SourceFolderFinder.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.finder.classes.impl; 2 | 3 | import utils.sacha.finder.classes.ClassFinder; 4 | 5 | import java.io.File; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | 10 | public class SourceFolderFinder implements ClassFinder { 11 | 12 | private String srcFolder; 13 | 14 | public SourceFolderFinder(String srcFolder) { 15 | this.srcFolder = srcFolder; 16 | } 17 | 18 | @Override 19 | public String[] getClasses() { 20 | return getClassesLoc(new File(srcFolder),null).toArray(new String[0]); 21 | } 22 | 23 | static List getClassesLoc(File testSrcFolder,String pack) { 24 | List classes = new ArrayList<>(); 25 | for (File file : testSrcFolder.listFiles()) { 26 | if(file.isDirectory()) 27 | classes.addAll(getClassesLoc(file, pack==null?file.getName():pack+'.'+file.getName())); 28 | else if(file.getName().endsWith(".java")){ 29 | String className= pack==null?file.getName():pack+'.'+file.getName(); 30 | className = className.substring(0, className.length()); 31 | classes.add(className); 32 | }else if(file.getName().endsWith(".class")){ 33 | String className= pack==null?file.getName():pack+'.'+file.getName(); 34 | className = className.substring(0, className.length()); 35 | classes.add(className); 36 | } 37 | } 38 | return classes; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/finder/filters/ClassFilter.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.finder.filters; 2 | 3 | public interface ClassFilter { 4 | boolean acceptClass(Class clazz); 5 | boolean acceptClassName(String className); 6 | boolean acceptInnerClass(); 7 | boolean searchInJars(); 8 | } -------------------------------------------------------------------------------- /src/main/java/utils/sacha/finder/filters/impl/AcceptAllFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @author Johannes Link (business@johanneslink.net) 3 | * 4 | * Published under GNU General Public License 2.0 (http://www.gnu.org/licenses/gpl.html) 5 | */ 6 | package utils.sacha.finder.filters.impl; 7 | 8 | import utils.sacha.finder.filters.ClassFilter; 9 | 10 | public class AcceptAllFilter implements ClassFilter { 11 | 12 | public boolean acceptClassName(String className) { 13 | return true; 14 | } 15 | 16 | public boolean acceptInnerClass() { 17 | return true; 18 | } 19 | 20 | public boolean acceptClass(Class clazz) { 21 | return true; 22 | } 23 | 24 | public boolean searchInJars() { 25 | return true; 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /src/main/java/utils/sacha/finder/filters/impl/TestFilter.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.finder.filters.impl; 2 | 3 | import junit.framework.TestCase; 4 | import org.junit.runner.RunWith; 5 | import utils.sacha.finder.filters.ClassFilter; 6 | import utils.sacha.finder.filters.utils.TestType; 7 | 8 | import java.lang.annotation.Annotation; 9 | import java.lang.reflect.Method; 10 | import java.lang.reflect.Modifier; 11 | import java.util.Arrays; 12 | 13 | 14 | /** 15 | * ClassTester implementation to retrieve JUnit4 test classes in the classpath. 16 | * You can specify if you want to include jar files in the search and you can 17 | * give a set of regex expression to specify the class names to include. 18 | * 19 | */ 20 | public class TestFilter implements ClassFilter { 21 | 22 | private final boolean searchInJars; 23 | 24 | private final TestType[] testTypes; 25 | 26 | public TestFilter() { 27 | this.searchInJars = true; 28 | this.testTypes = new TestType[]{TestType.JUNIT38_TEST_CLASSES,TestType.RUN_WITH_CLASSES,TestType.TEST_CLASSES}; 29 | } 30 | 31 | public TestFilter(boolean searchInJars) { 32 | this.searchInJars = searchInJars; 33 | this.testTypes = new TestType[]{TestType.JUNIT38_TEST_CLASSES,TestType.RUN_WITH_CLASSES,TestType.TEST_CLASSES}; 34 | } 35 | 36 | public TestFilter(TestType[] suiteTypes) { 37 | this.searchInJars = true; 38 | this.testTypes = suiteTypes; 39 | } 40 | 41 | public TestFilter(boolean searchInJars, 42 | TestType[] suiteTypes) { 43 | this.searchInJars = searchInJars; 44 | this.testTypes = suiteTypes; 45 | } 46 | 47 | public boolean acceptClass(Class clazz) { 48 | if (isInSuiteTypes(TestType.TEST_CLASSES)) { 49 | if (acceptTestClass(clazz)) { 50 | return true; 51 | } 52 | 53 | } 54 | if (isInSuiteTypes(TestType.JUNIT38_TEST_CLASSES)) { 55 | if (acceptJUnit38Test(clazz)) { 56 | return true; 57 | } 58 | } 59 | if (isInSuiteTypes(TestType.RUN_WITH_CLASSES)) { 60 | return acceptRunWithClass(clazz); 61 | } 62 | 63 | return false; 64 | } 65 | 66 | private boolean acceptJUnit38Test(Class clazz) { 67 | if (isAbstractClass(clazz)) { 68 | return false; 69 | } 70 | return TestCase.class.isAssignableFrom(clazz); 71 | } 72 | 73 | private boolean acceptRunWithClass(Class clazz) { 74 | return clazz.isAnnotationPresent(RunWith.class); 75 | } 76 | 77 | private boolean isInSuiteTypes(TestType testType) { 78 | return Arrays.asList(testTypes).contains(testType); 79 | } 80 | 81 | private boolean acceptTestClass(Class clazz) { 82 | if (isAbstractClass(clazz)) { 83 | return false; 84 | } 85 | try { 86 | for (Method method : clazz.getMethods()) { 87 | for (Annotation annotation : method.getAnnotations()) { 88 | if ("org.junit.Test".equals(annotation.annotationType().getName())) { 89 | return true; 90 | } 91 | } 92 | } 93 | } catch (NoClassDefFoundError ignore) { 94 | } 95 | return false; 96 | } 97 | 98 | private boolean isAbstractClass(Class clazz) { 99 | return (clazz.getModifiers() & Modifier.ABSTRACT) != 0; 100 | } 101 | 102 | public boolean acceptInnerClass() { 103 | return true; 104 | } 105 | 106 | public boolean searchInJars() { 107 | return searchInJars; 108 | } 109 | 110 | public boolean acceptClassName(String className) { 111 | return true; 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/finder/filters/utils/TestType.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.finder.filters.utils; 2 | 3 | public enum TestType { 4 | TEST_CLASSES, RUN_WITH_CLASSES, JUNIT38_TEST_CLASSES 5 | } -------------------------------------------------------------------------------- /src/main/java/utils/sacha/finder/main/Main.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.finder.main; 2 | 3 | import java.io.File; 4 | 5 | public abstract class Main { 6 | 7 | protected static String checkFolder(String testFolder) { 8 | if(testFolder.endsWith("/")||testFolder.endsWith("\\")) 9 | testFolder=testFolder.substring(0, testFolder.length()); 10 | 11 | File testSrcFolder = new File(testFolder); 12 | if(!testSrcFolder.exists() || !testSrcFolder.isDirectory() || !testSrcFolder.canRead()) 13 | throw new IllegalArgumentException("cannot found "+testFolder+" or is not a directory or is not readable"); 14 | 15 | return testFolder; 16 | 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/finder/main/TestClassFinder.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.finder.main; 2 | 3 | import utils.sacha.classloader.enrich.EnrichableClassloader; 4 | import utils.sacha.finder.classes.impl.ProjectFinder; 5 | import utils.sacha.finder.filters.impl.TestFilter; 6 | import utils.sacha.finder.processor.Processor; 7 | 8 | public class TestClassFinder{ 9 | 10 | private EnrichableClassloader urlClassloader; 11 | 12 | public TestClassFinder(EnrichableClassloader classloader) { 13 | this.urlClassloader=classloader; 14 | } 15 | 16 | public Class[] findTestClasses(){ 17 | return new Processor(new ProjectFinder(urlClassloader), new TestFilter()).process(); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/finder/main/TestInClasspath.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.finder.main; 2 | 3 | import utils.sacha.finder.classes.impl.ClasspathFinder; 4 | import utils.sacha.finder.filters.impl.TestFilter; 5 | import utils.sacha.finder.processor.Processor; 6 | 7 | public class TestInClasspath{ 8 | 9 | public Class[] find(){ 10 | return new Processor(new ClasspathFinder(), new TestFilter()).process(); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/finder/main/TestInFolder.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.finder.main; 2 | 3 | import utils.sacha.finder.classes.impl.SourceFolderFinder; 4 | import utils.sacha.finder.filters.impl.TestFilter; 5 | import utils.sacha.finder.processor.Processor; 6 | 7 | public class TestInFolder{ 8 | 9 | private String testFolder = null; 10 | 11 | public TestInFolder(String testFolder) { 12 | this.testFolder=testFolder; 13 | } 14 | 15 | public Class[] find(){ 16 | return new Processor(new SourceFolderFinder(testFolder), new TestFilter()).process(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/finder/main/TestInURLClassloader.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.finder.main; 2 | 3 | import utils.sacha.finder.classes.impl.ClassloaderFinder; 4 | import utils.sacha.finder.filters.impl.TestFilter; 5 | import utils.sacha.finder.processor.Processor; 6 | 7 | import java.net.URLClassLoader; 8 | 9 | public class TestInURLClassloader{ 10 | 11 | private URLClassLoader urlClassloader; 12 | 13 | public TestInURLClassloader(URLClassLoader classloader) { 14 | this.urlClassloader=classloader; 15 | } 16 | 17 | public Class[] find(){ 18 | return new Processor(new ClassloaderFinder(urlClassloader), new TestFilter()).process(); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/finder/main/TestMain.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.finder.main; 2 | 3 | import utils.sacha.finder.classes.impl.SourceFolderFinder; 4 | import utils.sacha.finder.filters.impl.TestFilter; 5 | import utils.sacha.finder.processor.Processor; 6 | 7 | public class TestMain extends Main{ 8 | 9 | public static Class[] findTest(String testFolder){ 10 | return getTestsClasses(checkFolder(testFolder)); 11 | } 12 | 13 | private static Class[] getTestsClasses(String testFolder) { 14 | return new Processor(new SourceFolderFinder(testFolder), new TestFilter()).process(); 15 | } 16 | 17 | 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/finder/processor/Processor.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.finder.processor; 2 | 3 | import utils.sacha.finder.classes.ClassFinder; 4 | import utils.sacha.finder.filters.ClassFilter; 5 | 6 | import java.io.File; 7 | import java.util.ArrayList; 8 | import java.util.Collections; 9 | import java.util.Comparator; 10 | import java.util.List; 11 | 12 | 13 | 14 | public class Processor { 15 | 16 | static final int CLASS_SUFFIX_LENGTH = ".class".length(); 17 | static final int JAVA_SUFFIX_LENGTH = ".java".length(); 18 | 19 | private final ClassFilter tester; 20 | private final ClassFinder finder; 21 | 22 | public Processor(ClassFinder finder, ClassFilter tester) { 23 | this.tester = tester; 24 | this.finder = finder; 25 | } 26 | 27 | public Class[] process() { 28 | List> classes = new ArrayList<>(); 29 | for (String fileName : finder.getClasses()) { 30 | String className; 31 | if(isJavaFile(fileName)){ 32 | className = classNameFromJava(fileName); 33 | }else 34 | if(isClassFile(fileName)) { 35 | className = classNameFromFile(fileName); 36 | }else continue; 37 | if (!tester.acceptClassName(className)) { 38 | continue; 39 | } 40 | if (!tester.acceptInnerClass() && isInnerClass(className)) { 41 | continue; 42 | } 43 | if(!className.contains("$")) 44 | try { 45 | Class clazz = Thread.currentThread().getContextClassLoader().loadClass(className); 46 | if (clazz.isLocalClass() || clazz.isAnonymousClass()) { 47 | continue; 48 | } 49 | if (tester.acceptClass(clazz)) { 50 | classes.add(clazz); 51 | } 52 | } catch (ClassNotFoundException cnfe) { 53 | try { 54 | ClassLoader tmp= Thread.currentThread().getContextClassLoader(); 55 | Class clazz = Class.forName(className,false,tmp); 56 | if (clazz.isLocalClass() || clazz.isAnonymousClass()) { 57 | continue; 58 | } 59 | if (tester.acceptClass(clazz)) { 60 | classes.add(clazz); 61 | } 62 | } catch (ClassNotFoundException cnfe2) { 63 | // cnfe2.printStackTrace(); 64 | } catch (NoClassDefFoundError ncdfe) { 65 | // ignore not instantiable classes 66 | } 67 | } catch (NoClassDefFoundError ncdfe) { 68 | // ignore not instantiable classes 69 | } 70 | } 71 | 72 | Collections.sort(classes, new Comparator>() { 73 | public int compare(Class o1, Class o2) { 74 | return o1.getName().compareTo(o2.getName()); 75 | } 76 | }); 77 | return classes.toArray(new Class[0]); 78 | } 79 | 80 | 81 | private String classNameFromJava(String fileName) { 82 | String s = replaceFileSeparators(cutOffExtension(fileName,JAVA_SUFFIX_LENGTH)); 83 | while (s.startsWith(".")) 84 | s= s.substring(1); 85 | return s; 86 | } 87 | 88 | private boolean isJavaFile(String fileName) { 89 | return fileName.endsWith(".java"); 90 | } 91 | 92 | private boolean isInnerClass(String className) { 93 | return className.contains("$"); 94 | } 95 | 96 | private boolean isClassFile(String classFileName) { 97 | return classFileName.endsWith(".class"); 98 | } 99 | 100 | private String classNameFromFile(String classFileName) { 101 | String s = replaceFileSeparators(cutOffExtension(classFileName,CLASS_SUFFIX_LENGTH)); 102 | while (s.startsWith(".")) 103 | s= s.substring(1); 104 | return s; 105 | } 106 | 107 | private String replaceFileSeparators(String s) { 108 | String result = s.replace(File.separatorChar, '.'); 109 | if (File.separatorChar != '/') { 110 | result = result.replace('/', '.'); 111 | } 112 | return result; 113 | } 114 | 115 | private String cutOffExtension(String classFileName, int length) { 116 | return classFileName.substring(0, classFileName.length() 117 | - length); 118 | } 119 | 120 | } 121 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/impl/AbstractConfigurator.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.impl; 2 | 3 | import utils.org.eclipse.core.internal.localstore.SafeChunkyInputStream; 4 | import utils.sacha.classloader.enrich.EnrichableClassloader; 5 | import utils.sacha.classloader.factory.ClassloaderFactory; 6 | import utils.sacha.interfaces.IEclipseConfigurable; 7 | 8 | import java.io.DataInputStream; 9 | import java.io.File; 10 | import java.io.IOException; 11 | import java.net.URI; 12 | import java.net.URISyntaxException; 13 | 14 | public abstract class AbstractConfigurator implements IEclipseConfigurable { 15 | 16 | private File projectDir = null; 17 | private String projectName = null; 18 | private File metadataFolder = null; 19 | 20 | @Override 21 | public void setEclipseProject(String projectName) { 22 | this.projectName = projectName; 23 | if(projectDir!=null) 24 | refreshProjectDir(); 25 | } 26 | 27 | @Override 28 | public void setEclipseMetadataFolder(String metadataLoc) { 29 | File tmp = new File(metadataLoc); 30 | if (tmp.exists() && tmp.isDirectory() && tmp.canRead()) 31 | this.metadataFolder = tmp; 32 | else 33 | throw new IllegalArgumentException(metadataLoc + " is not a correct absolute path to an eclipse metadata folder"); 34 | if(projectDir!=null) 35 | refreshProjectDir(); 36 | } 37 | 38 | private void refreshProjectDir() { 39 | projectDir=getProjectLocation(); 40 | } 41 | 42 | public File getProjectDir() { 43 | if(projectDir==null) 44 | refreshProjectDir(); 45 | if(projectDir==null) 46 | throw new IllegalArgumentException("you have to use setEclipseProject and setEclipseMetadataFolder before"); 47 | return projectDir; 48 | } 49 | 50 | public File getMetadataFolder() { 51 | if(metadataFolder==null) 52 | throw new IllegalArgumentException("you have to use setEclipseMetadataFolder before"); 53 | return metadataFolder; 54 | } 55 | 56 | /** 57 | * Get the project location for a project in the eclipse metadata. 58 | * 59 | * @param workspaceLocation the location of the workspace 60 | * @param project the project subdirectory in the metadata 61 | * @return the full path to the project. 62 | * @throws IOException failures to read location file 63 | * @throws URISyntaxException failures to read location file 64 | */ 65 | @SuppressWarnings("resource") 66 | private File getProjectLocation(){ 67 | if(projectName==null || metadataFolder==null){ 68 | throw new IllegalArgumentException("you have to use setEclipseProject and setEclipseMetadataFolder before"); 69 | } 70 | String locationPath = metadataFolder.getAbsolutePath()+"/.plugins/org.eclipse.core.resources/.projects/"+projectName+"/.location"; 71 | File location = new File(locationPath); 72 | if (location.exists()) { 73 | SafeChunkyInputStream fileInputStream = null; 74 | try { 75 | fileInputStream = new SafeChunkyInputStream(location); 76 | DataInputStream dataInputStream = new DataInputStream(fileInputStream); 77 | String file = dataInputStream.readUTF().trim(); 78 | 79 | if (file.length() > 0) { 80 | if (!file.startsWith("URI//")) { 81 | throw new IOException(location.getAbsolutePath() + " contains unexpected data: " + file); 82 | } 83 | file = file.substring("URI//".length()); 84 | return new File(new URI(file)); 85 | } 86 | }catch(Throwable t){ 87 | throw new RuntimeException(t); 88 | }finally { 89 | try { 90 | if (fileInputStream != null) 91 | fileInputStream.close(); 92 | } catch (IOException ioe) { 93 | // NOOP 94 | } 95 | } 96 | } 97 | locationPath = metadataFolder.getParentFile().getAbsolutePath()+"/"+projectName; 98 | location = new File(locationPath); 99 | if (location.exists()) { 100 | return location; 101 | } 102 | throw new IllegalArgumentException("cannot find project"); 103 | } 104 | 105 | protected EnrichableClassloader getEnrichableClassloader(){ 106 | EnrichableClassloader eClassloader = ClassloaderFactory.getEnrichableClassloader(); 107 | eClassloader.addEclipseMetadata(getMetadataFolder()); 108 | eClassloader.addEclipseProject(getProjectDir().getAbsolutePath()); 109 | return eClassloader; 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/impl/DefaultSpooner.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.impl; 2 | 3 | import spoon.Launcher; 4 | import utils.sacha.classloader.enrich.EnrichableClassloader; 5 | import utils.sacha.interfaces.ISpooner; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | public class DefaultSpooner extends AbstractConfigurator implements ISpooner { 11 | 12 | public static void main(String[] args) throws Exception { 13 | Launcher.main(new String[]{"-h"}); 14 | } 15 | private String outputFolder = null; 16 | private String[] processors = null; 17 | private String[] sources = null; 18 | private boolean graphical = false; 19 | 20 | 21 | @Override 22 | public void setOutputFolder(String folderPath) { 23 | outputFolder=folderPath; 24 | } 25 | 26 | @Override 27 | public void setProcessors(String... processorNames) { 28 | processors=processorNames; 29 | } 30 | 31 | @Override 32 | public void setProcessors(Class... processor) { 33 | List processorNames = new ArrayList<>(); 34 | for (Class class1 : processor) { 35 | processorNames.add(class1.getCanonicalName()); 36 | } 37 | this.setProcessors(processorNames.toArray(new String[0])); 38 | } 39 | 40 | @Override 41 | public void setSourceFolder(String... sources) { 42 | this.sources = sources; 43 | } 44 | 45 | @Override 46 | public void setGraphicalOutput(boolean b) { 47 | graphical = b; 48 | } 49 | 50 | 51 | @Override 52 | public void spoon() { 53 | EnrichableClassloader eClassloader = getEnrichableClassloader(); 54 | 55 | Thread.currentThread().setContextClassLoader(eClassloader); 56 | 57 | List args = new ArrayList<>(); 58 | args.add("-v"); 59 | if(graphical) 60 | args.add("-g"); 61 | args.add("--with-imports"); 62 | args.add("--compliance"); 63 | args.add("7"); 64 | if(sources == null || sources.length==0) 65 | throw new IllegalArgumentException("you have to use setSourceFolder before"); 66 | args.add("-i"); 67 | String tmp = ""; 68 | for (String string : sources) { 69 | if(string==null || string.length()==0) 70 | throw new IllegalArgumentException("setSourceFolder can not be used with empty value"); 71 | tmp+=getProjectDir().getAbsolutePath()+"/"+string+":"; 72 | } 73 | tmp = tmp.substring(0, tmp.length()-1); 74 | args.add(tmp); 75 | if(processors != null && processors.length>0){ 76 | args.add("-p"); 77 | tmp = ""; 78 | for (String string : processors) { 79 | if(string==null || string.length()==0) 80 | throw new IllegalArgumentException("setProcessors can not be used with empty value"); 81 | tmp+=string+":"; 82 | } 83 | tmp = tmp.substring(0, tmp.length()-1); 84 | args.add(tmp); 85 | } 86 | 87 | 88 | if(outputFolder != null){ 89 | args.add("-o"); 90 | if(outputFolder==null || outputFolder.length()==0) 91 | throw new IllegalArgumentException("setOutputFolder can not be used with empty value"); 92 | args.add(outputFolder); 93 | } 94 | 95 | try { 96 | Launcher.main(args.toArray(new String[]{})); 97 | } catch (Exception t) { 98 | throw t instanceof RuntimeException?(RuntimeException)t:new RuntimeException(t); 99 | } 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/impl/TestFinderCore.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.impl; 2 | 3 | import utils.sacha.classloader.enrich.EnrichableClassloader; 4 | import utils.sacha.finder.main.TestClassFinder; 5 | 6 | public class TestFinderCore extends AbstractConfigurator { 7 | 8 | public Class[] findTestClasses() { 9 | EnrichableClassloader eClassloader = getEnrichableClassloader(); 10 | 11 | Thread.currentThread().setContextClassLoader(eClassloader); 12 | 13 | return new TestClassFinder(eClassloader).findTestClasses(); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/impl/TestRunnerCore.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.impl; 2 | 3 | import utils.sacha.classloader.enrich.EnrichableClassloader; 4 | import utils.sacha.finder.main.TestClassFinder; 5 | import utils.sacha.finder.main.TestInFolder; 6 | import utils.sacha.interfaces.IRunner; 7 | import utils.sacha.interfaces.ITestResult; 8 | import utils.sacha.runner.main.TestRunner; 9 | 10 | import java.util.HashSet; 11 | import java.util.Set; 12 | 13 | public class TestRunnerCore extends AbstractConfigurator implements IRunner { 14 | 15 | @Override 16 | public ITestResult runAllTestsInClasspath() { 17 | EnrichableClassloader eClassloader = getEnrichableClassloader(); 18 | 19 | Thread.currentThread().setContextClassLoader(eClassloader); 20 | 21 | Class[] tests = new TestClassFinder(eClassloader).findTestClasses(); 22 | Set testList = new HashSet(); 23 | for (int i = 0; i < tests.length; i++) { 24 | String s = tests[i].getCanonicalName(); 25 | if(s.startsWith("fr.inria.spirals.npefix")) { 26 | continue; 27 | } 28 | testList.add(tests[i]); 29 | } 30 | return new TestRunner().run(testList.toArray(new Class[]{})); 31 | } 32 | 33 | @Override 34 | public ITestResult runAllTestsInDirectory(String dir) { 35 | 36 | TestInFolder tf = new TestInFolder(dir); 37 | 38 | EnrichableClassloader eClassloader = getEnrichableClassloader(); 39 | 40 | Thread.currentThread().setContextClassLoader(eClassloader); 41 | Class[] tests = new TestClassFinder(eClassloader).findTestClasses(); 42 | 43 | return new TestRunner().run(tf.find()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/impl/TestSuiteCreatorCore.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.impl; 2 | 3 | import utils.sacha.classloader.enrich.EnrichableClassloader; 4 | import utils.sacha.finder.main.TestClassFinder; 5 | 6 | import java.io.PrintStream; 7 | 8 | public class TestSuiteCreatorCore extends AbstractConfigurator{ 9 | 10 | public void printJavaTestSuite(PrintStream out, String className){ 11 | EnrichableClassloader eClassloader = getEnrichableClassloader(); 12 | 13 | Thread.currentThread().setContextClassLoader(eClassloader); 14 | 15 | Class[] tests = new TestClassFinder(eClassloader).findTestClasses(); 16 | 17 | if(tests.length==0) 18 | throw new IllegalArgumentException("no tests found in "+getProjectDir().getAbsolutePath()); 19 | 20 | String classes = ""; 21 | for (Class clazz : tests) { 22 | classes+=clazz.getName()+".class"; 23 | classes+=","; 24 | } 25 | classes = classes.substring(0, classes.length()-1); 26 | 27 | out.print("\n" + 28 | "import org.junit.internal.TextListener;\n"+ 29 | "import org.junit.runner.JUnitCore;\n"+ 30 | "import org.junit.runner.Result;\n" + 31 | "\n" + 32 | "public class "+className+"{\n" + 33 | "\tpublic static void main(String[] args){\n" + 34 | "\t\tnew "+className+"().run();\n"+ 35 | "\t}\n" + 36 | "\n" + 37 | "\tpublic Result run(){\n" + 38 | "\t\tJUnitCore runner = new JUnitCore();\n"+ 39 | "\t\trunner.addListener(new TextListener(System.out));\n"+ 40 | "\t\treturn runner.run(getClassesArray());\n"+ 41 | "\t}\n" + 42 | "\n"+ 43 | "\tprivate Class[] getClassesArray(){\n" + 44 | "\t\treturn new Class[]{"+classes+"};\n"+ 45 | "\t}\n" + 46 | "}"); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/interfaces/IEclipseConfigurable.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.interfaces; 2 | 3 | public interface IEclipseConfigurable { 4 | 5 | void setEclipseMetadataFolder(String folderName); 6 | 7 | void setEclipseProject(String projectName); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/interfaces/IGeneralToJava.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.interfaces; 2 | 3 | public interface IGeneralToJava { 4 | 5 | public void changeToJava(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/interfaces/IRunner.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.interfaces; 2 | 3 | public interface IRunner { 4 | 5 | /** setEclipseClassPath must have been called before */ 6 | utils.sacha.interfaces.ITestResult runAllTestsInClasspath(); 7 | 8 | /** dir must be valid source folder */ 9 | utils.sacha.interfaces.ITestResult runAllTestsInDirectory(String dir); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/interfaces/ISpooner.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.interfaces; 2 | 3 | public interface ISpooner extends IEclipseConfigurable { 4 | 5 | void spoon(); 6 | 7 | void setOutputFolder(String folderPath); 8 | 9 | void setProcessors(String... processorNames); 10 | 11 | void setProcessors(Class... processor); 12 | 13 | /** must be set before spooning */ 14 | void setSourceFolder(String... sources); 15 | 16 | void setGraphicalOutput(boolean b); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/interfaces/ITestResult.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.interfaces; 2 | 3 | import org.junit.runner.Result; 4 | 5 | public interface ITestResult { 6 | 7 | int getNbRunTests(); 8 | 9 | int getNbFailedTests(); 10 | 11 | Result getResult(); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/mains/CheckLoopMain.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.mains; 2 | 3 | /** checks that a Spoon transformation is semantic-preserving */ 4 | public class CheckLoopMain { 5 | 6 | public static void main(String[] args) { 7 | 8 | // 9 | // // sets the source or binary classpath 10 | // // semanticPreservingLoop.setSourceClassPath("foo"); 11 | // // semanticPreservingLoop.dependsOn("foo.jar") 12 | // // or 13 | // setEclipseProject("projectName"); 14 | // 15 | // // runs the test folder 16 | // // ITestResult res = semanticPreservingLoop.testDirectory("/dir/test"); 17 | // // or 18 | // ITestResult res = runAllTestsInClasspath(); 19 | // 20 | // // spoons the main folder 21 | // spoon(new SpoonConfigImpl()); 22 | // 23 | // // re-runs the tests 24 | // ITestResult res2 = runAllTestsInDirectory(""); 25 | // 26 | // // compares both runs, should be the same 27 | // assert res.equals(res2); 28 | // } 29 | // 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/mains/EclipseGeneralToJavaProject.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.mains; 2 | 3 | import utils.sacha.impl.GeneralToJavaCore; 4 | 5 | 6 | /** Manipulates Eclipse projects (nature, classpath, etc. **/ 7 | public class EclipseGeneralToJavaProject { 8 | 9 | public static void main(String[] args) { 10 | GeneralToJavaCore core = new GeneralToJavaCore(); 11 | core.setEclipseMetadataFolder("/home/bcornu/workspace/.metadata"); 12 | core.setEclipseProject("jmeter-maven-plugin"); 13 | core.changeToJava(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/mains/MergeMavenProjects.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.mains; 2 | 3 | import utils.sacha.project.utils.MavenModulesMerger; 4 | 5 | /** Merges Maven projects in one single Eclipse project */ 6 | public class MergeMavenProjects { 7 | 8 | public static void main(String[] args) { 9 | MavenModulesMerger merger = new MavenModulesMerger(); 10 | merger.setEclipseMetadataFolder("/home/bcornu/workspace/.metadata"); 11 | merger.setEclipseProject("find-sec-bugs"); 12 | merger.merge(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/mains/RepairLoop1.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.mains; 2 | 3 | /** Is a basic example on how having the repair loop modification -> test suite (TODO Matias) */ 4 | public class RepairLoop1 { 5 | 6 | public static void main(String[] args) { 7 | throw new UnsupportedOperationException(); 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/mains/RunSpoonWithClasspath.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.mains; 2 | 3 | import utils.sacha.impl.DefaultSpooner; 4 | import utils.sacha.interfaces.ISpooner; 5 | 6 | /** Runs spoon in an easy manner */ 7 | public class RunSpoonWithClasspath { 8 | 9 | public static void main(String[] args) { 10 | 11 | ISpooner spooner = new DefaultSpooner(); 12 | //project config 13 | spooner.setEclipseProject("test"); 14 | spooner.setEclipseMetadataFolder("/home/bcornu/workspace/.metadata"); 15 | //spoon config 16 | spooner.setSourceFolder("src"); 17 | // spooner.setProcessors("bcu.transformer.processors.ClassAnnotation","bcu.transformer.processors.TryEncapsulation"); 18 | spooner.setOutputFolder("/home/bcornu/workspace/test-spooned/src"); 19 | 20 | spooner.setGraphicalOutput(true); 21 | 22 | spooner.spoon(); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/mains/TestFinderMain.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.mains; 2 | 3 | import utils.sacha.impl.TestFinderCore; 4 | 5 | /** Runs all tests of an Eclipse project */ 6 | public class TestFinderMain { 7 | 8 | public static void main(String[] args) { 9 | TestFinderCore finder = new TestFinderCore(); 10 | finder.setEclipseMetadataFolder("/home/bcornu/workspace/.metadata/"); 11 | finder.setEclipseProject("joda-time"); 12 | 13 | Class[] tests = finder.findTestClasses(); 14 | for (Class clazz : tests) { 15 | System.out.println(clazz);; 16 | } 17 | 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/mains/TestRunnerMain.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.mains; 2 | 3 | import utils.sacha.impl.TestRunnerCore; 4 | import utils.sacha.interfaces.ITestResult; 5 | 6 | /** Runs all tests of an Eclipse project */ 7 | public class TestRunnerMain { 8 | 9 | public static void main(String[] args) { 10 | TestRunnerCore runner = new TestRunnerCore(); 11 | runner.setEclipseMetadataFolder("/home/bcornu/workspace/.metadata/"); 12 | runner.setEclipseProject("joda-time"); 13 | // runs the test folder 14 | ITestResult res = runner.runAllTestsInClasspath(); 15 | System.out.println(res.getNbRunTests()); 16 | System.out.println(res.getNbFailedTests()); 17 | 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/mains/TestSuiteGeneratorMain.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.mains; 2 | 3 | import utils.sacha.impl.TestSuiteCreatorCore; 4 | 5 | import java.io.File; 6 | import java.io.PrintStream; 7 | 8 | /** Generates on standard output a JUnit4 test class that runs all the test of a given Eclipse project */ 9 | public class TestSuiteGeneratorMain { 10 | 11 | public static void main(String[] args) { 12 | PrintStream f; 13 | TestSuiteCreatorCore tcsc = new TestSuiteCreatorCore(); 14 | tcsc.setEclipseMetadataFolder("/home/langloisj/workspace/.metadata"); 15 | tcsc.setEclipseProject("jbehave-core"); 16 | try 17 | { 18 | f = new PrintStream(new File("/home/langloisj/eclipse-workspace-projects-with-junit-tests/jbehave-core/src/test/java/AllTests.java")); 19 | }catch(Exception e){throw new RuntimeException(e);} 20 | tcsc.printJavaTestSuite(f,"AllTests"); 21 | } 22 | 23 | } 24 | 25 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/project/utils/IMavenMerger.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.project.utils; 2 | 3 | public interface IMavenMerger { 4 | 5 | public void merge(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/runner/utils/TestInfo.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.runner.utils; 2 | 3 | import org.junit.runner.Result; 4 | import utils.sacha.interfaces.ITestResult; 5 | 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Set; 10 | 11 | public class TestInfo extends HashMap> implements ITestResult { 12 | 13 | private static final long serialVersionUID = 1L; 14 | 15 | private Result result; 16 | 17 | private String countRun; 18 | 19 | public TestInfo() { 20 | super(); 21 | } 22 | 23 | public void add(String className, String methodName) { 24 | if (!containsKey(className)) 25 | put(className, new ArrayList()); 26 | get(className).add(methodName); 27 | } 28 | 29 | public static void compare(TestInfo runnedTests, TestInfo importedTests) { 30 | System.out.println("runned : "+runnedTests.countRun+" / imported : "+importedTests.countRun); 31 | // int diff = runnedTests.count>importedTests.count?runnedTests.count-importedTests.count:importedTests.count-runnedTests.count; 32 | // if(diff>0) 33 | // System.err.println("number of tests diff : "+diff); 34 | Set runnedClasses = runnedTests.keySet(); 35 | Set importedClasses = importedTests.keySet(); 36 | int total=0; 37 | for (String string : importedClasses) { 38 | if(!runnedClasses.contains(string)){ 39 | System.err.print("imported not runned : "+string); 40 | System.err.println(" number of tests : "+importedTests.get(string).size()); 41 | total+=importedTests.get(string).size(); 42 | } 43 | } 44 | if(total>0) 45 | System.err.println("\ttotal number : "+total); 46 | total = 0; 47 | for (String string : runnedClasses) { 48 | if(!importedClasses.contains(string)){ 49 | System.err.print("runned not imported : "+string); 50 | System.err.println(" number of tests : "+runnedTests.get(string).size()); 51 | total+=runnedTests.get(string).size(); 52 | } 53 | } 54 | if(total>0) 55 | System.err.println("\ttotal number : "+total); 56 | } 57 | 58 | @Override 59 | public int getNbRunTests() { 60 | return result.getRunCount(); 61 | } 62 | 63 | @Override 64 | public int getNbFailedTests() { 65 | return result.getFailureCount(); 66 | } 67 | 68 | public void setResult(Result result) { 69 | this.result = result; 70 | } 71 | 72 | public Result getResult() { 73 | return result; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/utils/sacha/utils/SachaDocumentationGenerator.java: -------------------------------------------------------------------------------- 1 | package utils.sacha.utils; 2 | 3 | import spoon.processing.AbstractManualProcessor; 4 | import spoon.reflect.declaration.CtClass; 5 | import spoon.reflect.declaration.CtPackage; 6 | import spoon.reflect.visitor.filter.TypeFilter; 7 | 8 | /** Generates the documentation of sacha-infrastructure */ 9 | public class SachaDocumentationGenerator extends AbstractManualProcessor { 10 | 11 | @Override 12 | public void process() { 13 | System.out.println("Generated Documentation of sacha-infrastructure\n"+ 14 | "===============================================\n"+ 15 | "(generated with sacha.utils.SachaDocumentationGenerator)\n\n"+ 16 | "Sacha-infrastructure supports the following use cases:\n\n"); 17 | 18 | for (CtPackage pack : getFactory().Package().getAll()) { 19 | 20 | for (CtPackage pack2 : pack.getPackages()) { 21 | if ("sacha.mains".equals(pack2.getQualifiedName())) { 22 | for (CtClass c : pack2.getElements(new TypeFilter(CtClass.class))) { 23 | System.out.println("\n-------------------\n"+c.getSimpleName()+": " + c.getDocComment()); 24 | } 25 | } 26 | } 27 | } 28 | } 29 | 30 | public static void main(String[] arg) throws Exception { 31 | String[] args = { 32 | "-p", "sacha.utils.SachaDocumentationGenerator", "-i", "src" 33 | }; 34 | // new Launcher(args).run();; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/resources/config.ini: -------------------------------------------------------------------------------- 1 | # in sec 2 | iteration.timeout = 5 3 | iteration.count = 10000 4 | 5 | server.port = 10000 6 | server.host = 127.0.0.1 7 | server.name = Selector 8 | 9 | evaluation.datasetRoot = ../npedataset/ 10 | evaluation.workingDirectory = /tmp/npefix/ 11 | evaluation.m2Root = ~/.m2/ 12 | 13 | selector.greedy.epsilon = 0.2 14 | 15 | random.seed = 10 -------------------------------------------------------------------------------- /src/test/java/fr/inria/spirals/npefix/main/all/End2EndTest.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.main.all; 2 | 3 | import org.junit.Ignore; 4 | import org.junit.Test; 5 | 6 | public class End2EndTest { 7 | @Test 8 | @Ignore 9 | public void test() throws Exception { 10 | // test end 2 end for helping @Peanu11 in https://github.com/SpoonLabs/npefix/issues/29 11 | 12 | // execute command ls 13 | Runtime.getRuntime().exec("rm -rf npefix-src"); 14 | 15 | fr.inria.spirals.npefix.main.run.Main.main(new String[] { "-s" 16 | , "../npe-dataset/pdfbox_2965/src/" 17 | , "-c" 18 | , "../npe-dataset/pdfbox_2965/target/classes/:../npe-dataset/pdfbox_2965/target/test-classes/:/home/martin/.m2/repository/org/apache/pdfbox/fontbox/2.0.0-RC1/fontbox-2.0.0-RC1.jar:/home/martin/.m2/repository/commons-logging/commons-logging/1.2/commons-logging-1.2.jar:/home/martin/.m2/repository/org/bouncycastle/bcpkix-jdk15on/1.50/bcpkix-jdk15on-1.50.jar:/home/martin/.m2/repository/org/bouncycastle/bcprov-jdk15on/1.50/bcprov-jdk15on-1.50.jar:/home/martin/.m2/repository/junit/junit/4.12/junit-4.12.jar:/home/martin/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar" 19 | , "-t" 20 | , "org.apache.pdfbox.pdmodel.interactive.form.PDAcroFormTest" 21 | }); 22 | 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/fr/inria/spirals/npefix/patchTemplate/ReplaceGlobalTest.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.patchTemplate; 2 | 3 | import fr.inria.spirals.npefix.patchTemplate.template.ReplaceGlobal; 4 | import org.junit.Assert; 5 | import org.junit.Test; 6 | import spoon.Launcher; 7 | import spoon.SpoonModelBuilder; 8 | import spoon.reflect.code.CtForEach; 9 | import spoon.reflect.declaration.CtClass; 10 | 11 | import java.io.File; 12 | import java.net.URL; 13 | import java.util.ArrayList; 14 | 15 | public class ReplaceGlobalTest { 16 | 17 | @Test 18 | public void ReplaceGlobalInstanceTest() { 19 | Launcher spoon = getSpoonLauncher(); 20 | 21 | CtClass foo = spoon.getFactory().Class().get("Foo"); 22 | 23 | CtForEach afor = (CtForEach) foo.getMethod("foo2").getBody().getStatement(1); 24 | Assert.assertEquals("for (String element : array) {\n" 25 | + " result += element.toString();\n" 26 | + " if (element == null) {\n" 27 | + " return null;\n" 28 | + " }\n" 29 | + "}", afor.toString()); 30 | 31 | new ReplaceGlobal(foo.getFactory().Class().get(ArrayList.class)).apply(afor.getExpression()); 32 | 33 | Assert.assertEquals("if (array == null)\n" 34 | + " this.array = new ArrayList();\n", 35 | foo.getMethod("foo2").getBody().getStatement(1).toString()); 36 | } 37 | 38 | @Test 39 | public void ReplaceGlobalVariableTest() { 40 | Launcher spoon = getSpoonLauncher(); 41 | 42 | CtClass foo = spoon.getFactory().Class().get("Foo"); 43 | 44 | CtForEach afor = (CtForEach) foo.getMethod("foo2").getBody().getStatement(1); 45 | Assert.assertEquals("for (String element : array) {\n" 46 | + " result += element.toString();\n" 47 | + " if (element == null) {\n" 48 | + " return null;\n" 49 | + " }\n" 50 | + "}", afor.toString()); 51 | 52 | new ReplaceGlobal(foo.getField("field")).apply(afor.getExpression()); 53 | 54 | Assert.assertEquals("if (array == null)\n" 55 | + " this.array = this.field;\n", 56 | foo.getMethod("foo2").getBody().getStatement(1).toString()); 57 | } 58 | 59 | 60 | private Launcher getSpoonLauncher() { 61 | URL sourcePath = getClass().getResource("/foo/src/main/java/"); 62 | URL testPath = getClass().getResource("/foo/src/test/java/"); 63 | String classpath = System.getProperty("java.class.path"); 64 | 65 | Launcher launcher = new Launcher(); 66 | launcher.addInputResource(sourcePath.getPath()); 67 | launcher.addInputResource(testPath.getPath()); 68 | launcher.getEnvironment().setAutoImports(true); 69 | 70 | SpoonModelBuilder compiler = launcher.getModelBuilder(); 71 | compiler.setSourceClasspath(classpath.split(File.pathSeparator)); 72 | launcher.buildModel(); 73 | return launcher; 74 | } 75 | } -------------------------------------------------------------------------------- /src/test/java/fr/inria/spirals/npefix/patchTemplate/ReplaceLocalTest.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.patchTemplate; 2 | 3 | import fr.inria.spirals.npefix.patchTemplate.template.ReplaceLocal; 4 | import org.junit.Assert; 5 | import org.junit.Test; 6 | import spoon.Launcher; 7 | import spoon.SpoonModelBuilder; 8 | import spoon.reflect.code.CtForEach; 9 | import spoon.reflect.declaration.CtClass; 10 | 11 | import java.io.File; 12 | import java.net.URL; 13 | import java.util.ArrayList; 14 | 15 | public class ReplaceLocalTest { 16 | 17 | @Test 18 | public void ReplaceLocalInstanceTest() { 19 | Launcher spoon = getSpoonLauncher(); 20 | 21 | CtClass foo = spoon.getFactory().Class().get("Foo"); 22 | 23 | CtForEach afor = (CtForEach) foo.getMethod("foo2").getBody().getStatement(1); 24 | Assert.assertEquals("for (String element : array) {\n" 25 | + " result += element.toString();\n" 26 | + " if (element == null) {\n" 27 | + " return null;\n" 28 | + " }\n" 29 | + "}", afor.toString()); 30 | 31 | new ReplaceLocal(foo.getFactory().Class().get(ArrayList.class)).apply(afor.getExpression()); 32 | 33 | Assert.assertEquals("if (array == null)\n" 34 | + " for (String element : new ArrayList()) {\n" 35 | + " result += element.toString();\n" 36 | + " if (element == null) {\n" 37 | + " return null;\n" 38 | + " }\n" 39 | + " }\n" 40 | + "else\n" 41 | + " for (String element : array) {\n" 42 | + " result += element.toString();\n" 43 | + " if (element == null) {\n" 44 | + " return null;\n" 45 | + " }\n" 46 | + " }\n", foo.getMethod("foo2").getBody().getStatement(1).toString()); 47 | } 48 | 49 | @Test 50 | public void ReplaceLocalVariableTest() { 51 | Launcher spoon = getSpoonLauncher(); 52 | 53 | CtClass foo = spoon.getFactory().Class().get("Foo"); 54 | 55 | CtForEach afor = (CtForEach) foo.getMethod("foo2").getBody().getStatement(1); 56 | Assert.assertEquals("for (String element : array) {\n" 57 | + " result += element.toString();\n" 58 | + " if (element == null) {\n" 59 | + " return null;\n" 60 | + " }\n" 61 | + "}", afor.toString()); 62 | 63 | new ReplaceLocal(foo.getField("field")).apply(afor.getExpression()); 64 | 65 | Assert.assertEquals("if (array == null)\n" 66 | + " for (String element : this.field) {\n" 67 | + " result += element.toString();\n" 68 | + " if (element == null) {\n" 69 | + " return null;\n" 70 | + " }\n" 71 | + " }\n" 72 | + "else\n" 73 | + " for (String element : array) {\n" 74 | + " result += element.toString();\n" 75 | + " if (element == null) {\n" 76 | + " return null;\n" 77 | + " }\n" 78 | + " }\n", foo.getMethod("foo2").getBody().getStatement(1).toString()); 79 | } 80 | 81 | 82 | private Launcher getSpoonLauncher() { 83 | URL sourcePath = getClass().getResource("/foo/src/main/java/"); 84 | URL testPath = getClass().getResource("/foo/src/test/java/"); 85 | String classpath = System.getProperty("java.class.path"); 86 | 87 | Launcher launcher = new Launcher(); 88 | launcher.addInputResource(sourcePath.getPath()); 89 | launcher.addInputResource(testPath.getPath()); 90 | launcher.getEnvironment().setAutoImports(true); 91 | 92 | SpoonModelBuilder compiler = launcher.getModelBuilder(); 93 | compiler.setSourceClasspath(classpath.split(File.pathSeparator)); 94 | launcher.buildModel(); 95 | return launcher; 96 | } 97 | } -------------------------------------------------------------------------------- /src/test/java/fr/inria/spirals/npefix/patchTemplate/SkipLineTest.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.patchTemplate; 2 | 3 | import fr.inria.spirals.npefix.patchTemplate.template.SkipLine; 4 | import org.junit.Assert; 5 | import org.junit.Test; 6 | import spoon.Launcher; 7 | import spoon.SpoonModelBuilder; 8 | import spoon.reflect.code.CtForEach; 9 | import spoon.reflect.declaration.CtClass; 10 | 11 | import java.io.File; 12 | import java.net.URL; 13 | 14 | public class SkipLineTest { 15 | 16 | @Test 17 | public void skipLineTest() { 18 | Launcher spoon = getSpoonLauncher(); 19 | 20 | CtClass foo = spoon.getFactory().Class().get("Foo"); 21 | 22 | CtForEach afor = (CtForEach) foo.getMethod("foo2").getBody().getStatement(1); 23 | Assert.assertEquals("for (java.lang.String element : array) {\n" 24 | + " result += element.toString();\n" 25 | + " if (element == null) {\n" 26 | + " return null;\n" 27 | + " }\n" 28 | + "}", afor.toString()); 29 | 30 | new SkipLine().apply(afor.getExpression()); 31 | 32 | Assert.assertEquals("if (array != null)\n" 33 | + " for (java.lang.String element : array) {\n" 34 | + " result += element.toString();\n" 35 | + " if (element == null) {\n" 36 | + " return null;\n" 37 | + " }\n" 38 | + " }\n", foo.getMethod("foo2").getBody().getStatement(1).toString()); 39 | } 40 | 41 | 42 | private spoon.Launcher getSpoonLauncher() { 43 | URL sourcePath = getClass().getResource("/foo/src/main/java/"); 44 | URL testPath = getClass().getResource("/foo/src/test/java/"); 45 | String classpath = System.getProperty("java.class.path"); 46 | 47 | spoon.Launcher launcher = new spoon.Launcher(); 48 | launcher.addInputResource(sourcePath.getPath()); 49 | launcher.addInputResource(testPath.getPath()); 50 | SpoonModelBuilder compiler = launcher.getModelBuilder(); 51 | compiler.setSourceClasspath(classpath.split(File.pathSeparator)); 52 | launcher.buildModel(); 53 | return launcher; 54 | } 55 | } -------------------------------------------------------------------------------- /src/test/java/fr/inria/spirals/npefix/patchTemplate/SkipMethodReturnTest.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.patchTemplate; 2 | 3 | import fr.inria.spirals.npefix.patchTemplate.template.SkipMethodReturn; 4 | import org.junit.Assert; 5 | import org.junit.Test; 6 | import spoon.Launcher; 7 | import spoon.SpoonModelBuilder; 8 | import spoon.reflect.code.CtForEach; 9 | import spoon.reflect.code.CtInvocation; 10 | import spoon.reflect.declaration.CtClass; 11 | 12 | import java.io.File; 13 | import java.net.URL; 14 | 15 | public class SkipMethodReturnTest { 16 | 17 | @Test 18 | public void skipMethodReturnInConstructorTest() { 19 | Launcher spoon = getSpoonLauncher(); 20 | 21 | CtClass foo = spoon.getFactory().Class().get("Foo2"); 22 | 23 | CtInvocation statement = (CtInvocation) foo.getConstructor().getBody().getStatement(1); 24 | Assert.assertEquals("public Foo2() {\n" 25 | + " super();\n" 26 | + " field.toString();\n" 27 | + " field = null;\n" 28 | + " array = null;\n" 29 | + "}", foo.getConstructor().toString()); 30 | 31 | new SkipMethodReturn().apply(statement.getTarget()); 32 | 33 | Assert.assertEquals("public Foo2() {\n" 34 | + " super();\n" 35 | + " if (field != null) {\n" 36 | + " field.toString();\n" 37 | + " field = null;\n" 38 | + " array = null;\n" 39 | + " }\n" 40 | + "}", foo.getConstructor().toString()); 41 | } 42 | 43 | 44 | @Test 45 | public void skipLineTest() { 46 | Launcher spoon = getSpoonLauncher(); 47 | 48 | CtClass foo = spoon.getFactory().Class().get("Foo"); 49 | 50 | CtForEach afor = (CtForEach) foo.getMethod("foo2").getBody().getStatement(1); 51 | Assert.assertEquals("for (java.lang.String element : array) {\n" 52 | + " result += element.toString();\n" 53 | + " if (element == null) {\n" 54 | + " return null;\n" 55 | + " }\n" 56 | + "}", afor.toString()); 57 | 58 | new SkipMethodReturn().apply(afor.getExpression()); 59 | 60 | Assert.assertEquals("if (array == null)\n" 61 | + " return null;\n", foo.getMethod("foo2").getBody().getStatement(1).toString()); 62 | } 63 | 64 | private Launcher getSpoonLauncher() { 65 | URL sourcePath = getClass().getResource("/foo/src/main/java/"); 66 | URL testPath = getClass().getResource("/foo/src/test/java/"); 67 | String classpath = System.getProperty("java.class.path"); 68 | 69 | Launcher launcher = new Launcher(); 70 | launcher.addInputResource(sourcePath.getPath()); 71 | launcher.addInputResource(testPath.getPath()); 72 | SpoonModelBuilder compiler = launcher.getModelBuilder(); 73 | compiler.setSourceClasspath(classpath.split(File.pathSeparator)); 74 | launcher.buildModel(); 75 | return launcher; 76 | } 77 | } -------------------------------------------------------------------------------- /src/test/java/fr/inria/spirals/npefix/patchTemplate/testClasses/ChildClassSamePackage.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.patchTemplate.testClasses; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class ChildClassSamePackage extends ParentClass { 6 | public int publicChildField; 7 | private String privateChildField; 8 | protected double protectedChildField; 9 | String defaultChildField; 10 | 11 | public void m(String parameter) { 12 | String localVariable = ""; 13 | String[] array = new String[0]; 14 | for(Object foreach: new ArrayList<>()) { 15 | new ArrayList() { 16 | private String innerClass; 17 | 18 | private void m(String parameterInner) { 19 | this.get(8).getClass(); 20 | privateChildField.toString(); 21 | } 22 | }; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/test/java/fr/inria/spirals/npefix/patchTemplate/testClasses/ParentClass.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.patchTemplate.testClasses; 2 | 3 | public class ParentClass { 4 | public String publicParentField; 5 | private String privateParentField; 6 | protected String protectedParentField; 7 | String defaultParentField; 8 | } -------------------------------------------------------------------------------- /src/test/java/fr/inria/spirals/npefix/transformer/processors/ArrayAccessTest.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.transformer.processors; 2 | 3 | import org.junit.Test; 4 | import spoon.Launcher; 5 | 6 | public class ArrayAccessTest { 7 | 8 | @Test 9 | public void test() { 10 | Launcher spoon = new Launcher(); 11 | spoon.addInputResource("src/test/resources/foo/src/main/java/"); 12 | spoon.addProcessor(new ArrayRead()); 13 | spoon.setSourceOutputDirectory("target/instrumented"); 14 | 15 | spoon.run(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/fr/inria/spirals/npefix/transformer/processors/BeforeDerefAdderTest.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.transformer.processors; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Ignore; 5 | import org.junit.Test; 6 | import spoon.Launcher; 7 | import spoon.reflect.code.CtBlock; 8 | import spoon.reflect.code.CtIf; 9 | import spoon.reflect.code.CtLocalVariable; 10 | import spoon.reflect.declaration.CtClass; 11 | 12 | public class BeforeDerefAdderTest { 13 | 14 | @Test 15 | @Ignore 16 | public void genericTypeInInvocationType() { 17 | Launcher spoon = new Launcher(); 18 | spoon.addInputResource("src/test/resources/foo/src/main/java/"); 19 | spoon.addProcessor(BeforeDerefAdder.class.getCanonicalName()); 20 | spoon.setSourceOutputDirectory("target/instrumented"); 21 | 22 | spoon.run(); 23 | 24 | CtClass fooTernary = spoon.getFactory().Class().get("Foo"); 25 | CtIf beforeDerefIf1 = fooTernary.getMethod("genericInMethodType").getBody().getStatement(1); 26 | CtLocalVariable NPEFixVariable = (CtLocalVariable) ((CtBlock) beforeDerefIf1.getThenStatement()).getStatement(0); 27 | Assert.assertEquals("java.lang.String", NPEFixVariable.getType().toString()); 28 | 29 | 30 | CtIf beforeDerefIf2 = fooTernary.getMethod("genericWithoutExtendsInMethodType").getBody().getStatement(1); 31 | NPEFixVariable = (CtLocalVariable) ((CtBlock) beforeDerefIf2.getThenStatement()).getStatement(0); 32 | System.out.println(NPEFixVariable); 33 | Assert.assertEquals("T", NPEFixVariable.getType().toString()); 34 | 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/fr/inria/spirals/npefix/transformer/processors/CheckNotNullTest.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.transformer.processors; 2 | 3 | import org.junit.Test; 4 | import spoon.Launcher; 5 | 6 | public class CheckNotNullTest { 7 | 8 | @Test 9 | public void test() { 10 | Launcher spoon = new Launcher(); 11 | spoon.addInputResource("src/test/resources/foo/src/main/java/"); 12 | spoon.addProcessor(new CheckNotNull()); 13 | spoon.setSourceOutputDirectory("target/instrumented"); 14 | 15 | spoon.run(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/fr/inria/spirals/npefix/transformer/processors/ConstructorEncapsulationTest.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.transformer.processors; 2 | 3 | import org.junit.Test; 4 | import spoon.Launcher; 5 | import spoon.reflect.declaration.CtClass; 6 | import spoon.reflect.declaration.CtConstructor; 7 | 8 | import static org.junit.Assert.assertEquals; 9 | 10 | public class ConstructorEncapsulationTest { 11 | 12 | @Test 13 | public void test() { 14 | Launcher spoon = new Launcher(); 15 | spoon.addInputResource("src/test/resources/foo/src/main/java/"); 16 | spoon.addProcessor(new ConstructorEncapsulation()); 17 | spoon.setSourceOutputDirectory("target/instrumented"); 18 | 19 | spoon.run(); 20 | 21 | CtClass fooTernary = spoon.getFactory().Class().get("Foo"); 22 | CtConstructor constructor = fooTernary.getConstructor(); 23 | assertEquals("public Foo() {\n" 24 | + " super();\n" 25 | + " fr.inria.spirals.npefix.resi.context.ConstructorContext _bcornu_methode_context1 = new fr.inria.spirals.npefix.resi.context.ConstructorContext(Foo.class, 9, 167, 247);\n" 26 | + " try {\n" 27 | + " field = null;\n" 28 | + " array = null;\n" 29 | + " } finally {\n" 30 | + " _bcornu_methode_context1.methodEnd();\n" 31 | + " }\n" 32 | + "}", constructor.toString()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/fr/inria/spirals/npefix/transformer/processors/ImplicitCastCheckerTest.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.transformer.processors; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | import spoon.Launcher; 6 | import spoon.SpoonException; 7 | 8 | /** 9 | * Split if condition into several if in order to add check not null before each section of the condition 10 | */ 11 | public class ImplicitCastCheckerTest { 12 | 13 | @Test 14 | public void test() { 15 | Launcher spoon = new Launcher(); 16 | spoon.addInputResource("src/test/resources/foo/src/main/java/"); 17 | spoon.addProcessor(new AddImplicitCastChecker()); 18 | spoon.addProcessor(new BeforeDerefAdder()); 19 | spoon.setSourceOutputDirectory("target/instrumented"); 20 | spoon.getEnvironment().setShouldCompile(true); 21 | spoon.getModelBuilder().setSourceClasspath(System.getProperty("java.class.path").split(":")); 22 | try { 23 | spoon.run(); 24 | } catch (SpoonException e) { 25 | Assert.fail("No compilation error."); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/fr/inria/spirals/npefix/transformer/processors/TargetModifierTest.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.transformer.processors; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | import spoon.Launcher; 6 | import spoon.reflect.code.CtAssignment; 7 | import spoon.reflect.code.CtCatch; 8 | import spoon.reflect.code.CtStatement; 9 | import spoon.reflect.code.CtTry; 10 | import spoon.reflect.declaration.CtClass; 11 | import spoon.reflect.declaration.CtMethod; 12 | 13 | public class TargetModifierTest { 14 | 15 | @Test 16 | public void beforeCallInMultiCatch() { 17 | Launcher spoon = new Launcher(); 18 | spoon.addInputResource("src/test/resources/foo/src/main/java/"); 19 | spoon.addProcessor(TargetModifier.class.getCanonicalName()); 20 | spoon.setSourceOutputDirectory("target/instrumented"); 21 | 22 | spoon.run(); 23 | 24 | CtClass fooTernary = spoon.getFactory().Class().get("Foo"); 25 | CtMethod multiCatch = fooTernary.getMethod("multiCatch"); 26 | System.out.println(multiCatch); 27 | CtTry ctTry = multiCatch.getBody().getStatement(0); 28 | CtCatch ctCatch = ctTry.getCatchers().get(0); 29 | Assert.assertFalse(ctCatch.getBody().getStatement(0) instanceof CtAssignment); 30 | // catch variable cannot be null 31 | Assert.assertEquals("e.printStackTrace()", ctCatch.getBody().getStatement(0).toString()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/fr/inria/spirals/npefix/transformer/processors/TernarySplitterTest.java: -------------------------------------------------------------------------------- 1 | package fr.inria.spirals.npefix.transformer.processors; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | import spoon.Launcher; 6 | import spoon.reflect.declaration.CtClass; 7 | 8 | /** 9 | * Split if condition into several if in order to add check not null before each section of the condition 10 | */ 11 | public class TernarySplitterTest { 12 | 13 | @Test 14 | public void test() { 15 | Launcher spoon = new Launcher(); 16 | spoon.addInputResource("src/test/resources/foo/src/main/java/"); 17 | spoon.addProcessor(TernarySplitter.class.getCanonicalName()); 18 | spoon.setSourceOutputDirectory("target/instrumented"); 19 | 20 | spoon.run(); 21 | 22 | CtClass fooTernary = spoon.getFactory().Class().get("FooTernary"); 23 | Assert.assertNotNull(fooTernary); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/resources/bar/src/main/java/Coneflower.java: -------------------------------------------------------------------------------- 1 | 2 | public class Coneflower { 3 | 4 | private String nullString = null; 5 | private int i = 0; 6 | 7 | public String methodThrowingNPE() { 8 | return nullString.toString(); 9 | } 10 | 11 | public String intermediateMethod() { 12 | return "Brilliant coneflower," + methodThrowingNPE(); 13 | } 14 | 15 | public String method() { 16 | return "Cutleaf coneflower," + intermediateMethod(); 17 | } 18 | 19 | public int throwingException() { 20 | return Integer.parseInt("thisIsNotAnInteger"); 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /src/test/resources/bar/src/test/java/ConeflowerTest.java: -------------------------------------------------------------------------------- 1 | import org.junit.Test; 2 | import org.junit.Assert; 3 | 4 | public class ConeflowerTest { 5 | 6 | @Test 7 | public void test1() throws Exception { 8 | Coneflower flower = new Coneflower(); 9 | Assert.assertEquals("Cutleaf coneflower,Brilliant coneflower,", flower.method()); 10 | } 11 | 12 | @Test 13 | public void test2() throws Exception { 14 | Coneflower flower = new Coneflower(); 15 | Assert.assertEquals("Brilliant coneflower,", flower.intermediateMethod()); 16 | } 17 | 18 | @Test 19 | public void test3() throws Exception { 20 | Coneflower flower = new Coneflower(); 21 | Assert.assertEquals("", flower.methodThrowingNPE()); 22 | } 23 | 24 | @Test 25 | public void testThrowException() throws Exception { 26 | Coneflower flower = new Coneflower(); 27 | Assert.assertEquals("failing", 0, flower.throwingException()); 28 | } 29 | } -------------------------------------------------------------------------------- /src/test/resources/foo/src/main/java/Foo.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Arrays; 3 | import java.util.List; 4 | 5 | public class Foo { 6 | public String field = null; 7 | public String[] array = null; 8 | 9 | public Foo() { 10 | super(); 11 | field = null; 12 | array = null; 13 | } 14 | 15 | public void foo() { 16 | field.toString(); 17 | } 18 | 19 | public Object foo2() { 20 | String result = ""; 21 | for (String element : array) { 22 | result += element.toString(); 23 | if(element == null) { 24 | return null; 25 | } 26 | } 27 | return result; 28 | } 29 | 30 | public String fooLocal() { 31 | System.out.print(field.toLowerCase()); 32 | if(field == null) { 33 | return ""; 34 | } 35 | return field; 36 | } 37 | 38 | public String fooGlobal() { 39 | System.out.print(field.toLowerCase()); 40 | if(field == null) { 41 | return ""; 42 | } 43 | return field; 44 | } 45 | 46 | 47 | public String usePreviousVaribaleLocal() { 48 | String empty = "Init"; 49 | field = field.concat("expectedOutput"); 50 | if(field == null) { 51 | return ""; 52 | } 53 | return field; 54 | } 55 | 56 | public String usePreviousVaribaleGlobal() { 57 | String empty = "Init"; 58 | field = field.concat("expectedOutput"); 59 | if(field == null) { 60 | return ""; 61 | } 62 | return field; 63 | } 64 | 65 | 66 | public void returnVoid() { 67 | field = field.concat("expectedOutput"); 68 | if(field == null) { 69 | return; 70 | } 71 | return; 72 | } 73 | 74 | public void notnull() { 75 | if(field == null) { 76 | return; 77 | } else { 78 | field = field.concat("expectedOutput"); 79 | } 80 | return; 81 | } 82 | 83 | public void multiCatch() { 84 | try { 85 | 86 | } catch (IllegalArgumentException | NullPointerException e) { 87 | e.printStackTrace(); 88 | } 89 | } 90 | 91 | public void genericInMethodType() { 92 | List var = new ArrayList<>(); 93 | if(var.get(0).toString().equals("")) { 94 | 95 | } 96 | } 97 | 98 | public static void genericWithoutExtendsInMethodType() { 99 | List var = new ArrayList<>(); 100 | if(var.get(0).toString().equals("")) { 101 | 102 | } 103 | } 104 | 105 | public void multiDecisionLine() { 106 | Arrays.asList(field.toString(), field.toString()); 107 | } 108 | 109 | public void elseIf() { 110 | if (field == array[0]) { 111 | 112 | } else if (array[0].isEmpty()) { 113 | 114 | } 115 | } 116 | } -------------------------------------------------------------------------------- /src/test/resources/foo/src/main/java/Foo2.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Arrays; 3 | import java.util.List; 4 | 5 | public class Foo2 { 6 | public String field = null; 7 | public String[] array = null; 8 | 9 | public Foo2() { 10 | super(); 11 | field.toString(); 12 | field = null; 13 | array = null; 14 | } 15 | } -------------------------------------------------------------------------------- /src/test/resources/foo/src/main/java/FooArrayAccess.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Arrays; 3 | import java.util.List; 4 | 5 | public class FooArrayAccess { 6 | 7 | public String emtpyArray() { 8 | String[] array = new String[0]; 9 | return array[0]; 10 | } 11 | 12 | public String indexToSmall() { 13 | String[] array = new String[]{"Test"}; 14 | return array[-1]; 15 | } 16 | 17 | public String indexToBig() { 18 | String[] array = new String[]{"Test"}; 19 | return array[1]; 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /src/test/resources/foo/src/main/java/FooTernary.java: -------------------------------------------------------------------------------- 1 | public class FooTernary { 2 | 3 | String field; 4 | 5 | public String m1() { 6 | String local = (field == null?"": field); 7 | if(field == null) { 8 | System.out.println("test"); 9 | } 10 | return (field == null?"": field); 11 | } 12 | 13 | public void m2(String parm) { 14 | field = (parm == null?"": parm); 15 | } 16 | 17 | public static void add(Object[] array, Object element) { 18 | Class type = array != null ? array.getClass() : element != null ? element.getClass() : Object.class; 19 | } 20 | } -------------------------------------------------------------------------------- /src/test/resources/foo/src/main/java/ImplicitCast.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.List; 3 | import java.util.Objects; 4 | 5 | public class ImplicitCast { 6 | 7 | private int field; 8 | 9 | public int implicitCastReturn() { 10 | return new Integer(null); 11 | } 12 | 13 | public void implicitLocalVariable() { 14 | int i = new Integer(null); 15 | } 16 | 17 | public void implicitAssignment() { 18 | field = new Integer(null); 19 | } 20 | 21 | public void implicitAssignmentVariable() { 22 | Integer value = new Integer(null); 23 | field = value; 24 | } 25 | 26 | public void implicitInvocation() { 27 | List>> list = new ArrayList<>(); 28 | if(!list.get(0).isEmpty()) { 29 | List objects = list.get(0); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/test/resources/foo/src/test/java/FooArrayAccessTest.java: -------------------------------------------------------------------------------- 1 | import org.junit.Assert; 2 | import org.junit.Test; 3 | 4 | public class FooArrayAccessTest { 5 | 6 | @Test 7 | public void fooTest() { 8 | FooArrayAccess foo = new FooArrayAccess(); 9 | foo.emtpyArray(); 10 | } 11 | 12 | @Test 13 | public void fooTest1() { 14 | FooArrayAccess foo = new FooArrayAccess(); 15 | foo.indexToSmall(); 16 | } 17 | 18 | 19 | @Test 20 | public void fooTest2() { 21 | FooArrayAccess foo = new FooArrayAccess(); 22 | foo.indexToBig(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/resources/foo/src/test/java/FooClassTest.java: -------------------------------------------------------------------------------- 1 | import org.junit.Assert; 2 | import org.junit.Test; 3 | 4 | public class FooClassTest { 5 | 6 | @Test 7 | public void fooTest() { 8 | Foo foo = new Foo(); 9 | foo.foo(); 10 | } 11 | 12 | @Test 13 | public void foo1Test() { 14 | Foo foo = new Foo(); 15 | foo.foo2(); 16 | } 17 | 18 | @Test 19 | public void fooLocalTest() { 20 | Foo foo = new Foo(); 21 | String result = foo.fooLocal(); 22 | Assert.assertEquals("", result); 23 | } 24 | 25 | @Test 26 | public void fooGlobalTest() { 27 | Foo foo = new Foo(); 28 | String result = foo.fooLocal(); 29 | Assert.assertEquals("", result); 30 | } 31 | 32 | @Test 33 | public void fooVariableLocalTest() { 34 | Foo foo = new Foo(); 35 | String result = foo.usePreviousVaribaleLocal(); 36 | Assert.assertEquals("", result); 37 | } 38 | 39 | @Test 40 | public void fooVariableGlobalTest() { 41 | Foo foo = new Foo(); 42 | String result = foo.usePreviousVaribaleGlobal(); 43 | Assert.assertEquals("InitexpectedOutput", result); 44 | } 45 | 46 | @Test 47 | public void returnVoidTest() { 48 | Foo foo = new Foo(); 49 | foo.returnVoid(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /targets: -------------------------------------------------------------------------------- 1 | col-331:collections-331 src /home/bcornu/workspace/collections-331-o/src 2 | test:test src/main/java /home/bcornu/workspace/test-spooned/src2 3 | lang-304:lang-304 src /home/bcornu/workspace/lang-304-o/src 4 | lang-587:lang-587 src /home/bcornu/workspace/lang-587-o/src 5 | lang-703:lang-703 src /home/bcornu/workspace/lang-703-o/src 6 | math-290:math-290 src /home/bcornu/workspace/math-290-o/src 7 | math-305:math-305 src /home/bcornu/workspace/math-305-o/src 8 | math-369:math-369 src /home/bcornu/workspace/math-369-o/src 9 | math988a:math-988a src /home/bcornu/workspace/math-988a-o/src 10 | math988b:math-988b src /home/bcornu/workspace/math-988b-o/src 11 | math-1115:math-1115 src /home/bcornu/workspace/math-1115-o/src 12 | math-1117:math-1117 src2/main/java /home/bcornu/workspace/math-1117-o/src 13 | 01-mckoi:01-Mckoi src /home/bcornu/workspace/01-Mckoi-th/src 14 | 02-freemarker107:02-freemarker src /home/bcornu/workspace/02-freemarker-o/src 15 | 03-jfreechart687:03-jfreechart src /home/bcornu/workspace/03-jfreechart-o/src 16 | --------------------------------------------------------------------------------