Search in sources :

Example 26 with SpoonException

use of spoon.SpoonException in project repairnator by Spirals-Team.

the class NopolRepair method businessExecute.

@Override
protected void businessExecute() {
    this.getLogger().debug("Start to use nopol to repair...");
    this.setPipelineState(PipelineState.NOPOL_NOTPATCHED);
    Metrics metric = this.inspector.getJobStatus().getMetrics();
    List<URL> classPath = this.inspector.getJobStatus().getRepairClassPath();
    File[] sources = this.inspector.getJobStatus().getRepairSourceDir();
    if (classPath != null && sources != null) {
        String[] sourcesStr = new String[sources.length];
        int i = 0;
        for (File f : sources) {
            sourcesStr[i++] = f.getAbsolutePath();
        }
        List<FailureLocation> failureLocationList = new ArrayList<>(this.inspector.getJobStatus().getFailureLocations());
        Collections.sort(failureLocationList, new ComparatorFailureLocation());
        boolean patchCreated = false;
        int passingTime = 0;
        for (FailureLocation failureLocation : failureLocationList) {
            Set<String> erroringTests = failureLocation.getErroringMethods();
            Set<String> failingTests = failureLocation.getFailingMethods();
            // this one is used to loop on Nopol over tests to ignore. It can be a list containing an empty list.
            List<List<String>> listOfTestToIgnore = new ArrayList<>();
            boolean ignoreError = false;
            // in that case: no tests to ignore
            if (erroringTests.isEmpty() || failingTests.isEmpty()) {
                listOfTestToIgnore.add(new ArrayList<>());
            // then we will first try to ignore erroring tests, then to ignore failing tests
            } else {
                listOfTestToIgnore.add(new ArrayList<>(erroringTests));
                listOfTestToIgnore.add(new ArrayList<>(failingTests));
                ignoreError = true;
            }
            for (List<String> testsToIgnore : listOfTestToIgnore) {
                NopolInformation nopolInformation;
                if (testsToIgnore.isEmpty()) {
                    nopolInformation = new NopolInformation(failureLocation, IgnoreStatus.NOTHING_TO_IGNORE);
                } else {
                    if (ignoreError) {
                        nopolInformation = new NopolInformation(failureLocation, IgnoreStatus.IGNORE_ERRORING);
                        ignoreError = false;
                    } else {
                        nopolInformation = new NopolInformation(failureLocation, IgnoreStatus.IGNORE_FAILING);
                    }
                }
                this.nopolInformations.add(nopolInformation);
                nopolInformation.setStatus(NopolStatus.RUNNING);
                String testClass = failureLocation.getClassName();
                int timeout = (TOTAL_MAX_TIME - passingTime) / 2;
                if (timeout < MIN_TIMEOUT) {
                    timeout = MIN_TIMEOUT;
                }
                nopolInformation.setAllocatedTime(timeout);
                this.getLogger().debug("Launching repair with Nopol for following test class: " + testClass + " (should timeout in " + timeout + " minutes)");
                NopolContext nopolContext = new NopolContext(sources, classPath.toArray(new URL[classPath.size()]), new String[] { testClass }, testsToIgnore);
                nopolContext.setComplianceLevel(8);
                nopolContext.setTimeoutTestExecution(300);
                nopolContext.setMaxTimeEachTypeOfFixInMinutes(15);
                nopolContext.setMaxTimeInMinutes(timeout);
                nopolContext.setLocalizer(NopolContext.NopolLocalizer.COCOSPOON);
                nopolContext.setSolverPath(this.getConfig().getZ3solverPath());
                nopolContext.setSynthesis(NopolContext.NopolSynthesis.DYNAMOTH);
                nopolContext.setType(RepairType.COND_THEN_PRE);
                nopolContext.setOnlyOneSynthesisResult(false);
                nopolContext.setOutputFolder(this.getInspector().getRepoLocalPath());
                nopolInformation.setNopolContext(nopolContext);
                SolverFactory.setSolver(nopolContext.getSolver(), nopolContext.getSolverPath());
                long beforeNopol = new Date().getTime();
                try {
                    final NoPol nopol = new NoPol(nopolContext);
                    Factory spoonFactory = nopol.getSpooner().spoonFactory();
                    List<PatchAndDiff> patchAndDiffs = new ArrayList<>();
                    final ExecutorService executor = Executors.newSingleThreadExecutor();
                    final Future<NopolResult> nopolExecution = executor.submit(new Callable<NopolResult>() {

                        @Override
                        public NopolResult call() throws Exception {
                            NopolResult result = null;
                            try {
                                result = nopol.build();
                            } catch (RuntimeException e) {
                                addStepError("Got runtime exception while running Nopol", e);
                            }
                            return result;
                        }
                    });
                    try {
                        executor.shutdown();
                        NopolResult result = nopolExecution.get(nopolContext.getMaxTimeInMinutes(), TimeUnit.MINUTES);
                        if (result == null) {
                            result = nopol.getNopolResult();
                        }
                        nopolInformation.setNbStatements(result.getNbStatements());
                        nopolInformation.setNbAngelicValues(result.getNbAngelicValues());
                        String failureLocationWithoutDots = failureLocation.getClassName().replace('.', '/');
                        metric.addAngelicValueByTest(failureLocationWithoutDots, result.getNbAngelicValues());
                        List<Patch> patches = result.getPatches();
                        if (patches != null && !patches.isEmpty()) {
                            for (Patch patch : patches) {
                                String diff = patch.toDiff(spoonFactory, nopolContext);
                                patchAndDiffs.add(new PatchAndDiff(patch, diff));
                            }
                            nopolInformation.setPatches(patchAndDiffs);
                            nopolInformation.setStatus(NopolStatus.PATCH);
                            patchCreated = true;
                        } else {
                            nopolInformation.setStatus(NopolStatus.NOPATCH);
                        }
                    } catch (TimeoutException exception) {
                        this.addStepError("Timeout: execution time > " + nopolContext.getMaxTimeInMinutes() + " " + TimeUnit.MINUTES);
                        nopolExecution.cancel(true);
                        executor.shutdownNow();
                        nopolInformation.setStatus(NopolStatus.TIMEOUT);
                        NopolResult result = nopol.getNopolResult();
                        nopolInformation.setNbStatements(result.getNbStatements());
                        nopolInformation.setNbAngelicValues(result.getNbAngelicValues());
                    } catch (InterruptedException | ExecutionException e) {
                        this.addStepError(e.getMessage());
                        nopolExecution.cancel(true);
                        executor.shutdownNow();
                        nopolInformation.setStatus(NopolStatus.EXCEPTION);
                        nopolInformation.setExceptionDetail(e.getMessage());
                        NopolResult result = nopol.getNopolResult();
                        nopolInformation.setNbStatements(result.getNbStatements());
                        nopolInformation.setNbAngelicValues(result.getNbAngelicValues());
                    }
                } catch (SpoonException e) {
                    this.addStepError(e.getMessage());
                    nopolInformation.setStatus(NopolStatus.EXCEPTION);
                    nopolInformation.setExceptionDetail(e.getMessage());
                }
                long afterNopol = new Date().getTime();
                nopolInformation.setDateEnd();
                int localPassingTime = Math.round((afterNopol - beforeNopol) / 60000);
                nopolInformation.setPassingTime(localPassingTime);
                passingTime += localPassingTime;
            }
        }
        File nopolLog = new File(System.getProperty("user.dir"), "debug.log");
        if (nopolLog.exists()) {
            String nopolDestName = "repairnator.nopol.log";
            File nopolDest = new File(this.getInspector().getRepoLocalPath(), nopolDestName);
            try {
                Files.move(nopolLog.toPath(), nopolDest.toPath());
                this.getInspector().getJobStatus().addFileToPush(nopolDestName);
            } catch (IOException e) {
                getLogger().error("Error while renaming nopol log", e);
            }
        }
        File nopolProperties = new File(this.getInspector().getRepoLocalPath() + "/repairnator.nopol.results");
        this.getInspector().getJobStatus().addFileToPush("repairnator.nopol.results");
        File patchDir = new File(this.getInspector().getRepoLocalPath() + "/repairnatorPatches");
        patchDir.mkdir();
        try {
            BufferedWriter writer = new BufferedWriter(new FileWriter(nopolProperties));
            int infoNumber = 0;
            for (NopolInformation information : this.nopolInformations) {
                String informationStr = "nopolinfo #" + (infoNumber++) + "\n" + "location: " + information.getLocation() + "\n" + "status: " + information.getStatus().name() + "\n" + "dateEnd: " + information.getDateEnd().toString() + "\n" + "allocatedtime: " + information.getAllocatedTime() + "minutes \n" + "passingTime: " + information.getPassingTime() + "minutes \n" + "nb patches: " + information.getPatches().size() + "\n" + "nopol context: " + information.getNopolContext() + "\n" + "exception: " + information.getExceptionDetail() + "\n" + "nbStatements: " + information.getNbStatements() + "\n" + "nbAngelicValues: " + information.getNbAngelicValues() + "\n" + "ignoreStatus: " + information.getIgnoreStatus().name() + "\n" + "----------\n\n";
                writer.write(informationStr);
                writer.newLine();
                writer.newLine();
                writer.flush();
                int patchNumber = 0;
                for (PatchAndDiff patchAndDiff : information.getPatches()) {
                    File patchFile = new File(patchDir.getPath() + "/" + information.getLocation().getClassName() + "_patch_" + (patchNumber++));
                    Patch patch = patchAndDiff.getPatch();
                    BufferedWriter patchWriter = new BufferedWriter(new FileWriter(patchFile));
                    String patchWrite = "location: " + patch.getSourceLocation() + "\n" + "type: " + patch.getType() + "\n" + "patch: " + patchAndDiff.getDiff();
                    patchWriter.write(patchWrite);
                    patchWriter.flush();
                    patchWriter.close();
                }
            }
            writer.close();
        } catch (IOException e) {
            this.addStepError("Error while writing nopol informations");
            this.getLogger().error("Error while writing nopol informations", e);
        }
        if (!patchCreated) {
            this.addStepError("No patch has been generated by Nopol. Look at the trace to get more information.");
            return;
        }
        this.setPipelineState(PipelineState.NOPOL_PATCHED);
        this.getInspector().getJobStatus().setHasBeenPatched(true);
        List<String> nopolPatches = new ArrayList<>();
        for (NopolInformation information : this.nopolInformations) {
            for (PatchAndDiff p : information.getPatches()) {
                nopolPatches.add(p.getDiff());
            }
        }
        this.getInspector().getJobStatus().setNopolPatches(nopolPatches);
    } else {
        this.addStepError("No classpath or sources directory has been given. Nopol can't be launched.");
    }
}
Also used : NopolContext(fr.inria.lille.repair.common.config.NopolContext) FileWriter(java.io.FileWriter) Factory(spoon.reflect.factory.Factory) SolverFactory(fr.inria.lille.commons.synthesis.smt.solver.SolverFactory) URL(java.net.URL) BufferedWriter(java.io.BufferedWriter) ComparatorFailureLocation(fr.inria.spirals.repairnator.process.testinformation.ComparatorFailureLocation) Metrics(fr.inria.spirals.repairnator.process.inspectors.Metrics) NoPol(fr.inria.lille.repair.nopol.NoPol) PatchAndDiff(fr.inria.spirals.repairnator.process.nopol.PatchAndDiff) NopolInformation(fr.inria.spirals.repairnator.process.nopol.NopolInformation) ComparatorFailureLocation(fr.inria.spirals.repairnator.process.testinformation.ComparatorFailureLocation) FailureLocation(fr.inria.spirals.repairnator.process.testinformation.FailureLocation) NopolResult(fr.inria.lille.repair.nopol.NopolResult) SpoonException(spoon.SpoonException) IOException(java.io.IOException) SpoonException(spoon.SpoonException) IOException(java.io.IOException) File(java.io.File) Patch(fr.inria.lille.repair.common.patch.Patch)

Example 27 with SpoonException

use of spoon.SpoonException in project repairnator by Spirals-Team.

the class AstorRepair method businessExecute.

@Override
protected void businessExecute() {
    this.getLogger().info("Start to repair using Astor");
    JobStatus jobStatus = this.getInspector().getJobStatus();
    List<String> astorPatches = new ArrayList<>();
    List<URL> classPath = this.inspector.getJobStatus().getRepairClassPath();
    File[] sources = this.inspector.getJobStatus().getRepairSourceDir();
    if (classPath != null && sources != null) {
        List<String> dependencies = new ArrayList<>();
        for (URL url : jobStatus.getRepairClassPath()) {
            if (url.getFile().endsWith(".jar")) {
                dependencies.add(url.getPath());
            }
        }
        final List<String> astorArgs = new ArrayList<>();
        astorArgs.add("-dependencies");
        astorArgs.add(StringUtils.join(dependencies, ":"));
        astorArgs.add("-mode");
        astorArgs.add("jgenprog");
        astorArgs.add("-location");
        astorArgs.add(jobStatus.getFailingModulePath());
        String relativeSourcePath = new File(jobStatus.getFailingModulePath()).toURI().relativize(jobStatus.getRepairSourceDir()[0].toURI()).getPath();
        astorArgs.add("-srcjavafolder");
        astorArgs.add(relativeSourcePath);
        astorArgs.add("-stopfirst");
        astorArgs.add("true");
        astorArgs.add("-population");
        astorArgs.add("1");
        // astorArgs.add("-loglevel");
        // astorArgs.add("DEBUG");
        astorArgs.add("-parameters");
        astorArgs.add("timezone:Europe/Paris:maxnumbersolutions:3:limitbysuspicious:false:maxmodificationpoints:1000:javacompliancelevel:8:logfilepath:" + this.getInspector().getRepoLocalPath() + "/repairnator.astor.log");
        astorArgs.add("-maxtime");
        astorArgs.add(MAX_TIME_EXECUTION + "");
        astorArgs.add("-seed");
        astorArgs.add("1");
        final AstorMain astorMain = new AstorMain();
        final ExecutorService executor = Executors.newSingleThreadExecutor();
        final Future<AstorOutputStatus> astorExecution = executor.submit(new Callable<AstorOutputStatus>() {

            @Override
            public AstorOutputStatus call() throws Exception {
                AstorOutputStatus status = null;
                try {
                    astorMain.execute(astorArgs.toArray(new String[0]));
                    if (astorMain.getEngine() != null) {
                        status = astorMain.getEngine().getOutputStatus();
                    } else {
                        status = AstorOutputStatus.ERROR;
                    }
                } catch (SpoonException e) {
                    status = AstorOutputStatus.ERROR;
                    addStepError("Got SpoonException while running Astor", e);
                } catch (RuntimeException e) {
                    addStepError("Got runtime exception while running Astor", e);
                    status = AstorOutputStatus.ERROR;
                }
                return status;
            }
        });
        AstorOutputStatus status = null;
        try {
            executor.shutdown();
            status = astorExecution.get(MAX_TIME_EXECUTION, TimeUnit.MINUTES);
            if (astorMain.getEngine() != null) {
                List<ProgramVariant> solutions = astorMain.getEngine().getSolutions();
                if (solutions != null) {
                    for (ProgramVariant pv : solutions) {
                        if (pv.isSolution()) {
                            astorPatches.add(pv.getPatchDiff());
                        }
                    }
                }
            }
        } catch (Exception e) {
            status = AstorOutputStatus.ERROR;
            this.addStepError("Error while executing astor with args: " + StringUtils.join(astorArgs, ","), e);
        }
        jobStatus.addFileToPush("repairnator.astor.log");
        jobStatus.setAstorPatches(astorPatches);
        jobStatus.setAstorStatus(status);
        String jsonpath;
        try {
            jsonpath = astorMain.getEngine().getProjectFacade().getProperties().getWorkingDirRoot() + File.separator + ConfigurationProperties.getProperty("jsonoutputname") + ".json";
        } catch (NullPointerException e) {
            jsonpath = null;
        }
        if (jsonpath != null) {
            File jsonResultFile = new File(jsonpath);
            if (jsonResultFile.exists()) {
                try {
                    FileUtils.copyFile(jsonResultFile, new File(this.getInspector().getRepoLocalPath() + "/repairnator.astor.results.json"));
                } catch (IOException e) {
                    this.addStepError("Error while moving astor JSON results", e);
                }
                JsonParser jsonParser = new JsonParser();
                try {
                    JsonElement root = jsonParser.parse(new FileReader(jsonResultFile));
                    this.getInspector().getJobStatus().setAstorResults(root);
                } catch (FileNotFoundException e) {
                    this.addStepError("Error while reading astor JSON results", e);
                }
                jobStatus.addFileToPush("repairnator.astor.results.json");
            }
        }
        if (astorPatches.isEmpty()) {
            this.setPipelineState(PipelineState.ASTOR_NOTPATCHED);
        } else {
            this.setPipelineState(PipelineState.ASTOR_PATCHED);
            this.getInspector().getJobStatus().setHasBeenPatched(true);
        }
    }
}
Also used : ArrayList(java.util.ArrayList) FileNotFoundException(java.io.FileNotFoundException) ProgramVariant(fr.inria.astor.core.entities.ProgramVariant) URL(java.net.URL) JobStatus(fr.inria.spirals.repairnator.process.inspectors.JobStatus) FileReader(java.io.FileReader) JsonParser(com.google.gson.JsonParser) SpoonException(spoon.SpoonException) IOException(java.io.IOException) AstorOutputStatus(fr.inria.main.AstorOutputStatus) SpoonException(spoon.SpoonException) IOException(java.io.IOException) FileNotFoundException(java.io.FileNotFoundException) AstorMain(fr.inria.main.evolution.AstorMain) JsonElement(com.google.gson.JsonElement) ExecutorService(java.util.concurrent.ExecutorService) File(java.io.File)

