2016-11-14 1 views
2

나는 주석 클래스를 취하고 그것의 서브 클래스를 만들려고 시도 주석 프로세서가 :TypeMirror의 경계를 찾아 JavaPoet TypeSpec으로 변환하는 방법은 무엇입니까?

package test; 

import com.squareup.javapoet.ClassName; 
import com.squareup.javapoet.JavaFile; 
import com.squareup.javapoet.TypeSpec; 

import java.io.IOException; 
import java.util.Set; 

import javax.annotation.processing.AbstractProcessor; 
import javax.annotation.processing.ProcessingEnvironment; 
import javax.annotation.processing.RoundEnvironment; 
import javax.annotation.processing.SupportedAnnotationTypes; 
import javax.annotation.processing.SupportedSourceVersion; 
import javax.lang.model.SourceVersion; 
import javax.lang.model.element.Element; 
import javax.lang.model.element.Modifier; 
import javax.lang.model.element.TypeElement; 

@SupportedAnnotationTypes("java.lang.SuppressWarnings") 
@SupportedSourceVersion(SourceVersion.RELEASE_7) 
public class BSProcessor extends AbstractProcessor { 
    @Override 
    public synchronized void init(ProcessingEnvironment processingEnv) { 
     super.init(processingEnv); 
    } 

    @Override 
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnvironment) { 
     for (TypeElement baseClassAnnotation : annotations) { 
      for (Element annotatedElement : roundEnvironment.getElementsAnnotatedWith(baseClassAnnotation)) { 
       handleAnnotatedTypeElement((TypeElement) annotatedElement); 
      } 
     } 
     return true; 
    } 

    private void handleAnnotatedTypeElement(TypeElement annotatedTypeElement) { 
     try { 
      javaFile(annotatedTypeElement).writeTo(System.out); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    private JavaFile javaFile(TypeElement annotatedTypeElement) { 
     return JavaFile.builder(packageName(annotatedTypeElement), typeSpec(annotatedTypeElement)) 
       .build(); 
    } 

    private TypeSpec typeSpec(TypeElement annotatedTypeElement) { 
     return TypeSpec.classBuilder(className(annotatedTypeElement)) 
       .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT) 
       .build(); 
    } 

    private ClassName className(TypeElement annotatedTypeElement) { 
     return ClassName.get(packageName(annotatedTypeElement), String.format("AutoGenerated_%s", 
       annotatedTypeElement.getSimpleName())); 
    } 

    private String packageName(TypeElement annotatedTypeElement) { 
     return annotatedTypeElement.getEnclosingElement().toString(); 
    } 
} 

이 유형의 매개 변수가없는 클래스와 함께 작동하지만, 내가 그들과 함께 그렇게하는 방법을 모르겠어요. 유형 변수에 toString을 수행하면 경계가 아닌 변수 이름 만 제공됩니다. 이 작업을 수행하는 방법에 대한 아이디어가 있습니까? TypeElement

답변

1

유형 매개 변수 getTypeParameters()를 호출하여 검색 할 수 있으며, 자신의 경계를 얻을 TypeParameterElement들에 getBounds()를 호출하는 것으로 취득 할 수 있습니다. 나는 여러분이 다음 단계에서 문제가 있다고 가정하고 있습니다. 어떤 유형이 그러한 유형 매개 변수에 전달되어 그 경계를 만족시켜야한다고 가정합니다.

불행히도 이것은 문제가되는데, 이는 임의의 유형으로 쉽게 해결할 수 없습니다. 예를 들어, 이러한 유형의보고 :

public abstract class Recursive<UU extends Callable<UU>> { 
} 

당신은 그것을 직관적으로이 같은 클래스에 의해 구현 될 수 있다는 결론을 내릴 수 있습니다

public class Solution extends Recursive<Solution> implements Callable<Solution> { 
    @Override 
    public Solution call() throws Exception { 
    return new Solution(); 
    } 
} 

을하지만 자동화 사소한 아니다, 그리고 (아마도) 코드에 필요한 기계류를 포함하고 싶지는 않습니다. 대신 그 문제를 직접 해결하기 위해 노력의

, 당신이 유형의 삭제를 활용하고 컴파일러는 당신을위한 문제를 해결할 수 있도록하는 것이 좋습니다 : 이와 같이

// returns something like "Map<K, V>", this is NOT what you want! 
DeclaredType classType = (DeclaredType) typeElement.asType(); 

Types types = processingEnvironment.getTypeUtils(); 
Elements elements = processingEnvironment.getElementUtils(); 

// this obtains raw type (plain "Map"), with all methods type-erased, 
// the compiler is much better at solving type riddles than you! 
DeclaredType rawType = types.getDeclaredType(typeElement); 

final Collection<? extends ExecutableElement> methods = 
    ElementFilter.methodsIn(elements.getAllMembers(typeElement)); 

// To create a MethodSpec, suitable for the raw type, you should 
// call 3-parameter MethodSpec#overriding with type-erased raw class type 
// as second parameter and javax.lang.model.util.Types instance as third 
MethodSpec newMethod = MethodSpec.overriding(methods.get(0), rawType, types); 

을, 특정 질문에 대한 답은 "돈이다 어떤 유형 매개 변수도 JavaPoet에 전달하지 않고 원시 유형을 사용하십시오. "

+0

감사합니다. 많이 도와 줬어! –