private static void handleStructField(ParseContext context, SchemaNode node, List<Diagnostic> diagnostics) {
        Node prev = node.getPreviousSibling();
        if (prev.getASTClass() == STRUCT_FIELD.class) {
            Node enclosingBodyNode = node.getParent().getParent();

            if (enclosingBodyNode.getASTClass() == fieldBodyElm.class) {
                // struct-field declared inside field
                Node fieldIdentifierNode = enclosingBodyNode.getParent().get(1);

                if (!fieldIdentifierNode.hasSymbol() || fieldIdentifierNode.getSymbol().getStatus() != SymbolStatus.DEFINITION) return;
                Optional<Symbol> subfieldInParent = SymbolReferenceResolver.resolveSubFieldReference(node, fieldIdentifierNode.getSymbol(), context, diagnostics);

                if (subfieldInParent.isEmpty()) return;

                Symbol scope = fieldIdentifierNode.getSymbol();
                createStructFieldDefinition(context, scope, node, subfieldInParent.get());
            } else if (enclosingBodyNode.getASTClass() == structFieldBodyElm.class) {
                // nested struct-field
                // the referred field definition is the last component in the struct-field identifier
                Node lastStructFieldIdentifier = enclosingBodyNode.getParent().get(1);
                while (lastStructFieldIdentifier.getNextSibling() != null && lastStructFieldIdentifier.getNextSibling().getASTClass() == identifierStr.class) {
                    lastStructFieldIdentifier = lastStructFieldIdentifier.getNextSibling();
                }
                if (!lastStructFieldIdentifier.hasSymbol() || lastStructFieldIdentifier.getSymbol().getStatus() != SymbolStatus.DEFINITION) return;

                Optional<Symbol> referredParentFieldDefinition = context.schemaIndex().getFirstSymbolDefinition(lastStructFieldIdentifier.getSymbol());

                if (referredParentFieldDefinition.isEmpty()) return;

                Optional<Symbol> subfieldInParent = SymbolReferenceResolver.resolveSubFieldReference(node, referredParentFieldDefinition.get(), context, diagnostics);

                if (subfieldInParent.isEmpty()) return;

                Symbol scope = lastStructFieldIdentifier.getSymbol();
                createStructFieldDefinition(context, scope, node, subfieldInParent.get());

            }
        } else if (prev.hasSymbol() && prev.getSymbol().getStatus() == SymbolStatus.DEFINITION) {
            // Assume we are in a struct-field statement
            Optional<Symbol> referredParentFieldDefinition = context.schemaIndex().getFirstSymbolDefinition(prev.getSymbol());

            if (referredParentFieldDefinition.isEmpty()) return;

            Optional<Symbol> subfieldInParent = SymbolReferenceResolver.resolveSubFieldReference(node, referredParentFieldDefinition.get(), context, diagnostics);

            if (subfieldInParent.isEmpty()) return;

            Symbol scope = prev.getSymbol();
            createStructFieldDefinition(context, scope, node, subfieldInParent.get());
        }
    }
StructFieldDefinitionResolver
Finds struct-field declarations and turns them into definitions of fields
integration/schema-language-server/language-server/src/main/java/ai/vespa/schemals/schemadocument/resolvers/StructFieldDefinitionResolver.java