protected Map<Statement, Double> buildCodeFragmentFor(CtType cl, Coverage coverage) { Factory factory = cl.getFactory(); Map<Statement, Double> codeFragments = new LinkedHashMap<>(); for (CtMethod<?> mth : (Set<CtMethod>) cl.getMethods()) { if (!mth.getModifiers().contains(ModifierKind.ABSTRACT) && !mth.getModifiers().contains(ModifierKind.PRIVATE)) { // && getCoverageForMethod(coverage, cl, mth) != 1.0) { CtExecutableReference executableRef = factory.Executable().createReference(mth); executableRef.setStatic(mth.getModifiers().contains(ModifierKind.STATIC)); CtInvocation invocation = factory.Code().createInvocation(buildVarRef(cl.getReference(), factory), executableRef); invocation.setArguments( mth.getParameters() .stream() .map(param -> buildVarRef(param.getType(), factory)) .collect(Collectors.toList())); invocation.setType(mth.getType()); Statement stmt = new Statement(invocation); codeFragments.put(stmt, getCoverageForMethod(coverage, cl, mth)); } } return codeFragments; }
/** * Creates a method by copying an existing method. * * @param <T> the type of the method * @param target the target type where the new method has to be inserted to * @param source the source method to be copied * @param redirectReferences tells if all the references to the owning type of the source method * should be redirected to the target type (true is recommended for most uses) * @return the newly created method */ public <T> CtMethod<T> create(CtType<?> target, CtMethod<T> source, boolean redirectReferences) { CtMethod<T> newMethod = factory.Core().clone(source); if (redirectReferences && (source.getDeclaringType() != null)) { Substitution.redirectTypeReferences( newMethod, source.getDeclaringType().getReference(), target.getReference()); } target.getMethods().add(newMethod); return newMethod; }
@Test public void testBasicAPIUsage() throws Exception { // this test shows a basic usage of the Launcher API without command line // and asserts there is no exception SpoonAPI spoon = new Launcher(); spoon.addInputResource("src/test/resources/spoon/test/api"); spoon.setSourceOutputDirectory("target/spooned"); spoon.run(); Factory factory = spoon.getFactory(); for (CtPackage p : factory.Package().getAll()) { spoon.getEnvironment().debugMessage("package: " + p.getQualifiedName()); } for (CtType<?> s : factory.Class().getAll()) { spoon.getEnvironment().debugMessage("class: " + s.getQualifiedName()); } }
public CtBlock getDummyStringIf() { CtMethod<?> dummyIf = type.getElements(new NameFilter<CtMethod<?>>("UselessPositiveIfWithString")).get(0); return dummyIf.getBody(); }
// example usage (please do not use directly, use instead the spoon.Launcher // API to create the factory) public static void main(String[] args) throws Exception { Launcher main = new Launcher(); JDTBasedSpoonCompiler comp = new JDTBasedSpoonCompiler(main.createFactory()); comp.createBatchCompiler().printUsage(); SpoonFile file = new FileSystemFile(new File("./src/main/java/spoon/support/compiler/JDTCompiler.java")); comp.addInputSource(file); try { comp.build(); final Set<CtType<?>> types = comp.getFactory().Package().get("spoon.support.compiler").getTypes(); for (CtType<?> type : types) { main.getEnvironment().debugMessage(type.toString()); } } catch (Exception e) { throw new RuntimeException(e); } }
protected CtType findClassUnderTest(CtType testClass) { String testClassName = testClass.getQualifiedName(); return AmplificationHelper.computeClassProvider(testClass) .stream() .filter(cl -> cl != null) .filter(cl -> cl != testClass) .filter(cl -> testClassName.contains(cl.getSimpleName())) .findFirst() .orElse(null); }
private ITypeModel processType(CtType<?> classElement) { String qualifiedName = classElement.getQualifiedName(); TypeModel type = (TypeModel) registry.getType(qualifiedName); if (type == null) { type = new TypeModel(); type.setFullyQualifiedName(qualifiedName); } registry.registerType(type); fillBasic(type, classElement); fillTypeParameters(type, classElement); if (classElement instanceof CtType) { CtTypeReference<?> superClass = classElement.getSuperclass(); if (superClass != null) { ITypeModel superType = processTypeReference(superClass); type.setSuperClass(superType); } Set<CtTypeReference<?>> interfaces = classElement.getSuperInterfaces(); if (interfaces != null) { ArrayList<ITypeModel> list = new ArrayList<ITypeModel>(); for (CtTypeReference<?> ref : interfaces) { ITypeModel tm = this.processTypeReference(ref); if (tm != null) { list.add(tm); } } type.setImplementedInterfaces(list.toArray(new ITypeModel[list.size()])); } Set<CtMethod<?>> methods = ((CtType<?>) classElement).getMethods(); for (CtMethod<?> m : methods) { IMethodModel methodModel = processMethod(m, type); type.addMethod(methodModel); } Collection<CtField<?>> fields = ((CtType<?>) classElement).getFields(); for (CtField<?> m : fields) { IFieldModel methodModel = processField(m, type); type.addField(methodModel); } } return type; }
@Test public void superInvocationWithEnclosingInstance() throws Exception { /** * To extend a nested class an enclosing instance must be provided to call the super * constructor. */ String sourcePath = "./src/test/resources/spoon/test/prettyprinter/NestedSuperCall.java"; List<SpoonResource> files = SpoonResourceHelper.resources(sourcePath); assertEquals(1, files.size()); SpoonCompiler comp = new Launcher().createCompiler(); comp.addInputSources(files); comp.build(); Factory factory = comp.getFactory(); CtType<?> theClass = factory.Type().get("spoon.test.prettyprinter.NestedSuperCall"); assertTrue(theClass.toString().contains("nc.super(\"a\")")); }
public void init() { type = null; try { type = getLoops(); } catch (Exception e) { System.out.println("Fail to get dummy loop : " + e); } if (type != null) { this.ifs = type.getElements(new TypeFilter<CtIf>(CtIf.class)); } }
public static Set<CtType> computeClassProvider(CtType testClass) { List<CtType> types = Query.getElements(testClass.getParent(CtPackage.class), new TypeFilter(CtType.class)); types = types .stream() .filter(type -> type != null) .filter(type -> type.getPackage() != null) .filter( type -> type.getPackage() .getQualifiedName() .equals(testClass.getPackage().getQualifiedName())) .collect(Collectors.toList()); if (testClass.getParent(CtType.class) != null) { types.add(testClass.getParent(CtType.class)); } types.addAll( types.stream().flatMap(type -> getImport(type).stream()).collect(Collectors.toSet())); return types.stream().collect(Collectors.toSet()); }
@Test public void testSearchMethodWithGeneric() throws Exception { CtType<Tacos> aTacos = buildClass(Tacos.class); CtMethod<Object> method1 = aTacos.getMethod("method1", aTacos.getFactory().Type().integerType()); assertEquals( "public <T extends java.lang.Integer> void method1(T t) {" + System.lineSeparator() + "}", method1.toString()); method1 = aTacos.getMethod("method1", aTacos.getFactory().Type().stringType()); assertEquals( "public <T extends java.lang.String> void method1(T t) {" + System.lineSeparator() + "}", method1.toString()); method1 = aTacos.getMethod("method1", aTacos.getFactory().Type().objectType()); assertEquals( "public <T> void method1(T t) {" + System.lineSeparator() + "}", method1.toString()); }
protected double getCoverageForMethod(Coverage coverage, CtType cl, CtMethod mth) { if (coverage == null) { return 0d; } String key = mth.getDeclaringType().getQualifiedName() + "_" + mth.getType().getQualifiedName() + "_" + mth.getSimpleName() + "(" + mth.getParameters() .stream() .map(param -> ((CtParameter) param).getType().getQualifiedName()) .collect(Collectors.joining(",")) + ")"; if (coverage.getMethodCoverage(key) != null) { return coverage.getMethodCoverage(key).coverage(); } else { key = cl.getQualifiedName() + "_" + mth.getType().getQualifiedName() + "_" + mth.getSimpleName() + "(" + mth.getParameters() .stream() .map(param -> ((CtParameter) param).getType().getQualifiedName()) .collect(Collectors.joining(",")) + ")"; if (coverage.getMethodCoverage(key) != null) { return coverage.getMethodCoverage(key).coverage(); } else { return 0d; } } }
/** * Creates an empty method. * * @param target the class where the method is inserted * @param modifiers the modifiers * @param returnType the method's return type * @param name the method's name * @param parameters the parameters * @param thrownTypes the thrown types */ public <T> CtMethod<T> create( CtType<?> target, Set<ModifierKind> modifiers, CtTypeReference<T> returnType, String name, List<CtParameter<?>> parameters, Set<CtTypeReference<? extends Throwable>> thrownTypes) { CtMethod<T> method = factory.Core().createMethod(); target.addMethod(method); if (modifiers != null) { method.setModifiers(modifiers); } method.setType(returnType); method.setSimpleName(name); if (parameters != null) { method.setParameters(parameters); } if (thrownTypes != null) { method.setThrownTypes(thrownTypes); } return method; }
public CtStatement apply(CtType<?> targetType) { CtClass<?> c; Factory factory; // we first need a factory if (targetType != null) { // if it's template with reference replacement factory = targetType.getFactory(); } else { // else we have at least one template parameter with a factory factory = getFactory(); } c = factory.Class().get(this.getClass()); if (c == null) { c = factory.Class().get(this.getClass()); } // we substitute the first statement of method statement CtStatement result = factory.Core().clone(c.getMethod("statement").getBody().getStatements().get(0)); new SubstitutionVisitor(factory, targetType, this).scan(result); return result; }
@Test public void testStackedAssignments() throws Exception { CtType<StackedAssignmentSample> type = buildClass(StackedAssignmentSample.class); List<CtAssignment> l = type.getElements(new TypeFilter<>(CtAssignment.class)); assertEquals(3, l.size()); }
protected void generateProcessedSourceFilesUsingCUs() { factory.getEnvironment().debugMessage("Generating source using compilation units..."); // Check output directory if (outputDirectory == null) { throw new RuntimeException("You should set output directory before generating source files"); } // Create spooned directory if (outputDirectory.isFile()) { throw new RuntimeException("Output must be a directory"); } if (!outputDirectory.exists()) { if (!outputDirectory.mkdirs()) { throw new RuntimeException("Error creating output directory"); } } try { outputDirectory = outputDirectory.getCanonicalFile(); } catch (IOException e1) { throw new SpoonException(e1); } factory.getEnvironment().debugMessage("Generating source files to: " + outputDirectory); List<File> printedFiles = new ArrayList<File>(); for (spoon.reflect.cu.CompilationUnit cu : factory.CompilationUnit().getMap().values()) { factory .getEnvironment() .debugMessage("Generating source for compilation unit: " + cu.getFile()); CtType<?> element = cu.getMainType(); CtPackage pack = element.getPackage(); // create package directory File packageDir; if (pack.getQualifiedName().equals(CtPackage.TOP_LEVEL_PACKAGE_NAME)) { packageDir = new File(outputDirectory.getAbsolutePath()); } else { // Create current package directory packageDir = new File( outputDirectory.getAbsolutePath() + File.separatorChar + pack.getQualifiedName().replace('.', File.separatorChar)); } if (!packageDir.exists()) { if (!packageDir.mkdirs()) { throw new RuntimeException("Error creating output directory"); } } // print type try { File file = new File( packageDir.getAbsolutePath() + File.separatorChar + element.getSimpleName() + DefaultJavaPrettyPrinter.JAVA_FILE_EXTENSION); file.createNewFile(); // the path must be given relatively to to the working directory InputStream is = getCompilationUnitInputStream(cu.getFile().getPath()); IOUtils.copy(is, new FileOutputStream(file)); if (!printedFiles.contains(file)) { printedFiles.add(file); } } catch (Exception e) { Launcher.LOGGER.error(e.getMessage(), e); } } }
@SuppressWarnings("unchecked") private <T, U extends CtVariable<T>> U getVariableDeclaration( final String name, final Class<U> clazz) { final CoreFactory coreFactory = jdtTreeBuilder.getFactory().Core(); final TypeFactory typeFactory = jdtTreeBuilder.getFactory().Type(); final ClassFactory classFactory = jdtTreeBuilder.getFactory().Class(); final InterfaceFactory interfaceFactory = jdtTreeBuilder.getFactory().Interface(); final FieldFactory fieldFactory = jdtTreeBuilder.getFactory().Field(); final ReferenceBuilder referenceBuilder = jdtTreeBuilder.getReferencesBuilder(); final Environment environment = jdtTreeBuilder.getFactory().getEnvironment(); // there is some extra work to do if we are looking for CtFields (and subclasses) final boolean lookingForFields = clazz == null || coreFactory.createField().getClass().isAssignableFrom(clazz); // try to find the variable on stack beginning with the most recent element for (final ASTPair astPair : stack) { // the variable may have been declared directly by one of these elements final ScopeRespectingVariableScanner<U> scanner = new ScopeRespectingVariableScanner(name, clazz); astPair.element.accept(scanner); if (scanner.getResult() != null) { return scanner.getResult(); } // the variable may have been declared in a super class/interface if (lookingForFields && astPair.node instanceof TypeDeclaration) { final TypeDeclaration nodeDeclaration = (TypeDeclaration) astPair.node; final Deque<ReferenceBinding> referenceBindings = new ArrayDeque<>(); // add super class if any if (nodeDeclaration.superclass != null && nodeDeclaration.superclass.resolvedType instanceof ReferenceBinding) { referenceBindings.push((ReferenceBinding) nodeDeclaration.superclass.resolvedType); } // add interfaces if any if (nodeDeclaration.superInterfaces != null) { for (final TypeReference tr : nodeDeclaration.superInterfaces) { if (tr.resolvedType instanceof ReferenceBinding) { referenceBindings.push((ReferenceBinding) tr.resolvedType); } } } while (!referenceBindings.isEmpty()) { final ReferenceBinding referenceBinding = referenceBindings.pop(); for (final FieldBinding fieldBinding : referenceBinding.fields()) { if (name.equals(new String(fieldBinding.readableName()))) { final String qualifiedNameOfParent = new String(referenceBinding.readableName()); final CtType parentOfField = referenceBinding.isClass() ? classFactory.create(qualifiedNameOfParent) : interfaceFactory.create(qualifiedNameOfParent); return (U) fieldFactory.create( parentOfField, JDTTreeBuilderQuery.getModifiers(fieldBinding.modifiers), referenceBuilder.getTypeReference(fieldBinding.type), name); } } // add super class if any final ReferenceBinding superclass = referenceBinding.superclass(); if (superclass != null) { referenceBindings.push(superclass); } // add interfaces if any final ReferenceBinding[] interfaces = referenceBinding.superInterfaces(); if (interfaces != null) { for (ReferenceBinding rb : interfaces) { referenceBindings.push(rb); } } } } } // the variable may have been imported statically from another class/interface if (lookingForFields) { final CtReference potentialReferenceToField = referenceBuilder.getDeclaringReferenceFromImports(name.toCharArray()); if (potentialReferenceToField != null && potentialReferenceToField instanceof CtTypeReference) { final CtTypeReference typeReference = (CtTypeReference) potentialReferenceToField; try { final Class classOfType = typeReference.getActualClass(); if (classOfType != null) { final CtType declaringTypeOfField = typeReference.isInterface() ? interfaceFactory.get(classOfType) : classFactory.get(classOfType); final CtField field = declaringTypeOfField.getField(name); if (field != null) { return (U) field; } } } catch (final SpoonClassNotFoundException scnfe) { // in noclasspath mode we do some heuristics to determine if `name` could be a // field that has been imported statically from another class (or interface). if (environment.getNoClasspath()) { // if `potentialReferenceToField` is a `CtTypeReference` then `name` must // have been imported statically. Otherwise, `potentialReferenceToField` // would be a CtPackageReference! // if `name` consists only of upper case characters separated by '_', we // assume a constant value according to JLS. if (name.toUpperCase().equals(name)) { final CtType parentOfField = classFactory.create(typeReference.getQualifiedName()); // it is the best thing we can do final CtField field = coreFactory.createField(); field.setParent(parentOfField); field.setSimpleName(name); // it is the best thing we can do field.setType(typeFactory.nullType()); return (U) field; } } } } } return null; }
@Test public void testRHS() throws Exception { CtType<RHSSample> type = buildClass(RHSSample.class); assertEquals(4, type.getElements(new TypeFilter<>(CtRHSReceiver.class)).size()); }