private void verifySymbolFunctionName(SchemaNode node, List<Diagnostic> diagnostics) {
        String functionName = node.getSymbol().getShortIdentifier();
        if (reservedFunctionNames.contains(functionName)) {
            diagnostics.add(new SchemaDiagnostic.Builder()
                .setRange(node.getRange())
                .setMessage("Function '" + node.getText() + "' has a reserved name. This might mean that the function shadows the built-in function with the same name.")
                .setSeverity(DiagnosticSeverity.Warning)
                .build());
        }
    }
For rank expressions.
Example:
tensor<float>(d0[1], d1[10])
d0, and d1 should be marked as definition because they can be referenced in the body.
For this to work, the tensor type itself should also be marked as a definition, in order to give the dimensions a scope.
We will use the hashCode trick to give the tensorType node an unique identifier.
integration/schema-language-server/language-server/src/main/java/ai/vespa/schemals/schemadocument/parser/schema/IdentifySymbolDefinition.java