Package ro.redeul.google.go.lang.psi.resolve.refs

Source Code of ro.redeul.google.go.lang.psi.resolve.refs.MethodReference

package ro.redeul.google.go.lang.psi.resolve.refs;

import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import ro.redeul.google.go.lang.packages.GoPackages;
import ro.redeul.google.go.lang.psi.GoPackage;
import ro.redeul.google.go.lang.psi.expressions.literals.GoLiteralIdentifier;
import ro.redeul.google.go.lang.psi.processors.ResolveStates;
import ro.redeul.google.go.lang.psi.resolve.ReferenceWithSolver;
import ro.redeul.google.go.lang.psi.types.GoPsiType;
import ro.redeul.google.go.lang.psi.types.GoPsiTypePointer;
import ro.redeul.google.go.lang.psi.types.struct.GoTypeStructAnonymousField;
import ro.redeul.google.go.lang.psi.typing.GoType;
import ro.redeul.google.go.lang.psi.typing.GoTypeName;
import ro.redeul.google.go.lang.psi.typing.GoTypeStruct;
import ro.redeul.google.go.lang.psi.typing.GoTypes;
import ro.redeul.google.go.lang.psi.utils.GoPsiScopesUtil;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;

public class MethodReference extends ReferenceWithSolver<GoLiteralIdentifier, MethodSolver, MethodReference> {

    private Set<GoTypeName> receiverTypes;
    private GoTypeName type;

    public MethodReference(GoLiteralIdentifier element, @NotNull GoTypeName type) {
        super(element);
        this.type = type;
    }

    @Override
    protected MethodReference self() {
        return this;
    }

    @Override
    public MethodSolver newSolver() {
        return new MethodSolver(self());
    }

    @Override
    public void walkSolver(MethodSolver solver) {
        PsiElement toFindPackagePsi;

        GoPackage goPackage = GoPackages.getTargetPackageIfDifferent(getElement(), type.getDefinition());

        if ( goPackage != null) {
            GoPsiScopesUtil.walkPackage(solver, getElement(), goPackage);
        } else {
            GoPsiScopesUtil.treeWalkUp(
                    solver,
                    getElement().getContainingFile().getLastChild(),
                    getElement().getContainingFile(),
                    ResolveStates.initial());
        }
    }

    @NotNull
    public Set<GoTypeName> resolveBaseReceiverTypes() {
        if ( receiverTypes != null )
            return receiverTypes;

        receiverTypes = new HashSet<GoTypeName>();

        Queue<GoTypeName> typeNamesToExplore = new LinkedList<GoTypeName>();
        typeNamesToExplore.offer(type);

        while ( ! typeNamesToExplore.isEmpty() ) {
            GoTypeName currentTypeName = typeNamesToExplore.poll();

            receiverTypes.add(currentTypeName);

            GoType underlyingType = currentTypeName.underlyingType();
            if ( !(underlyingType instanceof GoTypeStruct) )
                continue;

            GoTypeStruct typeStruct = (GoTypeStruct) underlyingType;
            for (GoTypeStructAnonymousField field : typeStruct.getPsiType().getAnonymousFields()) {
                GoPsiType psiType = field.getType();
                if ( psiType == null)
                    continue;
                if ( psiType instanceof GoPsiTypePointer) {
                    psiType = ((GoPsiTypePointer) psiType).getTargetType();
                }

                GoType embeddedType = GoTypes.fromPsi(psiType);
                if (!(embeddedType instanceof GoTypeName))
                    continue;

                GoTypeName embeddedTypeName = (GoTypeName) embeddedType;
                if (! receiverTypes.contains(embeddedTypeName) )
                    typeNamesToExplore.offer(embeddedTypeName);

                receiverTypes.add(embeddedTypeName);
            }
        }

        return receiverTypes;
    }
}
TOP

Related Classes of ro.redeul.google.go.lang.psi.resolve.refs.MethodReference

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.