private void visitDefinition()

in src/java/apiview-java-processor/src/main/java/com/azure/tools/apiview/processor/analysers/JavaASTAnalyser.java [598:765]


    private void visitDefinition(BodyDeclaration<?> definition, ReviewLine parentLine) {
        boolean isTypeDeclaration = false;
        String id;
        String name;

        if (definition instanceof TypeDeclaration<?>) {
            TypeDeclaration<?> typeDeclaration = (TypeDeclaration<?>) definition;
            // Skip if the class is private or package-private, unless it is a nested type defined inside a public interface
            if (!isTypeAPublicAPI(typeDeclaration)) {
                return;
            }

            // FIXME getKnownTypes is...icky
            id = makeId(typeDeclaration);
            name = typeDeclaration.getNameAsString();
            apiListing.getKnownTypes().put(typeDeclaration.getFullyQualifiedName().orElse(""), id);
            isTypeDeclaration = true;
        } else if (definition instanceof FieldDeclaration) {
            FieldDeclaration fieldDeclaration = (FieldDeclaration) definition;
            id = makeId(fieldDeclaration);
            name = fieldDeclaration.toString();
        } else if (definition instanceof CallableDeclaration<?>) {
            CallableDeclaration<?> callableDeclaration = (CallableDeclaration<?>) definition;
            id = makeId(callableDeclaration);
            name = callableDeclaration.getNameAsString();
        } else {
            System.out.println("Unknown definition type: " + definition.getClass().getName());
            System.exit(-1);
            return;
        }

        // when we are dealing with a type declaration, annotations go on the line *before* the definition,
        // as opposed to fields and methods where they go on the same line
        final boolean showAnnotationsOnNewLine = isTypeDeclaration;

        final ReviewLine definitionLine;

        if (isTypeDeclaration) {
            visitAnnotations(definition, isTypeDeclaration, showAnnotationsOnNewLine, parentLine, id);
            visitJavaDoc(definition, parentLine, id);
            definitionLine = parentLine.addChildLine(new ReviewLine(parentLine, id));
        } else {
            visitJavaDoc(definition, parentLine, id);
            definitionLine = parentLine.addChildLine(new ReviewLine(parentLine, id));
            visitAnnotations(definition, isTypeDeclaration, showAnnotationsOnNewLine, definitionLine, definitionLine);
        }

        // Add modifiers - public, protected, static, final, etc
        for (final Modifier modifier : ((NodeWithModifiers<?>)definition).getModifiers()) {
            definitionLine.addToken(new ReviewToken(KEYWORD, modifier.getKeyword().asString()));
        }

        // for type declarations, add in if it is a class, annotation, enum, interface, etc
        if (definition instanceof TypeDeclaration<?>) {
            TypeDeclaration<?> typeDeclaration = (TypeDeclaration<?>) definition;
            TokenKind kind = getTokenKind(typeDeclaration);
            definitionLine.addToken(new ReviewToken(KEYWORD, kind.getTypeDeclarationString()));

            // Note that it is not necessary to specify the ID here, as it is already specified on the TreeNode
            ReviewToken typeNameToken = new ReviewToken(kind, name)
                .setSpacing(Spacing.NO_SPACE); // no space here - we have to see if there is any type parameters below first

            typeNameToken.setNavigationDisplayName(name);

            possiblyAddNavigationLink(typeNameToken, typeDeclaration);
            possiblyDeprecate(typeNameToken, typeDeclaration);

            checkForCrossLanguageDefinitionId(definitionLine, typeDeclaration);
            definitionLine.addToken(typeNameToken);
        }

        boolean addedSpace = false;

        // Add type parameters for definition
        if (definition instanceof NodeWithTypeParameters<?>) {
            NodeWithTypeParameters<?> d = (NodeWithTypeParameters<?>) definition;
            spacingState = SpacingState.SKIP_NEXT_SUFFIX;
            boolean modified = visitTypeParameters(d.getTypeParameters(), definitionLine);
            spacingState = SpacingState.DEFAULT;

            if (modified) {
                // add the space we skipped earlier, due to the generics
                definitionLine.addSpace();
                addedSpace = true;
            }
        }

        if (!addedSpace && definition instanceof TypeDeclaration<?>) {
            // add the space we skipped earlier, due to the generics
            definitionLine.addSpace();
        }

        // Add type for definition - this is the return type for methods
        visitType(definition, definitionLine, RETURN_TYPE);

        if (definition instanceof FieldDeclaration) {
            // For Fields - we add the field type and name
            visitDeclarationNameAndVariables((FieldDeclaration) definition, definitionLine);
            definitionLine.addToken(new ReviewToken(PUNCTUATION, ";"));
        } else if (definition instanceof CallableDeclaration<?>) {
            // For Methods - Add name and parameters for definition
            CallableDeclaration<?> n = (CallableDeclaration<?>) definition;
            visitDeclarationNameAndParameters(n, n.getParameters(), definitionLine);

            // Add throw exceptions for definition
            visitThrowException(n, definitionLine);
        } else if (definition instanceof TypeDeclaration<?>) {
            TypeDeclaration<?> d = (TypeDeclaration<?>) definition;

            // add in types that we are extending or implementing
            visitExtendsAndImplements((TypeDeclaration<?>) definition, definitionLine);

            definitionLine.addContextStartTokens();

            // now process inner values (e.g. if it is a class, interface, enum, etc
            if (d.isEnumDeclaration()) {
                visitEnumEntries((EnumDeclaration) d, definitionLine);
            }

            // Get if the declaration is interface or not
            boolean isInterfaceDeclaration = isInterfaceType(d);

            // public custom annotation @interface's members
            if (d.isAnnotationDeclaration() && isPublicOrProtected(d.getAccessSpecifier())) {
                final AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration) d;
                visitAnnotationMember(annotationDeclaration, definitionLine);
            }

            // get fields
            visitFields(isInterfaceDeclaration, d, definitionLine);

            // get Constructors
            final List<ConstructorDeclaration> constructors = d.getConstructors();
            if (constructors.isEmpty()) {
                // add default constructor if there is no constructor at all, except interface and enum
                if (!isInterfaceDeclaration && !d.isEnumDeclaration() && !d.isAnnotationDeclaration()) {
                    addDefaultConstructor(d, definitionLine);
                } else {
                    // skip and do nothing if there is no constructor in the interface.
                }
            } else {
                visitConstructorsOrMethods(d, isInterfaceDeclaration, true, constructors, definitionLine);
            }

            // get Methods
            visitConstructorsOrMethods(d, isInterfaceDeclaration, false, d.getMethods(), definitionLine);

            // get Inner classes
            d.getChildNodes()
                .stream()
                .filter(n -> n instanceof TypeDeclaration)
                .map(n -> (TypeDeclaration<?>) n)
                .forEach(innerType -> {
                    if (innerType.isEnumDeclaration() || innerType.isClassOrInterfaceDeclaration()) {
                        visitDefinition(innerType, definitionLine);
                    }
                });

            if (isInterfaceDeclaration) {
                if (d.getMembers().isEmpty()) {
                    // we have an empty interface declaration, it is probably a marker interface and we will leave a
                    // comment to that effect
                    definitionLine.addChildLine().addToken(COMMENT, "// This interface does not declare any API.");
                }
            }
            definitionLine.addContextEndTokens();
        }
    }