Package com.dci.intellij.dbn.language.common.psi

Source Code of com.dci.intellij.dbn.language.common.psi.BasePsiElement

package com.dci.intellij.dbn.language.common.psi;

import com.dci.intellij.dbn.code.common.style.formatting.FormattingAttributes;
import com.dci.intellij.dbn.code.common.style.formatting.FormattingDefinition;
import com.dci.intellij.dbn.code.common.style.formatting.FormattingProviderPsiElement;
import com.dci.intellij.dbn.common.editor.BasicTextEditor;
import com.dci.intellij.dbn.common.thread.ReadActionRunner;
import com.dci.intellij.dbn.common.util.DocumentUtil;
import com.dci.intellij.dbn.common.util.EditorUtil;
import com.dci.intellij.dbn.connection.ConnectionHandler;
import com.dci.intellij.dbn.database.DatabaseCompatibilityInterface;
import com.dci.intellij.dbn.editor.ddl.DDLFileEditor;
import com.dci.intellij.dbn.language.common.DBLanguage;
import com.dci.intellij.dbn.language.common.DBLanguageDialect;
import com.dci.intellij.dbn.language.common.DBLanguageFile;
import com.dci.intellij.dbn.language.common.element.ElementType;
import com.dci.intellij.dbn.language.common.element.util.ElementTypeAttribute;
import com.dci.intellij.dbn.language.common.element.util.ElementTypeAttributesBundle;
import com.dci.intellij.dbn.language.common.element.util.IdentifierCategory;
import com.dci.intellij.dbn.language.common.psi.lookup.ObjectLookupAdapter;
import com.dci.intellij.dbn.language.common.psi.lookup.PsiLookupAdapter;
import com.dci.intellij.dbn.object.DBSchema;
import com.dci.intellij.dbn.object.common.DBObject;
import com.dci.intellij.dbn.object.common.DBObjectType;
import com.dci.intellij.dbn.object.common.DBVirtualObject;
import com.dci.intellij.dbn.vfs.DatabaseEditableObjectFile;
import com.dci.intellij.dbn.vfs.SourceCodeFile;
import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.ide.util.EditSourceUtil;
import com.intellij.lang.ASTNode;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiErrorElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.SearchScope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.Icon;
import java.util.Set;

public abstract class BasePsiElement extends ASTWrapperPsiElement implements ItemPresentation, FormattingProviderPsiElement {
    private ElementType elementType;
    private DBVirtualObject underlyingObject;
    private boolean isScopeIsolation;
    private boolean isScopeDemarcation;
    private FormattingAttributes formattingAttributes;

    public BasePsiElement(ASTNode astNode, ElementType elementType) {
        super(astNode);
        this.elementType = elementType;
        isScopeIsolation = elementType.is(ElementTypeAttribute.SCOPE_ISOLATION);
        isScopeDemarcation = elementType.is(ElementTypeAttribute.SCOPE_DEMARCATION);
    }

    public FormattingAttributes getFormattingAttributes() {
        FormattingDefinition formattingDefinition = elementType.getFormatting();
        if (formattingAttributes == null && formattingDefinition != null) {
            formattingAttributes = FormattingAttributes.copy(formattingDefinition.getAttributes());
        }

        return formattingAttributes;
    }

    public ElementTypeAttributesBundle getElementTypeAttributes() {
        return elementType.getAttributes();
    }

    public FormattingAttributes getFormattingAttributesRecursive(boolean left) {
        FormattingAttributes formattingAttributes = getFormattingAttributes();
        if (formattingAttributes == null) {
            PsiElement psiElement = left ? getFirstChild() : getLastChild();
            if (psiElement instanceof BasePsiElement) {
                BasePsiElement basePsiElement = (BasePsiElement) psiElement;
                return basePsiElement.getFormattingAttributesRecursive(left);
            }
        }
        return formattingAttributes;
    }

    public boolean containsLineBreaks() {
        CharSequence charSequence = getNode().getChars();
        for (int i=0; i<charSequence.length(); i++) {
            if (charSequence.charAt(i) == '\n') return true;
        }
        return false;
    }

    public void setElementType(ElementType elementType) {
        this.elementType = elementType;
    }

    @Override
    public PsiElement getFirstChild() {
        ASTNode firstChildNode = getNode().getFirstChildNode();
        return firstChildNode == null ? null : firstChildNode.getPsi();
    }

    @Override
    public PsiElement getNextSibling() {
        ASTNode treeNext = getNode().getTreeNext();
        return treeNext == null ? null : treeNext.getPsi();
    }

    @Override
    public BasePsiElement getOriginalElement() {
        PsiFile containingFile = getContainingFile();
        PsiFile originalFile = containingFile.getOriginalFile();
        if (originalFile == null || originalFile == containingFile) {
            return this;
        }
        int startOffset = getTextOffset();

        PsiElement psiElement = originalFile.findElementAt(startOffset);
        while (psiElement != null) {
            int elementStartOffset = psiElement.getTextOffset();
            if (elementStartOffset < startOffset) {
                break;
            }
            if (psiElement instanceof BasePsiElement) {
                BasePsiElement basePsiElement = (BasePsiElement) psiElement;
                boolean isSameElement = basePsiElement.getElementType() == getElementType();
                boolean isIdentifier = basePsiElement instanceof IdentifierPsiElement && this instanceof IdentifierPsiElement;
                if ((isSameElement || isIdentifier) && elementStartOffset == startOffset) {
                    return basePsiElement;
                }
            }
            psiElement = psiElement.getParent();
        }

        return this;
    }

    public boolean isOriginalElement() {
        PsiFile containingFile = getContainingFile();
        PsiFile originalFile = containingFile.getOriginalFile();
        return originalFile == null || originalFile == containingFile;

    }

    public String getReferenceQualifiedName() {
        return isVirtualObject() ? "virtual " + getElementType().getVirtualObjectType().getName() : "[unknown element]";
    }

    public abstract int approximateLength();

    public ElementType getElementType() {
        return elementType;
    }

    public DBLanguageFile getFile() {
        PsiElement parent = getParent();
        while (parent != null && !(parent instanceof DBLanguageFile)) {
            parent = parent.getParent();
        }
        return (DBLanguageFile) parent;
    }

    @Nullable
    public ConnectionHandler getActiveConnection() {
        DBLanguageFile file = getFile();
        return file == null ? null : file.getActiveConnection();
    }

    public DBSchema getCurrentSchema() {
        DBLanguageFile file = getFile();
        return file == null ? null : file.getCurrentSchema();
    }

    public String toString() {
        return hasErrors() ?
                "[INVALID] " + elementType.getDebugName() :
                elementType.getDebugName() +
                        (isScopeDemarcation() ? " SCOPE_DEMARCATION" : "") +
                        (isScopeIsolation() ? " SCOPE_ISOLATION" : "");
    }

    public void acceptChildren(@NotNull PsiElementVisitor visitor) {
            final PsiElement psiChild = getFirstChild();
        if (psiChild == null) return;

        ASTNode child = psiChild.getNode();
        while (child != null) {
            if (child.getPsi() != null) {
                child.getPsi().accept(visitor);
            }
            child = child.getTreeNext();
        }
    }

    @NotNull
    @Override
    public SearchScope getUseScope() {
        return new LocalSearchScope(getFile());
    }

    public void accept(@NotNull PsiElementVisitor visitor) {
        super.accept(visitor);
    }

    public String getText() {
        if (ApplicationManager.getApplication().isReadAccessAllowed()) {
            return super.getText();
        }
        return new ReadActionRunner<String>() {
            protected String run() {
                return BasePsiElement.super.getText();
            }
        }.start();
    }


    public PsiElement findElementAt(int offset) {
        return super.findElementAt(offset);
    }

    public PsiElement getLastChildIgnoreWhiteSpace() {
        PsiElement psiElement = this.getLastChild();
        while (psiElement != null && psiElement instanceof PsiWhiteSpace) {
            psiElement = psiElement.getPrevSibling();
        }
        return psiElement;
    }

    public BasePsiElement getPrevElement() {
        PsiElement preElement = getPrevSibling();
        while (preElement != null && preElement instanceof PsiWhiteSpace) {
            preElement = preElement.getPrevSibling();
        }
        BasePsiElement previous = (BasePsiElement) preElement;
        while (previous != null && previous.getLastChild() instanceof BasePsiElement) {
            previous = (BasePsiElement) previous.getLastChild();
        }
        return previous;
    }

    protected BasePsiElement getNextElement() {
        PsiElement nextElement = getNextSibling();
        while (nextElement != null && (nextElement instanceof PsiWhiteSpace || nextElement instanceof PsiComment || nextElement instanceof PsiErrorElement)) {
            nextElement = nextElement.getNextSibling();
        }
        BasePsiElement next = (BasePsiElement) nextElement;
        while (next != null && next.getFirstChild() instanceof BasePsiElement) {
            next = (BasePsiElement) next.getFirstChild();
        }
        return next;
    }

    public boolean isVirtualObject() {
        return getElementType().isVirtualObject();
    }

    public void navigate(boolean requestFocus) {
        if (isValid()) {
            OpenFileDescriptor descriptor = (OpenFileDescriptor) EditSourceUtil.getDescriptor(this);
            if (descriptor != null) {
                VirtualFile virtualFile = getFile().getVirtualFile();
                FileEditorManager editorManager = FileEditorManager.getInstance(getProject());
                if (virtualFile != null) {
                    if (virtualFile instanceof SourceCodeFile) {
                        SourceCodeFile sourceCodeFile = (SourceCodeFile) virtualFile;
                        DatabaseEditableObjectFile databaseFile = sourceCodeFile.getDatabaseFile();
                        if (!editorManager.isFileOpen(databaseFile)) {
                            editorManager.openFile(databaseFile, requestFocus);
                        }
                        BasicTextEditor textEditor = EditorUtil.getFileEditor(databaseFile, virtualFile);
                        descriptor.navigateIn(textEditor.getEditor());
                        return;
                    }

                    Editor editor = editorManager.getSelectedTextEditor();
                    if (editor != null && virtualFile == DocumentUtil.getVirtualFile(editor)) {
                        super.navigate(requestFocus);
                        return;
                    }

                    FileEditor[] fileEditors = editorManager.getSelectedEditors();
                    for (FileEditor fileEditor : fileEditors) {
                        if (fileEditor instanceof DDLFileEditor) {
                            DDLFileEditor textEditor = (DDLFileEditor) fileEditor;
                            if (textEditor.getVirtualFile() == virtualFile) {
                                descriptor.navigateIn(textEditor.getEditor());
                                return;
                            }

                        }
                    }

                    super.navigate(requestFocus);
                }
            }
        }
    }

    /*********************************************************
     *                   Lookup routines                     *
     *********************************************************/
    public Set<BasePsiElement> collectObjectPsiElements(Set<BasePsiElement> bucket, Set<DBObjectType> objectTypes, IdentifierCategory identifierCategory) {
        for (DBObjectType objectType : objectTypes) {
            PsiLookupAdapter lookupAdapter = new ObjectLookupAdapter(null, identifierCategory, objectType, null);
            bucket = lookupAdapter.collectInElement(this, bucket);
        }
        return bucket;
    }

    public abstract BasePsiElement lookupPsiElement(PsiLookupAdapter lookupAdapter, int scopeCrossCount);
    public abstract Set<BasePsiElement> collectPsiElements(PsiLookupAdapter lookupAdapter, Set<BasePsiElement> bucket, int scopeCrossCount);

    public abstract void collectExecVariablePsiElements(Set<ExecVariablePsiElement> bucket);
    public abstract void collectSubjectPsiElements(Set<BasePsiElement> bucket);


    public void collectVirtualObjectPsiElements(Set<BasePsiElement> bucket, DBObjectType objectType) {
        if (getElementType().isVirtualObject()) {
            DBObjectType virtualObjectType = getElementType().getVirtualObjectType();
            if (objectType == virtualObjectType) {
                bucket.add(this);
            }
        }
    }

    public abstract NamedPsiElement lookupNamedPsiElement(String id);
    public abstract BasePsiElement lookupFirstPsiElement(ElementTypeAttribute attribute);
    public abstract BasePsiElement lookupFirstLeafPsiElement();
    public abstract BasePsiElement lookupPsiElementBySubject(ElementTypeAttribute attribute, CharSequence subjectName, DBObjectType subjectType);
    public abstract BasePsiElement lookupPsiElementByAttribute(ElementTypeAttribute attribute);


    public boolean containsPsiElement(BasePsiElement basePsiElement) {
        return this == basePsiElement;
    }

    /*********************************************************
     *                       ItemPresentation                *
     *********************************************************/

    public BasePsiElement lookupEnclosingPsiElement(ElementTypeAttribute attribute) {
        PsiElement element = this;
        while (element != null) {
            if (element instanceof BasePsiElement) {
                BasePsiElement basePsiElement = (BasePsiElement) element;
                if (basePsiElement.getElementType().is(attribute)) {
                    return (BasePsiElement) element;
                }
            }
            element = element.getParent();
        }
        return null;
    }

    public BasePsiElement lookupEnclosingPsiElement(ElementTypeAttribute[] typeAttributes) {
        PsiElement element = this;
        while (element != null) {
            if (element  instanceof BasePsiElement) {
                BasePsiElement basePsiElement = (BasePsiElement) element;
                for (ElementTypeAttribute typeAttribute : typeAttributes) {
                    if (basePsiElement.getElementType().is(typeAttribute)) {
                        return basePsiElement;
                    }
                }
            }
            element = element.getParent();
        }
        return null;
    }


    public NamedPsiElement lookupEnclosingNamedPsiElement() {
        PsiElement parent = getParent();
        while (parent != null) {
            if (parent instanceof NamedPsiElement) {
                return (NamedPsiElement) parent;
            }
            parent = parent.getParent();
        }
        return null;
    }

    public SequencePsiElement lookupEnclosingSequencePsiElement() {
        PsiElement parent = getParent();
        while (parent != null) {
            if (parent instanceof SequencePsiElement) {
                return (SequencePsiElement) parent;
            }
            parent = parent.getParent();
        }
        return null;
    }

    BasePsiElement enclosingScopePsiElement;

    public BasePsiElement getEnclosingScopePsiElement() {
        if (enclosingScopePsiElement == null) {
            enclosingScopePsiElement = lookupEnclosingScopePsiElement();
        }

        return enclosingScopePsiElement;
    }

    public BasePsiElement lookupEnclosingScopeIsolationPsiElement() {
        PsiElement element = this;
        BasePsiElement basePsiElement = null;
        while (element != null) {
            if (element instanceof BasePsiElement) {
                basePsiElement = (BasePsiElement) element;
                if (basePsiElement.isScopeIsolation()) {
                    return basePsiElement;
                }
            }
            element = element.getParent();
        }

        return basePsiElement;
    }

    public BasePsiElement lookupEnclosingScopeDemarcationPsiElement() {
        PsiElement element = this;
        BasePsiElement basePsiElement = null;
        while (element != null) {
            if (element instanceof BasePsiElement) {
                basePsiElement = (BasePsiElement) element;
                if (basePsiElement.isScopeDemarcation()) {
                    return basePsiElement;
                }
            }
            element = element.getParent();
        }

        return basePsiElement;
    }

    /**
     * @deprecated use scope demarcation and isolation
     */
    public BasePsiElement lookupEnclosingScopePsiElement() {
        PsiElement element = this;
        BasePsiElement basePsiElement = null;
        while (element != null) {
            if (element instanceof BasePsiElement) {
                basePsiElement = (BasePsiElement) element;
                if (basePsiElement.isScopeBoundary()) {
                    return basePsiElement;
                }
            }
            element = element.getParent();
        }

        return basePsiElement;
    }



    public BasePsiElement lookupEnclosingPsiElement(Class type) {
        PsiElement parent = getParent();
        while (parent != null) {
            if (type.isAssignableFrom(parent.getClass())) {
                return (BasePsiElement) parent;
            }
            parent = parent.getParent();
        }
        return null;
    }

    public NamedPsiElement lookupEnclosingRootPsiElement() {
        PsiElement parent = getParent();
        while (parent != null) {
            if (parent instanceof NamedPsiElement) {
                NamedPsiElement namedPsiElement = (NamedPsiElement) parent;
                if (namedPsiElement.getElementType().is(ElementTypeAttribute.ROOT)) {
                    return namedPsiElement;
                }
            }
            parent = parent.getParent();
        }
        return null;
    }
    public boolean isParentOf(BasePsiElement basePsiElement) {
        PsiElement parent = basePsiElement.getParent();
        while (parent != null) {
            if (parent == this) {
                return true;
            }
            parent = parent.getParent();
        }
        return false;
    }

    public boolean isMatchingScope(SequencePsiElement sourceScope) {
        return true;
       /* if (sourceScope == null) return true; // no scope constraints
        SequencePsiElement scope = getEnclosingScopePsiElement();
        return scope == sourceScope || scope.isParentOf(sourceScope);*/
    }

    public boolean isScopeDemarcation() {
        return isScopeDemarcation;
        //return elementType.is(ElementTypeAttribute.SCOPE_DEMARCATION);
    }

    public boolean isScopeIsolation() {
        return isScopeIsolation;
    }
   
    public boolean isScopeBoundary() {
        return isScopeDemarcation() || isScopeIsolation();
    }


    /*********************************************************
     *                       ItemPresentation                *
     *********************************************************/
    public String getPresentableText() {
        return elementType.getDescription();
    }

    @Nullable
    public String getLocationString() {
        return null;
    }

    @Nullable
    public Icon getIcon(boolean open) {
        return getElementType().getIcon();
    }

    @Nullable
    public TextAttributesKey getTextAttributesKey() {
        return null;
    }

    public abstract boolean hasErrors();

    @NotNull
    public DBLanguage getLanguage() {
        return getLanguageDialect().getBaseLanguage();
    }

    @NotNull
    public DBLanguageDialect getLanguageDialect() {
        return getElementType().getLanguageDialect();
    }

    public abstract boolean equals(BasePsiElement basePsiElement);

    public abstract boolean matches(BasePsiElement basePsiElement);

    public synchronized DBObject resolveUnderlyingObject() {
        if (isVirtualObject() && (underlyingObject == null || !underlyingObject.isValid()) ) {
            DBObjectType virtualObjectType = getElementType().getVirtualObjectType();
            underlyingObject = new DBVirtualObject(virtualObjectType, this);
        }
        return underlyingObject;
    }

    public char getIdentifierQuotesChar() {
        ConnectionHandler activeConnection = getActiveConnection();
        if (activeConnection != null) {
            return DatabaseCompatibilityInterface.getInstance(activeConnection).getIdentifierQuotes();
        }
        return '"';
    }

}
TOP

Related Classes of com.dci.intellij.dbn.language.common.psi.BasePsiElement

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.