modules/ballerina-core/src/main/java/org/ballerinalang/util/semantics/SemanticAnalyzer.java
private void validateAttributes(AnnotationAttachment annotation, AnnotationDef annotationDef) {
        annotation.getAttributeNameValuePairs().forEach((attributeName, attributeValue) -> {
            // Check attribute existence
            BLangSymbol attributeSymbol = annotationDef.resolveMembers(new SymbolName(attributeName));
            if (attributeSymbol == null || !(attributeSymbol instanceof AnnotationAttributeDef)) {
                BLangExceptionHelper.throwSemanticError(annotation, SemanticErrors.NO_SUCH_ATTRIBUTE, 
                    attributeName, annotation.getName());
            }
            
            // Check types
            AnnotationAttributeDef attributeDef = ((AnnotationAttributeDef) attributeSymbol);
            SimpleTypeName attributeType = attributeDef.getTypeName();
            SimpleTypeName valueType = attributeValue.getType();
            BLangSymbol valueTypeSymbol = currentScope.resolve(valueType.getSymbolName());
            BLangSymbol attributeTypeSymbol = annotationDef.resolve(new SymbolName(attributeType.getName(), 
                    attributeType.getPackagePath()));
            
            if (attributeType.isArrayType()) {
                if (!valueType.isArrayType()) {
                    BLangExceptionHelper.throwSemanticError(attributeValue, SemanticErrors.INCOMPATIBLE_TYPES, 
                        attributeTypeSymbol.getSymbolName() + TypeConstants.ARRAY_TNAME, 
                        valueTypeSymbol.getSymbolName());
                }
                
                AnnotationAttributeValue[] valuesArray = attributeValue.getValueArray();
                for (AnnotationAttributeValue value : valuesArray) {
                    valueTypeSymbol = currentScope.resolve(value.getType().getSymbolName());
                    if (attributeTypeSymbol != valueTypeSymbol) {
                        BLangExceptionHelper.throwSemanticError(attributeValue, SemanticErrors.INCOMPATIBLE_TYPES, 
                            attributeTypeSymbol.getSymbolName(), valueTypeSymbol.getSymbolName());
                    }
                    
                    // If the value of the attribute is another annotation, then recursively
                    // traverse to its attributes and validate
                    AnnotationAttachment childAnnotation = value.getAnnotationValue();
                    if (childAnnotation != null && valueTypeSymbol instanceof AnnotationDef) {
                        validateAttributes(childAnnotation, (AnnotationDef) valueTypeSymbol);
                    }
                }
            } else {
                if (valueType.isArrayType()) {
                    BLangExceptionHelper.throwSemanticError(attributeValue, 
                        SemanticErrors.INCOMPATIBLE_TYPES_ARRAY_FOUND, attributeTypeSymbol.getName());
                }
                
                if (attributeTypeSymbol != valueTypeSymbol) {
                    BLangExceptionHelper.throwSemanticError(attributeValue, SemanticErrors.INCOMPATIBLE_TYPES, 
                        attributeTypeSymbol.getSymbolName(), valueTypeSymbol.getSymbolName());
                }
                
                // If the value of the attribute is another annotation, then recursively
                // traverse to its attributes and validate
                AnnotationAttachment childAnnotation = attributeValue.getAnnotationValue();
                if (childAnnotation != null && valueTypeSymbol instanceof AnnotationDef) {
                    validateAttributes(childAnnotation, (AnnotationDef) valueTypeSymbol);
                }
            }
        });
    }
/**
     * Visit and validate attributes of an annotation attachment.
     * 
     * @param annotation Annotation attachment to validate attributes
     * @param annotationDef Definition of the annotation
     */
Visit and validate attributes of an annotation attachment.

@param annotation Annotation attachment to validate attributes
@param annotationDef Definition of the annotation
Visit and validate attributes of an annotation attachment . @param annotation Annotation attachment to validate attributes @param annotationDef Definition of the annotation
private void validateAttributes(AnnotationAttachment annotation, AnnotationDef annotationDef) {
        annotation.getAttributeNameValuePairs().forEach((attributeName, attributeValue) -> {
            BLangSymbol attributeSymbol = annotationDef.resolveMembers(new SymbolName(attributeName));
            if (attributeSymbol == null || !(attributeSymbol instanceof AnnotationAttributeDef)) {
                BLangExceptionHelper.throwSemanticError(annotation, SemanticErrors.NO_SUCH_ATTRIBUTE, 
                    attributeName, annotation.getName());
            }
            AnnotationAttributeDef attributeDef = ((AnnotationAttributeDef) attributeSymbol);
            SimpleTypeName attributeType = attributeDef.getTypeName();
            SimpleTypeName valueType = attributeValue.getType();
            BLangSymbol valueTypeSymbol = currentScope.resolve(valueType.getSymbolName());
            BLangSymbol attributeTypeSymbol = annotationDef.resolve(new SymbolName(attributeType.getName(), 
                    attributeType.getPackagePath()));
            if (attributeType.isArrayType()) {
                if (!valueType.isArrayType()) {
                    BLangExceptionHelper.throwSemanticError(attributeValue, SemanticErrors.INCOMPATIBLE_TYPES, 
                        attributeTypeSymbol.getSymbolName() + TypeConstants.ARRAY_TNAME, 
                        valueTypeSymbol.getSymbolName());
                }
                AnnotationAttributeValue[] valuesArray = attributeValue.getValueArray();
                for (AnnotationAttributeValue value : valuesArray) {
                    valueTypeSymbol = currentScope.resolve(value.getType().getSymbolName());
                    if (attributeTypeSymbol != valueTypeSymbol) {
                        BLangExceptionHelper.throwSemanticError(attributeValue, SemanticErrors.INCOMPATIBLE_TYPES, 
                            attributeTypeSymbol.getSymbolName(), valueTypeSymbol.getSymbolName());
                    }
                    AnnotationAttachment childAnnotation = value.getAnnotationValue();
                    if (childAnnotation != null && valueTypeSymbol instanceof AnnotationDef) {
                        validateAttributes(childAnnotation, (AnnotationDef) valueTypeSymbol);
                    }
                }
            } else {
                if (valueType.isArrayType()) {
                    BLangExceptionHelper.throwSemanticError(attributeValue, 
                        SemanticErrors.INCOMPATIBLE_TYPES_ARRAY_FOUND, attributeTypeSymbol.getName());
                }
                if (attributeTypeSymbol != valueTypeSymbol) {
                    BLangExceptionHelper.throwSemanticError(attributeValue, SemanticErrors.INCOMPATIBLE_TYPES, 
                        attributeTypeSymbol.getSymbolName(), valueTypeSymbol.getSymbolName());
                }
                AnnotationAttachment childAnnotation = attributeValue.getAnnotationValue();
                if (childAnnotation != null && valueTypeSymbol instanceof AnnotationDef) {
                    validateAttributes(childAnnotation, (AnnotationDef) valueTypeSymbol);
                }
            }
        });
    }
private void validateAttributes ( AnnotationAttachment annotation , AnnotationDef annotationDef ) { annotation . getAttributeNameValuePairs ( ) . forEach ( ( attributeName , attributeValue ) -> { BLangSymbol attributeSymbol = annotationDef . resolveMembers ( new SymbolName ( attributeName ) ) ; if ( attributeSymbol == null || ! ( attributeSymbol instanceof AnnotationAttributeDef ) ) { BLangExceptionHelper . throwSemanticError ( annotation , SemanticErrors . NO_SUCH_ATTRIBUTE , attributeName , annotation . getName ( ) ) ; } AnnotationAttributeDef attributeDef = ( ( AnnotationAttributeDef ) attributeSymbol ) ; SimpleTypeName attributeType = attributeDef . getTypeName ( ) ; SimpleTypeName valueType = attributeValue . getType ( ) ; BLangSymbol valueTypeSymbol = currentScope . resolve ( valueType . getSymbolName ( ) ) ; BLangSymbol attributeTypeSymbol = annotationDef . resolve ( new SymbolName ( attributeType . getName ( ) , attributeType . getPackagePath ( ) ) ) ; if ( attributeType . isArrayType ( ) ) { if ( ! valueType . isArrayType ( ) ) { BLangExceptionHelper . throwSemanticError ( attributeValue , SemanticErrors . INCOMPATIBLE_TYPES , attributeTypeSymbol . getSymbolName ( ) + TypeConstants . ARRAY_TNAME , valueTypeSymbol . getSymbolName ( ) ) ; } AnnotationAttributeValue [ ] valuesArray = attributeValue . getValueArray ( ) ; for ( AnnotationAttributeValue value : valuesArray ) { valueTypeSymbol = currentScope . resolve ( value . getType ( ) . getSymbolName ( ) ) ; if ( attributeTypeSymbol != valueTypeSymbol ) { BLangExceptionHelper . throwSemanticError ( attributeValue , SemanticErrors . INCOMPATIBLE_TYPES , attributeTypeSymbol . getSymbolName ( ) , valueTypeSymbol . getSymbolName ( ) ) ; } AnnotationAttachment childAnnotation = value . getAnnotationValue ( ) ; if ( childAnnotation != null && valueTypeSymbol instanceof AnnotationDef ) { validateAttributes ( childAnnotation , ( AnnotationDef ) valueTypeSymbol ) ; } } } else { if ( valueType . isArrayType ( ) ) { BLangExceptionHelper . throwSemanticError ( attributeValue , SemanticErrors . INCOMPATIBLE_TYPES_ARRAY_FOUND , attributeTypeSymbol . getName ( ) ) ; } if ( attributeTypeSymbol != valueTypeSymbol ) { BLangExceptionHelper . throwSemanticError ( attributeValue , SemanticErrors . INCOMPATIBLE_TYPES , attributeTypeSymbol . getSymbolName ( ) , valueTypeSymbol . getSymbolName ( ) ) ; } AnnotationAttachment childAnnotation = attributeValue . getAnnotationValue ( ) ; if ( childAnnotation != null && valueTypeSymbol instanceof AnnotationDef ) { validateAttributes ( childAnnotation , ( AnnotationDef ) valueTypeSymbol ) ; } } } ) ; }
Visit and validate attributes of an annotation attachment.
Visit and validate attributes of an annotation attachment .
// Check attribute existence // Check types // If the value of the attribute is another annotation, then recursively // traverse to its attributes and validate // If the value of the attribute is another annotation, then recursively // traverse to its attributes and validate