Search in sources :

Example 1 with EndpointDefinition

use of com.palantir.dialogue.annotations.processor.data.EndpointDefinition in project dialogue by palantir.

the class ServiceImplementationGenerator method clientImpl.

private MethodSpec clientImpl(EndpointDefinition def) {
    List<ParameterSpec> params = def.arguments().stream().map(arg -> ParameterSpec.builder(ArgumentTypes.caseOf(arg.argType()).primitive((javaTypeName, _parameterSerializerMethodName, _isList) -> javaTypeName).rawRequestBody(typeName -> typeName).optional((optionalJavaType, _unused) -> optionalJavaType).mapType(typeName -> typeName).customType(typeName -> typeName), arg.argName().get()).build()).collect(Collectors.toList());
    MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(def.endpointName().get()).addModifiers(Modifier.PUBLIC).addParameters(params).addAnnotation(Override.class);
    methodBuilder.addCode("$T $L = $T.builder();", Request.Builder.class, REQUEST, Request.class);
    def.arguments().forEach(arg -> methodBuilder.addCode(generateParam(arg)));
    methodBuilder.returns(def.returns().returnType());
    boolean isAsync = def.returns().asyncInnerType().isPresent();
    String executeCode = isAsync ? "$L.clients().call($L, $L.build(), $L);" : "$L.clients().callBlocking($L, $L.build(), $L);";
    CodeBlock execute = CodeBlock.of(executeCode, serviceDefinition.conjureRuntimeArgName(), def.channelFieldName(), REQUEST, def.returns().deserializerFieldName());
    methodBuilder.addCode(!def.returns().isVoid() || isAsync ? "return $L" : "$L", execute);
    return methodBuilder.build();
}
Also used : OptionalType(com.palantir.dialogue.annotations.processor.data.ArgumentType.OptionalType) Modifier(javax.lang.model.element.Modifier) FieldSpec(com.squareup.javapoet.FieldSpec) ClassName(com.squareup.javapoet.ClassName) Serializer(com.palantir.dialogue.Serializer) ParameterEncoderType(com.palantir.dialogue.annotations.processor.data.ParameterEncoderType) Cases(com.palantir.dialogue.annotations.processor.data.ParameterType.Cases) ParameterSerializer(com.palantir.dialogue.annotations.ParameterSerializer) ErrorHandlingVoidDeserializer(com.palantir.dialogue.annotations.ErrorHandlingVoidDeserializer) Request(com.palantir.dialogue.Request) CodeBlock(com.squareup.javapoet.CodeBlock) DefaultParameterSerializer(com.palantir.dialogue.annotations.DefaultParameterSerializer) ParameterSpec(com.squareup.javapoet.ParameterSpec) ParameterTypes(com.palantir.dialogue.annotations.processor.data.ParameterTypes) Deserializer(com.palantir.dialogue.Deserializer) MethodSpec(com.squareup.javapoet.MethodSpec) EncoderType(com.palantir.dialogue.annotations.processor.data.ParameterEncoderType.EncoderType) ServiceDefinition(com.palantir.dialogue.annotations.processor.data.ServiceDefinition) ParameterizedTypeName(com.squareup.javapoet.ParameterizedTypeName) ReturnType(com.palantir.dialogue.annotations.processor.data.ReturnType) ArgumentTypes(com.palantir.dialogue.annotations.processor.data.ArgumentTypes) TypeSpec(com.squareup.javapoet.TypeSpec) Collectors(java.util.stream.Collectors) ErrorHandlingDeserializerFactory(com.palantir.dialogue.annotations.ErrorHandlingDeserializerFactory) EndpointChannel(com.palantir.dialogue.EndpointChannel) List(java.util.List) ArgumentType(com.palantir.dialogue.annotations.processor.data.ArgumentType) TypeName(com.squareup.javapoet.TypeName) Optional(java.util.Optional) TypeMarker(com.palantir.dialogue.TypeMarker) ArgumentDefinition(com.palantir.dialogue.annotations.processor.data.ArgumentDefinition) EndpointDefinition(com.palantir.dialogue.annotations.processor.data.EndpointDefinition) ParameterSpec(com.squareup.javapoet.ParameterSpec) MethodSpec(com.squareup.javapoet.MethodSpec) Request(com.palantir.dialogue.Request) CodeBlock(com.squareup.javapoet.CodeBlock)

Example 2 with EndpointDefinition

use of com.palantir.dialogue.annotations.processor.data.EndpointDefinition in project dialogue by palantir.

the class DialogueRequestAnnotationsProcessor method generateDialogueServiceFactory.

private JavaFile generateDialogueServiceFactory(Element annotatedInterface, Collection<Element> annotatedMethods) {
    ElementKind kind = annotatedInterface.getKind();
    Preconditions.checkArgument(kind.isInterface(), "Only methods on interfaces can be annotated with @Request");
    Set<Element> nonMethodElements = annotatedMethods.stream().filter(element -> !element.getKind().equals(ElementKind.METHOD)).collect(Collectors.toSet());
    validationStep(ctx -> nonMethodElements.forEach(nonMethodElement -> ctx.reportError("Only methods can be annotated with @Request", nonMethodElement)));
    Preconditions.checkArgument(nonMethodElements.isEmpty(), "Only methods can be annotated with @Request");
    List<EndpointDefinition> endpoints = processingStep(ctx -> {
        EndpointDefinitions endpointDefinitions = new EndpointDefinitions(ctx, elements, types);
        List<Optional<EndpointDefinition>> maybeEndpoints = annotatedMethods.stream().map(MoreElements::asExecutable).map(endpointDefinitions::tryParseEndpointDefinition).collect(Collectors.toList());
        Preconditions.checkArgument(maybeEndpoints.stream().filter(Predicates.not(Optional::isPresent)).collect(Collectors.toList()).isEmpty(), "Failed validation");
        return maybeEndpoints.stream().map(Optional::get).collect(Collectors.toList());
    });
    ClassName serviceInterface = ClassName.get(MoreElements.getPackage(annotatedInterface).getQualifiedName().toString(), annotatedInterface.getSimpleName().toString());
    ServiceDefinition serviceDefinition = ImmutableServiceDefinition.builder().serviceInterface(serviceInterface).addAllEndpoints(endpoints).build();
    TypeSpec generatedClass = new DialogueServiceFactoryGenerator(serviceDefinition).generate();
    TypeSpec withOriginatingElement = generatedClass.toBuilder().addOriginatingElement(annotatedInterface).build();
    MoreElements.getAnnotationMirror(annotatedInterface, DialogueService.class).toJavaUtil().map(mirror -> AnnotationMirrors.getAnnotationValue(mirror, "value")).ifPresent(value -> value.accept(new SimpleAnnotationValueVisitor9<Void, Void>() {

        @Override
        public Void visitType(TypeMirror type, Void _unused) {
            // Quick check, the generated type is expected, however a hand-written
            // type may be used instead. This avoids a class of problems involving
            // dependencies between processor rounds.
            String typeName = type.toString();
            String expectedGenerated = serviceInterface.packageName() + '.' + generatedClass.name;
            if (typeName.equals(expectedGenerated)) {
                return null;
            }
            TypeElement factoryElement = elements.getTypeElement(DialogueServiceFactory.class.getName());
            if (factoryElement == null) {
                return null;
            }
            DeclaredType expectedType = types.getDeclaredType(factoryElement, types.getWildcardType(annotatedInterface.asType(), null));
            if (!types.isAssignable(type, expectedType)) {
                messager.printMessage(Kind.ERROR, "@DialogueService annotation references an " + "invalid DialogueServiceFactory type", annotatedInterface);
            }
            return null;
        }
    }, null));
    return JavaFile.builder(serviceInterface.packageName(), withOriginatingElement).build();
}
Also used : ElementKind(javax.lang.model.element.ElementKind) AbstractProcessor(javax.annotation.processing.AbstractProcessor) CompileTimeConstant(com.google.errorprone.annotations.CompileTimeConstant) ClassName(com.squareup.javapoet.ClassName) TypeElement(javax.lang.model.element.TypeElement) Function(java.util.function.Function) Elements(javax.lang.model.util.Elements) EndpointDefinitions(com.palantir.dialogue.annotations.processor.data.EndpointDefinitions) Kind(javax.tools.Diagnostic.Kind) ImmutableServiceDefinition(com.palantir.dialogue.annotations.processor.data.ImmutableServiceDefinition) DeclaredType(javax.lang.model.type.DeclaredType) Predicates(com.google.common.base.Predicates) DialogueService(com.palantir.dialogue.DialogueService) Arg(com.palantir.logsafe.Arg) Messager(javax.annotation.processing.Messager) Goethe(com.palantir.goethe.Goethe) MoreElements(com.google.auto.common.MoreElements) ImmutableSet(com.google.common.collect.ImmutableSet) ElementKind(javax.lang.model.element.ElementKind) Request(com.palantir.dialogue.annotations.Request) SafeRuntimeException(com.palantir.logsafe.exceptions.SafeRuntimeException) KeyedStream(com.palantir.common.streams.KeyedStream) GoetheException(com.palantir.goethe.GoetheException) SimpleAnnotationValueVisitor9(javax.lang.model.util.SimpleAnnotationValueVisitor9) Collection(java.util.Collection) ServiceDefinition(com.palantir.dialogue.annotations.processor.data.ServiceDefinition) Throwables(com.google.common.base.Throwables) Set(java.util.Set) Element(javax.lang.model.element.Element) TypeSpec(com.squareup.javapoet.TypeSpec) Types(javax.lang.model.util.Types) DialogueServiceFactory(com.palantir.dialogue.DialogueServiceFactory) Collectors(java.util.stream.Collectors) JavaFile(com.squareup.javapoet.JavaFile) Consumer(java.util.function.Consumer) SourceVersion(javax.lang.model.SourceVersion) SafeExceptions(com.palantir.logsafe.exceptions.SafeExceptions) List(java.util.List) TypeMirror(javax.lang.model.type.TypeMirror) FilerException(javax.annotation.processing.FilerException) RoundEnvironment(javax.annotation.processing.RoundEnvironment) Filer(javax.annotation.processing.Filer) ProcessingEnvironment(javax.annotation.processing.ProcessingEnvironment) Optional(java.util.Optional) DialogueServiceFactoryGenerator(com.palantir.dialogue.annotations.processor.generate.DialogueServiceFactoryGenerator) AnnotationMirrors(com.google.auto.common.AnnotationMirrors) Preconditions(com.palantir.logsafe.Preconditions) EndpointDefinition(com.palantir.dialogue.annotations.processor.data.EndpointDefinition) Optional(java.util.Optional) TypeElement(javax.lang.model.element.TypeElement) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) EndpointDefinition(com.palantir.dialogue.annotations.processor.data.EndpointDefinition) SimpleAnnotationValueVisitor9(javax.lang.model.util.SimpleAnnotationValueVisitor9) MoreElements(com.google.auto.common.MoreElements) DialogueServiceFactoryGenerator(com.palantir.dialogue.annotations.processor.generate.DialogueServiceFactoryGenerator) TypeMirror(javax.lang.model.type.TypeMirror) DialogueServiceFactory(com.palantir.dialogue.DialogueServiceFactory) ClassName(com.squareup.javapoet.ClassName) DialogueService(com.palantir.dialogue.DialogueService) ImmutableServiceDefinition(com.palantir.dialogue.annotations.processor.data.ImmutableServiceDefinition) ServiceDefinition(com.palantir.dialogue.annotations.processor.data.ServiceDefinition) EndpointDefinitions(com.palantir.dialogue.annotations.processor.data.EndpointDefinitions) TypeSpec(com.squareup.javapoet.TypeSpec) DeclaredType(javax.lang.model.type.DeclaredType)

Aggregations

EndpointDefinition (com.palantir.dialogue.annotations.processor.data.EndpointDefinition)2 ServiceDefinition (com.palantir.dialogue.annotations.processor.data.ServiceDefinition)2 ClassName (com.squareup.javapoet.ClassName)2 TypeSpec (com.squareup.javapoet.TypeSpec)2 List (java.util.List)2 Optional (java.util.Optional)2 Collectors (java.util.stream.Collectors)2 AnnotationMirrors (com.google.auto.common.AnnotationMirrors)1 MoreElements (com.google.auto.common.MoreElements)1 Predicates (com.google.common.base.Predicates)1 Throwables (com.google.common.base.Throwables)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 CompileTimeConstant (com.google.errorprone.annotations.CompileTimeConstant)1 KeyedStream (com.palantir.common.streams.KeyedStream)1 Deserializer (com.palantir.dialogue.Deserializer)1 DialogueService (com.palantir.dialogue.DialogueService)1 DialogueServiceFactory (com.palantir.dialogue.DialogueServiceFactory)1 EndpointChannel (com.palantir.dialogue.EndpointChannel)1 Request (com.palantir.dialogue.Request)1 Serializer (com.palantir.dialogue.Serializer)1