Package ro.redeul.google.go.lang.documentation

Source Code of ro.redeul.google.go.lang.documentation.DocumentUtil

package ro.redeul.google.go.lang.documentation;

import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiWhiteSpace;
import org.jetbrains.annotations.NotNull;
import ro.redeul.google.go.lang.parser.GoElementTypes;
import ro.redeul.google.go.lang.psi.GoFile;
import ro.redeul.google.go.lang.psi.declarations.GoConstDeclaration;
import ro.redeul.google.go.lang.psi.declarations.GoConstDeclarations;
import ro.redeul.google.go.lang.psi.declarations.GoVarDeclaration;
import ro.redeul.google.go.lang.psi.declarations.GoVarDeclarations;
import ro.redeul.google.go.lang.psi.expressions.literals.GoLiteralIdentifier;
import ro.redeul.google.go.lang.psi.toplevel.*;
import ro.redeul.google.go.lang.psi.types.GoPsiType;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static ro.redeul.google.go.lang.psi.utils.GoPsiUtils.isNewLineNode;
import static ro.redeul.google.go.lang.psi.utils.GoPsiUtils.isNodeOfType;

public class DocumentUtil {

    private static String getTailingDocumentOfElement(PsiElement element) {
        boolean foundNewLine = false;
        List<String> comments = new ArrayList<String>();
        while ((element = element.getNextSibling()) != null) {
            if (isNodeOfType(element, GoElementTypes.COMMENTS)) {
                foundNewLine = false;
                comments.add(getCommentText(element));
            } else if (isNewLineNode(element)) {
                if (foundNewLine || StringUtil.countChars(element.getText(), '\n') > 1) {
                    break;
                }

                foundNewLine = true;
            } else if (!(element instanceof PsiWhiteSpace)) {
                break;
            }
        }

        return StringUtil.join(comments, "\n");
    }

    private static String getHeaderDocumentOfElement(PsiElement element) {
        boolean foundNewLine = false;
        List<String> comments = new ArrayList<String>();
        while ((element = element.getPrevSibling()) != null) {
            if (isNodeOfType(element, GoElementTypes.COMMENTS)) {
                foundNewLine = false;
                comments.add(getCommentText(element));
            } else if (isNewLineNode(element)) {
                if (foundNewLine || StringUtil.countChars(element.getText(), '\n') > 1) {
                    break;
                }
                foundNewLine = true;
            } else if (!(element instanceof PsiWhiteSpace)) {
                break;
            }
        }

        Collections.reverse(comments);
        return StringUtil.join(comments, "\n");
    }

    private static String getCommentText(PsiElement comment) {
        String text = comment.getText().trim();
        if (text.startsWith("//")) {
            return text.substring(2);
        }
        return text.substring(2, text.length() - 2);
    }

    public static String getTailingOrHeaderDocument(PsiElement element) {
        if (element == null) {
            return "";
        }

        String text = getTailingDocumentOfElement(element);
        if (text.isEmpty()) {
            text = getHeaderDocumentOfElement(element);
        }
        return text;
    }

    public static String getTypeDocument(GoTypeNameDeclaration type) {
        if (type == null) {
            return "";
        }

        PsiFile file = type.getContainingFile();
        if (!(file instanceof GoFile)) {
            return "";
        }

        for (GoTypeDeclaration td : ((GoFile) file).getTypeDeclarations()) {
            for (GoTypeSpec spec : td.getTypeSpecs()) {
                if (spec != null && type.isEquivalentTo(spec.getTypeNameDeclaration())) {
                    String text = getHeaderDocumentOfElement(spec);
                    return text.isEmpty() ? getHeaderDocumentOfElement(td) : text;
                }
            }
        }

        return "";
    }

    public static String getFunctionDocument(GoFunctionDeclaration function) {
        String text = getFunctionQuickNavigationInfo(function).replace("\n", "<br/>") + "<br/><br/>\n";
        return text + getHeaderDocumentOfElement(function.getOriginalElement());
    }

    public static String getMethodDocument(GoMethodDeclaration method) {
        String text = getFunctionQuickNavigationInfo(method).replace("\n", "<br/>") + "<br/><br/>\n";
        return text + getHeaderDocumentOfElement(method.getOriginalElement());
    }

    public static String getVarDocument(GoLiteralIdentifier id) {
        if (id == null) {
            return "";
        }

        PsiElement original = id.getOriginalElement();
        if (!(original instanceof GoLiteralIdentifier)) {
            return "";
        }

        PsiElement parent = original.getParent();
        if (!(parent instanceof GoVarDeclaration)) {
            return "";
        }

        PsiElement grandpa = parent.getParent();
        if (!(grandpa instanceof GoVarDeclarations)) {
            return "";
        }

        String doc = getTailingOrHeaderDocument(parent);

        if (doc.isEmpty() && ((GoVarDeclarations) grandpa).getDeclarations().length == 1) {
            doc = getTailingDocumentOfElement(grandpa);
        }

        if (doc.isEmpty()) {
            doc = getHeaderDocumentOfElement(grandpa);
        }
        return doc;
    }

    public static String getConstDocument(GoLiteralIdentifier id) {
        if (id == null) {
            return "";
        }

        PsiElement original = id.getOriginalElement();
        if (!(original instanceof GoLiteralIdentifier)) {
            return "";
        }

        PsiElement parent = original.getParent();
        if (!(parent instanceof GoConstDeclaration)) {
            return "";
        }

        PsiElement grandpa = parent.getParent();
        if (!(grandpa instanceof GoConstDeclarations)) {
            return "";
        }

        String doc = getTailingOrHeaderDocument(parent);

        if (doc.isEmpty() && ((GoConstDeclarations) grandpa).getDeclarations().length == 1) {
            doc = getTailingDocumentOfElement(grandpa);
        }

        if (doc.isEmpty()) {
            doc = getHeaderDocumentOfElement(grandpa);
        }
        return doc;
    }

    private static String getElementPackageInfo(PsiElement element) {
        PsiFile file = element.getContainingFile();

        if (!(file instanceof GoFile)) {
            return "";
        }

        VirtualFile virtualFile = file.getVirtualFile();
        String packageName = ((GoFile) file).getPackage().getPackageName();
        return virtualFile != null ? packageName + "/" + virtualFile.getName() : packageName;
    }

    public static String getFunctionQuickNavigationInfo(GoFunctionDeclaration fd) {
        String packageInfo = getElementPackageInfo(fd);
        String functionInfo = getFunctionPresentationText(fd);
        return packageInfo + "\n" + functionInfo;
    }

    public static String getFunctionPresentationText(GoFunctionDeclaration fd) {
        StringBuilder sb = new StringBuilder(fd.getFunctionName());
        String params = parametersToString(fd.getParameters());
        String results = parametersToString(fd.getResults());
        sb.append("(").append(params).append(")");
        if (!results.isEmpty()) {
            sb.append(": (").append(results).append(")");
        }
        return sb.toString();
    }

    /**
     * In the result of {@link #getFunctionPresentationText}, find text range of specified parameter
     * @param fd        The function definition
     * @param index     Parameter position.
     * @return Text range of the parameter
     */
    public static TextRange getFunctionParameterRangeInText(GoFunctionDeclaration fd, int index) {
        return parameterRangeInText(fd.getParameters(), index).shiftRight(fd.getFunctionName().length() + 1);
    }

    private static TextRange parameterRangeInText(GoFunctionParameter[] parameters, int expectedIndex) {
        if (parameters == null || parameters.length == 0) {
            return TextRange.EMPTY_RANGE;
        }

        int start = 0;
        int currentIndex = 0;
        StringBuilder sb = new StringBuilder();
        for (GoFunctionParameter fp : parameters) {
            GoLiteralIdentifier[] ids = fp.getIdentifiers();
            GoPsiType type = fp.getType();
            String variadic = fp.isVariadic() ? "..." : "";
            String typeName = variadic + String.valueOf(type != null ? type.getText() : null);
            start = sb.length();
            if (ids.length == 0) {
                sb.append(typeName).append(", ");
                if (currentIndex++ == expectedIndex) {
                    return new TextRange(start, sb.length() - 2);
                }
                continue;
            } else if (ids.length == 1) {
                sb.append(ids[0].getName()).append(" ").append(typeName).append(", ");
                if (currentIndex++ == expectedIndex) {
                    return new TextRange(start, sb.length() - 2);
                }
                continue;
            }

            for (int i = 0; i < ids.length; i++) {
                start = sb.length();
                sb.append(ids[i].getName()).append(", ");
                if (i != ids.length - 1 && currentIndex++ == expectedIndex) {
                    return new TextRange(start, sb.length() - 2);
                }
            }
            sb.insert(sb.length() - 2, " " + typeName);
            if (currentIndex++ == expectedIndex) {
                return new TextRange(start, sb.length() - 2);
            }
        }

        return new TextRange(start, sb.length() - 2);
    }

    private static String parametersToString(GoFunctionParameter[] parameters) {
        if (parameters == null || parameters.length == 0) {
            return "";
        }

        StringBuilder sb = new StringBuilder();
        for (GoFunctionParameter fp : parameters) {
            GoLiteralIdentifier[] ids = fp.getIdentifiers();
            GoPsiType type = fp.getType();
            String variadic = fp.isVariadic() ? "..." : "";
            String typeName = variadic + String.valueOf(type != null ? type.getText() : null);
            if (ids.length == 0) {
                sb.append(typeName).append(", ");
                continue;
            } else if (ids.length == 1) {
                sb.append(ids[0].getName()).append(" ").append(typeName).append(", ");
                continue;
            }

            for (GoLiteralIdentifier id : ids) {
                sb.append(id.getName()).append(", ");
            }
            sb.insert(sb.length() - 2, " " + typeName);
        }

        return sb.delete(sb.length() - 2, sb.length()).toString();
    }

    public static void replaceElementWithText(final Document document, PsiElement element, final String text) {
        final int start = element.getTextOffset();
        final int end = start + element.getTextLength();

        WriteCommandAction writeCommandAction = new WriteCommandAction(element.getContainingFile().getProject()) {
            @Override
            protected void run(@NotNull Result result) throws Throwable {
                document.replaceString(start, end, text);
            }
        };
        writeCommandAction.execute();
    }
}
TOP

Related Classes of ro.redeul.google.go.lang.documentation.DocumentUtil

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.