private ArrayList<Diagnostic> identifySchemaLanguage(SchemaNode node) {
        ArrayList<Diagnostic> ret = new ArrayList<>();

        boolean isIdentifier = node.isSchemaASTInstance(identifierStr.class);
        boolean isIdentifierWithDash = node.isSchemaASTInstance(identifierWithDashStr.class);

        if (!isIdentifier && !isIdentifierWithDash) {
            return ret;
        }

        Node rawParent = node.getParent();
        if (rawParent == null) return ret;
        SchemaNode parent = rawParent.getSchemaNode();

        if (fieldReferenceIdentifierParents.contains(parent.getASTClass())) {
            return handleFieldReference(node);
        }

        if (parent.isASTInstance(importField.class)) {
            return handleImportField(node);
        }

        HashMap<Class<?>, SymbolType> searchMap = isIdentifier ? identifierTypeMap : identifierWithDashTypeMap;
        SymbolType symbolType = searchMap.get(parent.getASTClass());
        if (symbolType == null) return ret;


        Optional<Symbol> scope = CSTUtils.findScope(node);
        if (scope.isPresent()) {
            node.setSymbol(symbolType, context.fileURI(), scope.get());
        } else {
            node.setSymbol(symbolType, context.fileURI());
        }
        node.setSymbolStatus(SymbolStatus.UNRESOLVED);

        if (parent.isSchemaASTInstance(referenceType.class)) {
            context.addUnresolvedDocumentReferenceNode(node);
        }

        return ret;
    }
If the parent of an identifier belongs to one of these classes
it will be handled by the {@link IdentifySymbolReferences#handleFieldReference} method.

This involves splitting the identifierStr node into several nodes based on the dot-syntax for fields.
integration/schema-language-server/language-server/src/main/java/ai/vespa/schemals/schemadocument/parser/schema/IdentifySymbolReferences.java