Example 28 with SpoonException

use of spoon.SpoonException in project spoon by INRIA.

the class CtRenameLocalVariableRefactoring method detectNameConflicts.

@Override
protected void detectNameConflicts() {
    /*
		 * There can be these conflicts
		 * 1) target variable would shadow before declared variable (parameter, localVariable, catchVariable)
		 * --------------------------------------------------------------------------------------------------
		 */
    PotentialVariableDeclarationFunction potentialDeclarationFnc = new PotentialVariableDeclarationFunction(newName);
    CtVariable<?> var = getTarget().map(potentialDeclarationFnc).first();
    if (var != null) {
        if (var instanceof CtField) {
        /*
				 * we have found a field of same name.
				 * It is not problem, because variables can hide field declaration.
				 * Do nothing - OK
				 */
        } else if (potentialDeclarationFnc.isTypeOnTheWay()) {
            /*
				 * There is a local class declaration between future variable reference and variable declaration `var`.
				 * The found variable declaration `var` can be hidden by target variable with newName
				 * as long as there is no reference to `var` in visibility scope of the target variable.
				 * So search for such `var` reference now
				 */
            CtVariableReference<?> shadowedVar = target.map(new SiblingsFunction().includingSelf(true).mode(Mode.NEXT)).map(new VariableReferenceFunction(var)).first();
            if (shadowedVar != null) {
                // found variable reference, which would be shadowed by variable after rename.
                createNameConflictIssue(var, shadowedVar);
            } else {
            /*
					 * there is no local variable reference, which would be shadowed by variable after rename.
					 * OK
					 */
            }
        } else {
            /*
				 * the found variable is in conflict with target variable with newName
				 */
            createNameConflictIssue(var);
        }
    }
    /*
		 * 2) target variable is shadowed by later declared variable
		 * ---------------------------------------------------------
		 */
    final QueryDriver queryDriver = new QueryDriver();
    getTarget().map(new LocalVariableScopeFunction(queryDriver)).select(new Filter<CtElement>() {

        /**
         * return true for all CtVariables, which are in conflict
         */
        @Override
        public boolean matches(CtElement element) {
            if (element instanceof CtType<?>) {
                CtType<?> localClass = (CtType<?>) element;
                // TODO use faster hasField, implemented using map(new AllFieldsFunction()).select(new NameFilter(newName)).first()!=null
                Collection<CtFieldReference<?>> fields = localClass.getAllFields();
                for (CtFieldReference<?> fieldRef : fields) {
                    if (newName.equals(fieldRef.getSimpleName())) {
                        /*
							 * we have found a local class field, which will shadow input local variable if it's reference is in visibility scope of that field.
							 * Search for target variable reference in visibility scope of this field.
							 * If found than we cannot rename target variable to newName, because that reference would be shadowed
							 */
                        queryDriver.ignoreChildrenOf(element);
                        CtLocalVariableReference<?> shadowedVar = element.map(new LocalVariableReferenceFunction(target)).first();
                        if (shadowedVar != null) {
                            createNameConflictIssue(fieldRef.getFieldDeclaration(), shadowedVar);
                            return true;
                        }
                        return false;
                    }
                }
                return false;
            }
            if (element instanceof CtVariable<?>) {
                CtVariable<?> variable = (CtVariable<?>) element;
                if (newName.equals(variable.getSimpleName()) == false) {
                    // the variable with different name. Ignore it
                    return false;
                }
                // we have found a variable with new name
                if (variable instanceof CtField) {
                    throw new SpoonException("This should not happen. The children of local class which contains a field with new name should be skipped!");
                }
                if (variable instanceof CtCatchVariable || variable instanceof CtLocalVariable || variable instanceof CtParameter) {
                    /*
						 * we have found a catch variable or local variable or parameter with new name.
						 */
                    if (queryDriver.isInContextOfLocalClass()) {
                        /*
							 * We are in context of local class.
							 * This variable would shadow input local variable after rename
							 * so we cannot rename if there exist a local variable reference in variable visibility scope.
							 */
                        queryDriver.ignoreChildrenOf(variable.getParent());
                        CtQueryable searchScope;
                        if (variable instanceof CtLocalVariable) {
                            searchScope = variable.map(new SiblingsFunction().includingSelf(true).mode(Mode.NEXT));
                        } else {
                            searchScope = variable.getParent();
                        }
                        CtLocalVariableReference<?> shadowedVar = searchScope.map(new LocalVariableReferenceFunction(target)).first();
                        if (shadowedVar != null) {
                            // found local variable reference, which would be shadowed by variable after rename.
                            createNameConflictIssue(variable, shadowedVar);
                            return true;
                        }
                        // there is no local variable reference, which would be shadowed by variable after rename.
                        return false;
                    } else {
                        /*
							 * We are not in context of local class.
							 * So this variable is in conflict. Return it
							 */
                        createNameConflictIssue(variable);
                        return true;
                    }
                } else {
                    // Any new variable type???
                    throw new SpoonException("Unexpected variable " + variable.getClass().getName());
                }
            }
            return false;
        }
    }).first();
}
Also used : CtVariableReference(spoon.reflect.reference.CtVariableReference) SiblingsFunction(spoon.reflect.visitor.filter.SiblingsFunction) SpoonException(spoon.SpoonException) CtElement(spoon.reflect.declaration.CtElement) VariableReferenceFunction(spoon.reflect.visitor.filter.VariableReferenceFunction) LocalVariableReferenceFunction(spoon.reflect.visitor.filter.LocalVariableReferenceFunction) CtFieldReference(spoon.reflect.reference.CtFieldReference) CtParameter(spoon.reflect.declaration.CtParameter) CtLocalVariable(spoon.reflect.code.CtLocalVariable) CtType(spoon.reflect.declaration.CtType) Filter(spoon.reflect.visitor.Filter) CtField(spoon.reflect.declaration.CtField) CtQueryable(spoon.reflect.visitor.chain.CtQueryable) CtVariable(spoon.reflect.declaration.CtVariable) PotentialVariableDeclarationFunction(spoon.reflect.visitor.filter.PotentialVariableDeclarationFunction) CtCatchVariable(spoon.reflect.code.CtCatchVariable) LocalVariableScopeFunction(spoon.reflect.visitor.filter.LocalVariableScopeFunction) LocalVariableReferenceFunction(spoon.reflect.visitor.filter.LocalVariableReferenceFunction)

Example 29 with SpoonException

use of spoon.SpoonException in project spoon by INRIA.

the class Refactoring method copyMethod.

/**
 * See doc in {@link CtMethod#copyMethod()}
 */
public static CtMethod<?> copyMethod(final CtMethod<?> method) {
    CtMethod<?> clone = method.clone();
    String tentativeTypeName = method.getSimpleName() + "Copy";
    CtType parent = method.getParent(CtType.class);
    while (parent.getMethodsByName(tentativeTypeName).size() > 0) {
        tentativeTypeName += "X";
    }
    final String cloneMethodName = tentativeTypeName;
    clone.setSimpleName(cloneMethodName);
    parent.addMethod(clone);
    new CtScanner() {

        @Override
        public <T> void visitCtExecutableReference(CtExecutableReference<T> reference) {
            CtExecutable<T> declaration = reference.getDeclaration();
            if (declaration == null) {
                return;
            }
            if (declaration == method) {
                reference.setSimpleName(cloneMethodName);
            }
            if (reference.getDeclaration() != clone) {
                throw new SpoonException("post condition broken " + reference);
            }
            super.visitCtExecutableReference(reference);
        }
    }.scan(clone);
    return clone;
}
Also used : CtType(spoon.reflect.declaration.CtType) SpoonException(spoon.SpoonException) CtScanner(spoon.reflect.visitor.CtScanner) CtExecutable(spoon.reflect.declaration.CtExecutable)

Example 30 with SpoonException

use of spoon.SpoonException in project spoon by INRIA.

the class ReplaceParametrizedTest method testContract.

@Test
public void testContract() throws Throwable {
    List<String> problems = new ArrayList<>();
    // contract: all elements are replaceable wherever they are in the model
    // this test puts them at all possible locations
    CtType<?> toTest = typeToTest.getModelInterface();
    CtElement o = factory.Core().create((Class<? extends CtElement>) toTest.getActualClass());
    for (MetamodelProperty mmField : typeToTest.getRoleToProperty().values()) {
        Class<?> argType = mmField.getItemValueType().getActualClass();
        if (!CtElement.class.isAssignableFrom(argType)) {
            continue;
        }
        CtTypeReference<?> itemType = mmField.getItemValueType();
        // special cases...
        if (itemType.getQualifiedName().equals(CtStatement.class.getName())) {
            // the children of CtLoop wraps CtStatement into an implicit CtBlock. So make a block directly to test plain get/set and not wrapping.
            itemType = factory.createCtTypeReference(CtBlock.class);
        }
        if (o.getClass().getSimpleName().equals("CtAnnotationFieldAccessImpl") && mmField.getRole() == CtRole.VARIABLE) {
            itemType = factory.createCtTypeReference(CtFieldReference.class);
        } else if (CtFieldAccess.class.isAssignableFrom(o.getClass()) && mmField.getRole() == CtRole.VARIABLE) {
            itemType = factory.createCtTypeReference(CtFieldReference.class);
        }
        CtElement argument = (CtElement) createCompatibleObject(itemType);
        assertNotNull(argument);
        // we create a fresh object
        CtElement receiver = ((CtElement) o).clone();
        RoleHandler rh = RoleHandlerHelper.getRoleHandler(o.getClass(), mmField.getRole());
        if (mmField.isUnsettable()) {
            try {
                // we invoke the setter
                invokeSetter(rh, receiver, argument);
            } catch (SpoonException e) {
                // ok this unsettable property has no setter at all
                return;
            }
            // this unsettable property has setter, but it should do nothing
            CtRole argumentsRoleInParent = argument.getRoleInParent();
            if (argumentsRoleInParent == null) {
                // OK - unsettable property set no value
                continue;
            }
            if (argumentsRoleInParent == mmField.getRole()) {
                problems.add("UnsettableProperty " + mmField + " sets the value");
            } else {
                if (mmField.isDerived()) {
                // it is OK, that setting of value into derived unsettable field influences other field
                // Example 1: CtCatchVariable.setType(x) influences result of getMultitype()
                // Example 2: CtEnumValue.setAssignment(x) influences result of getDefaultExpression()
                } else {
                    problems.add("UnsettableProperty " + mmField + " sets the value into different role " + argumentsRoleInParent);
                }
            }
            continue;
        }
        // we invoke the setter
        invokeSetter(rh, receiver, argument);
        // contract: a property setter sets properties that are visitable by a scanner
        CtElement finalArgument = argument;
        class Scanner extends CtScanner {

            boolean found = false;

            @Override
            public void scan(CtRole role, CtElement e) {
                super.scan(role, e);
                if (e == finalArgument) {
                    if (rh.getRole() == role || rh.getRole().getSuperRole() == role) {
                        found = true;
                        return;
                    }
                    // if (rh.getRole()==CtRole.TYPE && role==CtRole.MULTI_TYPE) {
                    // //CtCatchVaraible#type sets CtCatchVaraible#multiType - OK
                    // found = true;
                    // return;
                    // }
                    problems.add("Argument was set into " + rh.getRole() + " but was found in " + role);
                }
            }
        }
        ;
        Scanner s = new Scanner();
        receiver.accept(s);
        assertTrue("Settable field " + mmField.toString() + " should set value.\n" + getReport(problems), s.found);
        // contract: a property getter on the same role can be used to get the value back
        assertSame(argument, invokeGetter(rh, receiver));
        final CtElement argument2 = argument.clone();
        assertNotSame(argument, argument2);
        // we do the replace
        argument.replace(argument2);
        // the new element is indeed now in this AST
        assertTrue(receiver.getClass().getSimpleName() + " failed for " + mmField, receiver.getElements(new Filter<CtElement>() {

            @Override
            public boolean matches(CtElement element) {
                return element == argument2;
            }
        }).size() == 1);
    }
    if (problems.size() > 0) {
        fail(getReport(problems));
    }
}
Also used : CtScanner(spoon.reflect.visitor.CtScanner) SpoonException(spoon.SpoonException) CtElement(spoon.reflect.declaration.CtElement) RoleHandler(spoon.reflect.meta.RoleHandler) ArrayList(java.util.ArrayList) CtFieldReference(spoon.reflect.reference.CtFieldReference) CtBlock(spoon.reflect.code.CtBlock) CtStatement(spoon.reflect.code.CtStatement) Filter(spoon.reflect.visitor.Filter) MetamodelProperty(spoon.test.metamodel.MetamodelProperty) CtRole(spoon.reflect.path.CtRole) CtScanner(spoon.reflect.visitor.CtScanner) Test(org.junit.Test)

Aggregations

SpoonException (spoon.SpoonException)57 Test (org.junit.Test)15 Launcher (spoon.Launcher)12 CtMethod (spoon.reflect.declaration.CtMethod)9 CtType (spoon.reflect.declaration.CtType)9 CtElement (spoon.reflect.declaration.CtElement)8 Factory (spoon.reflect.factory.Factory)8 File (java.io.File)7 IOException (java.io.IOException)7 ArrayList (java.util.ArrayList)7 CtField (spoon.reflect.declaration.CtField)6 URL (java.net.URL)4 CtTypeReference (spoon.reflect.reference.CtTypeReference)4 Collection (java.util.Collection)3 CompilationUnit (spoon.reflect.cu.CompilationUnit)3 CtExecutable (spoon.reflect.declaration.CtExecutable)3 CtParameter (spoon.reflect.declaration.CtParameter)3 CtScanner (spoon.reflect.visitor.CtScanner)3 Filter (spoon.reflect.visitor.Filter)3 FileNotFoundException (java.io.FileNotFoundException)2