2

注釈付きクラスを受け取り、そのサブクラスを作成しようとする注釈プロセッサがあります。

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すると、境界ではなく、変数名のみが得られます。これを行う方法についてのアイデアはありますか?

4

1 に答える 1

1

の型パラメータはTypeElementを呼び出すことで取得getTypeParameters()でき、その範囲は取得した を呼び出すことでgetBounds()取得できますTypeParameterElement。私は、あなたが次のステップに悩まされていると仮定しています — それらの境界を満たすために、どの具象型をそれらの型パラメーターに渡す必要がありますか。

残念ながら、これは問題であり、任意の型に対しては簡単に解決できません(これがあなたの求めているものです)。たとえば、次のタイプを見てください。

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 に渡さず、生の型を使用する」です。

于 2016-11-15T08:01:41.777 に答える