io.sundr.dsl.internal.processor.DslProcessor Maven / Gradle / Ivy
/*
* Copyright 2015 The original authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.sundr.dsl.internal.processor;
import io.sundr.codegen.model.ClassRef;
import io.sundr.codegen.model.TypeDef;
import io.sundr.codegen.model.TypeDefBuilder;
import io.sundr.codegen.model.Kind;
import io.sundr.codegen.model.Method;
import io.sundr.codegen.model.MethodBuilder;
import io.sundr.codegen.model.TypeRef;
import io.sundr.codegen.processor.JavaGeneratingProcessor;
import io.sundr.codegen.utils.ModelUtils;
import io.sundr.codegen.utils.TypeUtils;
import io.sundr.dsl.annotations.InterfaceName;
import io.sundr.dsl.internal.graph.Node;
import io.sundr.dsl.internal.graph.NodeContext;
import io.sundr.dsl.internal.graph.functions.Nodes;
import io.sundr.dsl.internal.type.functions.Generics;
import io.sundr.dsl.internal.utils.TypeDefUtils;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import static io.sundr.dsl.internal.Constants.ORIGINAL_REF;
import static io.sundr.dsl.internal.utils.TypeDefUtils.executablesToInterfaces;
import static io.sundr.dsl.internal.Constants.IS_GENERATED;
@SupportedAnnotationTypes("io.sundr.dsl.annotations.Dsl")
public class DslProcessor extends JavaGeneratingProcessor {
public static final String DEFAULT_TEMPLATE_LOCATION = "templates/dsl/dsl.vm";
@Override
public boolean process(Set extends TypeElement> annotations, RoundEnvironment env) {
Elements elements = processingEnv.getElementUtils();
Types types = processingEnv.getTypeUtils();
DslContext context = DslContextManager.create(elements, types);
for (TypeElement annotation : annotations) {
for (Element element : env.getElementsAnnotatedWith(annotation)) {
if (element instanceof TypeElement) {
Generics.clear();
TypeElement typeElement = (TypeElement) element;
InterfaceName interfaceName = element.getAnnotation(InterfaceName.class);
String targetInterface = interfaceName.value();
Set interfacesToGenerate = new LinkedHashSet();
Collection sorted = ElementFilter.methodsIn(typeElement.getEnclosedElements());
//1st step generate generic interface for all types.
Set genericInterfaces = executablesToInterfaces(context, sorted);
Set genericAndScopeInterfaces = Nodes.TO_SCOPE.apply(genericInterfaces);
for (TypeDef clazz : genericAndScopeInterfaces) {
if (!TypeDefUtils.isEntryPoint(clazz)) {
interfacesToGenerate.add(clazz);
}
}
//2nd step create dependency graph.
List methods = new ArrayList();
Set> graph = Nodes.TO_GRAPH.apply(genericAndScopeInterfaces);
for (Node root : graph) {
Node uncyclic = Nodes.TO_UNCYCLIC.apply(root);
Node unwrapped = Nodes.TO_UNWRAPPED.apply(NodeContext.builder().withItem(uncyclic.getItem()).build());
TypeDef current = unwrapped.getItem();
//If there are not transitions don't generate root interface.
//Just add the method with the direct return type.
if (unwrapped.getTransitions().isEmpty()) {
for (Method m : current.getMethods()) {
TypeRef returnType = m.getReturnType();
if (returnType instanceof ClassRef) {
TypeDef toUnwrap = ((ClassRef)returnType).getDefinition();
methods.add(new MethodBuilder(m).withReturnType(Generics.UNWRAP.apply(toUnwrap).toInternalReference()).build());
} else if (returnType.getAttributes().containsKey(ORIGINAL_REF)) {
methods.add(new MethodBuilder(m).withReturnType((TypeRef) returnType.getAttributes().get(ORIGINAL_REF)).build());
} else {
methods.add(new MethodBuilder(m).withReturnType(returnType).build());
}
}
} else {
for (Method m : current.getMethods()) {
methods.add(new MethodBuilder(m).withReturnType(current.toUnboundedReference()).build());
}
interfacesToGenerate.add(Nodes.TO_ROOT.apply(unwrapped));
}
}
//Do generate the DSL interface
interfacesToGenerate.add(new TypeDefBuilder()
.withPackageName(ModelUtils.getPackageElement(element).toString())
.withName(targetInterface)
.withKind(Kind.INTERFACE)
.withModifiers(TypeUtils.modifiersToInt(Modifier.PUBLIC))
.withMethods(methods)
.build());
interfacesToGenerate.addAll(context.getDefinitionRepository().getDefinitions(IS_GENERATED));
try {
for (TypeDef clazz : interfacesToGenerate) {
generateFromClazz(clazz, DEFAULT_TEMPLATE_LOCATION);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
return true;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy