All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ai.vespa.schemals.index.Symbol Maven / Gradle / Ivy

There is a newer version: 8.441.21
Show newest version
package ai.vespa.schemals.index;

import ai.vespa.schemals.common.FileUtils;
import ai.vespa.schemals.tree.Node;
import ai.vespa.schemals.tree.SchemaNode;

import java.net.URI;

import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.Position;

/**
 * Symbol represents a symbol in a document.
 */
public class Symbol {
    private Node identifierNode;
    private Symbol scope = null;
    private String fileURI;
    private URI fileURIimpl; // for comparing with other symbols file URIs
    private SymbolType type;
    private SymbolStatus status;
    private String overrideShortIdentifier = null;

    public Symbol(Node identifierNode, SymbolType type, String fileURI, Symbol scope, String shortIdentifier) {
        this.identifierNode = identifierNode;
        this.setFileURI(fileURI);
        this.type = type;
        this.status = SymbolStatus.UNRESOLVED;
        this.scope = scope;
        this.overrideShortIdentifier = shortIdentifier;
    }

    public Symbol(Node identifierNode, SymbolType type, String fileURI) {
        this(identifierNode, type, fileURI, null, null);
    }

    public Symbol(Node identifierNode, SymbolType type, String fileURI, Symbol scope) {
        this(identifierNode, type, fileURI, scope, null);
    }

    public String getFileURI() { return fileURI; }
    
    public String setFileURI(String fileURI) {
        this.fileURI = fileURI;
        this.fileURIimpl = URI.create(fileURI);
        return fileURI;
    }

    public boolean fileURIEquals(Symbol other) {
        return fileURIimpl.equals(other.fileURIimpl);
    }

    public boolean fileURIEquals(String otherURI) {
        return fileURIimpl.equals(URI.create(otherURI));
    }

    public boolean fileURIEquals(URI otherURI) {
        return fileURIimpl.equals(otherURI);
    }
    
    public void setType(SymbolType type) { this.type = type; }
    public SymbolType getType() { return type; }
    public void setStatus(SymbolStatus status) { this.status = status; }
    public SymbolStatus getStatus() { return status; }

    public Symbol getScope() { return scope; }
    // Be careful when using this
    public void setScope(Symbol scope) { this.scope = scope; }

    // TODO: not quite sure if this kind of equality check is good
    public boolean isInScope(Symbol scope) {
        if (scope == null || this.scope == null) return false;
        return this.scope.equals(scope);
    }

    public Node getNode() { return identifierNode; }

    public String getShortIdentifier() {
        if (overrideShortIdentifier != null) return overrideShortIdentifier;

        return identifierNode.getText();
    }

    public String getLongIdentifier() {
        if (scope == null) {
            return getShortIdentifier();
        }
        return scope.getLongIdentifier() + "." + getShortIdentifier();
    }

    /*
     * Same as long identifier, but without SCHEMA and DOCUMENT
     * Mainly for rendering purposes in LSP
     */
    public String getPrettyIdentifier() {
        if (type == SymbolType.DOCUMENT || type == SymbolType.SCHEMA) return getShortIdentifier();
        if (scope == null 
                || scope.getType() == SymbolType.DOCUMENT 
                || scope.getType() == SymbolType.SCHEMA) return getShortIdentifier();
        return scope.getPrettyIdentifier() + "." + getShortIdentifier();
    }

    public Location getLocation() {
        return new Location(fileURI, identifierNode.getRange());
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        Symbol other = (Symbol) obj;
        return (
            this.fileURIEquals(other) &&
            this.type == other.type &&
            this.status == other.status &&
            this.getNode() != null &&
            other.getNode() != null &&
            this.getNode().getRange() != null &&
            other.getNode().getRange() != null &&
            this.getNode().getRange().equals(other.getNode().getRange())
        );
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((this.fileURI == null) ? 0 : fileURIimpl.hashCode()); // use URI hashCode, not String hashCode because URI might be "same but different"
        result = prime * result + ((this.type == null) ? 0 : this.type.hashCode());
        result = prime * result + ((this.getNode() == null || this.getNode().getRange() == null) ? 0 : this.getNode().getRange().hashCode());
        return result;
    }

    public enum SymbolStatus {
        DEFINITION,
        REFERENCE,
        UNRESOLVED,
        INVALID,
        BUILTIN_REFERENCE // reference to stuff like "default" that doesn't have a definition in our CSTs
    }

    public enum SymbolType {
        ANNOTATION,
        DOCUMENT,
        DOCUMENT_SUMMARY,
        FIELD,
        FIELDSET,
        FUNCTION,
        LABEL,
        LAMBDA_FUNCTION,
        MAP_KEY,
        MAP_VALUE,
        ONNX_MODEL,
        PARAMETER,
        PROPERTY,
        QUERY_INPUT,
        RANK_CONSTANT,
        RANK_PROFILE,
        RANK_TYPE,
        SCHEMA,
        STRUCT,
        STRUCT_FIELD,
        SUBFIELD,
        TENSOR,
        TENSOR_DIMENSION_INDEXED,
        TENSOR_DIMENSION_MAPPED,
        TYPE_UNKNOWN,
        DIMENSION,
    }

    public String toString() {
        Position pos = getNode().getRange().getStart();
        String fileName = FileUtils.fileNameFromPath(fileURI);
        return "Symbol('" + getLongIdentifier() + "', " + getType() + ", " + getStatus() + ", at: " + fileName + ":" + pos.getLine() + ":" + pos.getCharacter() + ")@" + System.identityHashCode(this);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy