private boolean checkVarContextProvider(final TypeMirror typeMirror) {
        final TypeElement element = (TypeElement) types.asElement(typeMirror);
        if (varContextProviders.contains(typeMirror)) { // this VarContextProvider is already processed
            return true;
        }

        if (!element.getKind().isInterface()) { //check whether class is interface
            messager.printMessage(
                    Diagnostic.Kind.ERROR,
                    format(
                            "%s should be interface",
                            element
                    ),
                    element
            );
            return false;
        }

        boolean extendsVariableContext = extendsVariableContext(element);

        if (!extendsVariableContext) { //check whether interface extends VariableContext
            messager.printMessage(
                    Diagnostic.Kind.ERROR,
                    format(
                            "%s should be extending %s",
                            element,
                            VariableContext.class.getName()
                    ),
                    element
            );
            return false;
        }

        final List<Variable> elements = new ArrayList<>();
        final VarContextProvider varContextProvider = element.getAnnotation(VarContextProvider.class);

        if (varContextProvider == null) { //must be annotated with @VarContextProvider
            messager.printMessage(
                    Diagnostic.Kind.ERROR,
                    format(
                            "%s should be annotated with @VarContextProvider",
                            element
                    ),
                    element
            );
            return false;
        }

        //check methods of interface
        for (Element enclosed : element.getEnclosedElements()) {
            final Var annotation = enclosed.getAnnotation(Var.class);
            if (annotation != null) {
                final ExecutableType executableType = (ExecutableType) enclosed.asType();
                final Name simpleName = enclosed.getSimpleName();
                // check name of method

                //should not have method with names info, debug, error,...
                final List<String> logLevelsMethodNames = Arrays.stream(
                        LogLevel.values()
                )
                        .map(
                                LogLevel::getLevelMethodName
                        )
                        .collect(
                                Collectors.toList()
                        );

                //should not have method with names infoEvent, debugEvent, errorEvent,...
                final List<String> logEventMethodNames = Arrays.stream(
                        LogLevel.values()
                )
                        .map(
                                LogLevel::getLogEventMethodName
                        )
                        .collect(
                                Collectors.toList()
                        );

                List<String> loggingEventFieldNames =
                        Arrays.stream(LoggingEvent.class.getDeclaredFields()).map(e -> e.getName()).collect(Collectors.toList());
                if (
                        simpleName.contentEquals("log") || //should not have method with name log
                        logLevelsMethodNames.stream().anyMatch(simpleName::contentEquals) ||
                        logEventMethodNames.stream().anyMatch(simpleName::contentEquals) ||
                        loggingEventFieldNames.stream().anyMatch(simpleName::contentEquals)
                   )
                {
                    messager.printMessage(
                            Diagnostic.Kind.ERROR,
                            format(
                                    "%s interface cannot have method named %s",
                                    element,
                                    simpleName
                            ),
                            element
                    );
                    return false;
                }
                if (!executableType.getReturnType().toString().equals(typeMirror.toString())) { //check return type
                    messager.printMessage(
                            Diagnostic.Kind.ERROR,
                            format(
                                    "%s.%s method must have return type %s",
                                    element,
                                    simpleName,
                                    element
                            ),
                            element
                    );
                    return false;
                }
                if (executableType.getParameterTypes().size() != 1) { //check number of parameters
                    messager.printMessage(
                            Diagnostic.Kind.ERROR,
                            format(
                                    "%s.%s method must have exactly one argument",
                                    element,
                                    simpleName
                            ),
                            element);
                    return false;
                }
                if (elements.stream().map(Variable::getName).anyMatch(e -> e.contentEquals(simpleName))) { //check whether there is no method with same name
                    messager.printMessage(
                            Diagnostic.Kind.ERROR,
                            format(
                                    "%s.%s method cannot be overloaded",
                                    element,
                                    simpleName
                            ),
                            element
                    );
                    return false;
                }
                elements.add(new Variable(simpleName, executableType.getParameterTypes().get(0)));
            }
        }
        if (elements.isEmpty()) { //
            messager.printMessage(
                    Diagnostic.Kind.WARNING,
                    format(
                            "%s has no @Var annotated methods",
                            element
                    ),
                    element
            );
        }
        varsHashMap.put(typeMirror, new VariableContextProvider(typeMirror, elements, varContextProvider.parametrization()));
        varContextProviders.add(typeMirror);
        return true;
    }
private boolean checkVarContextProvider ( final TypeMirror typeMirror ) { final TypeElement element = ( TypeElement ) types . asElement ( typeMirror ) ; if ( varContextProviders . contains ( typeMirror ) ) { return true ; } if ( ! element . getKind ( ) . isInterface ( ) ) { messager . printMessage ( Diagnostic . Kind . ERROR , format ( "%s should be interface" , element ) , element ) ; return false ; } boolean extendsVariableContext = extendsVariableContext ( element ) ; if ( ! extendsVariableContext ) { messager . printMessage ( Diagnostic . Kind . ERROR , format ( "%s should be extending %s" , element , VariableContext . class . getName ( ) ) , element ) ; return false ; } final List < Variable > elements = new ArrayList < > ( ) ; final VarContextProvider varContextProvider = element . getAnnotation ( VarContextProvider . class ) ; if ( varContextProvider == null ) { messager . printMessage ( Diagnostic . Kind . ERROR , format ( "%s should be annotated with @VarContextProvider" , element ) , element ) ; return false ; } for ( Element enclosed : element . getEnclosedElements ( ) ) { final Var annotation = enclosed . getAnnotation ( Var . class ) ; if ( annotation != null ) { final ExecutableType executableType = ( ExecutableType ) enclosed . asType ( ) ; final Name simpleName = enclosed . getSimpleName ( ) ; final List < String > logLevelsMethodNames = Arrays . stream ( LogLevel . values ( ) ) . map ( LogLevel :: getLevelMethodName ) . collect ( Collectors . toList ( ) ) ; final List < String > logEventMethodNames = Arrays . stream ( LogLevel . values ( ) ) . map ( LogLevel :: getLogEventMethodName ) . collect ( Collectors . toList ( ) ) ; List < String > loggingEventFieldNames = Arrays . stream ( LoggingEvent . class . getDeclaredFields ( ) ) . map ( e -> e . getName ( ) ) . collect ( Collectors . toList ( ) ) ; if ( simpleName . contentEquals ( "log" ) || logLevelsMethodNames . stream ( ) . anyMatch ( simpleName :: contentEquals ) || logEventMethodNames . stream ( ) . anyMatch ( simpleName :: contentEquals ) || loggingEventFieldNames . stream ( ) . anyMatch ( simpleName :: contentEquals ) ) { messager . printMessage ( Diagnostic . Kind . ERROR , format ( "%s interface cannot have method named %s" , element , simpleName ) , element ) ; return false ; } if ( ! executableType . getReturnType ( ) . toString ( ) . equals ( typeMirror . toString ( ) ) ) { messager . printMessage ( Diagnostic . Kind . ERROR , format ( "%s.%s method must have return type %s" , element , simpleName , element ) , element ) ; return false ; } if ( executableType . getParameterTypes ( ) . size ( ) != 1 ) { messager . printMessage ( Diagnostic . Kind . ERROR , format ( "%s.%s method must have exactly one argument" , element , simpleName ) , element ) ; return false ; } if ( elements . stream ( ) . map ( Variable :: getName ) . anyMatch ( e -> e . contentEquals ( simpleName ) ) ) { messager . printMessage ( Diagnostic . Kind . ERROR , format ( "%s.%s method cannot be overloaded" , element , simpleName ) , element ) ; return false ; } elements . add ( new Variable ( simpleName , executableType . getParameterTypes ( ) . get ( 0 ) ) ) ; } } if ( elements . isEmpty ( ) ) { messager . printMessage ( Diagnostic . Kind . WARNING , format ( "%s has no @Var annotated methods" , element ) , element ) ; } varsHashMap . put ( typeMirror , new VariableContextProvider ( typeMirror , elements , varContextProvider . parametrization ( ) ) ) ; varContextProviders . add ( typeMirror ) ; return true ; }
checks VarContextProvider, whether it is interface, extends VariableContext, is properly annotated, contains proper logging variable methods
@param typeMirror of VarContextProvider
@return false when VarContextProvider is not valid