Package ro.redeul.google.go.lang.packages

Source Code of ro.redeul.google.go.lang.packages.GoPackages

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

import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.ex.ProjectRootManagerEx;
import com.intellij.openapi.util.NotNullLazyKey;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiManager;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.reference.SoftReference;
import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.containers.ConcurrentHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import ro.redeul.google.go.lang.psi.GoFile;
import ro.redeul.google.go.lang.psi.GoPackage;
import ro.redeul.google.go.lang.psi.impl.GoPackageImpl;

import java.util.concurrent.ConcurrentMap;

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

public class GoPackages extends AbstractProjectComponent {

    private static final NotNullLazyKey<GoPackages, Project> INSTANCE_KEY = ServiceManager.createLazyKey(GoPackages.class);

    private volatile SoftReference<ConcurrentMap<String, GoPackage>> packagesCache;

    public static final GoPackage C = new GoPackageImpl(null, null, null) {
        @Override
        public String getImportPath() {
            return "C";
        }

        @NotNull
        @Override
        public String getName() {
            return "C";
        }

        @Override
        public GoFile[] getFiles() {
            return GoFile.EMPTY_ARRAY;
        }

        @NotNull
        @Override
        public PsiDirectory[] getDirectories() {
            return PsiDirectory.EMPTY_ARRAY;
        }

        @NotNull
        @Override
        public PsiDirectory[] getDirectories(@NotNull GlobalSearchScope scope) {
            return getDirectories();
        }
    };

    public GoPackages(Project project) {
        super(project);
    }

    @NotNull
    @Override
    public String getComponentName() {
        return "GoPackages";
    }

    public static GoPackages getInstance(Project project) {
        return INSTANCE_KEY.getValue(project);
    }

    /**
     * @param path a fully qualified path name (not a relative one) accessible from one of the source roots.
     * @return an object encapsulating a go package.
     */
    @Nullable
    public GoPackage getPackage(String path) {
        ConcurrentMap<String, GoPackage> cache = SoftReference.dereference(packagesCache);
        if (cache == null) {
            packagesCache = new SoftReference<ConcurrentMap<String, GoPackage>>(cache = new ConcurrentHashMap<String, GoPackage>());
        }

        GoPackage aPackage = cache.get(path);
        if (aPackage != null) {
            return aPackage;
        }

        aPackage = resolvePackage(path);
        return aPackage != null ? ConcurrencyUtil.cacheOrGet(cache, path, aPackage) : null;
    }

    private GoPackage resolvePackage(String path){
        if ( path.equals(C.getImportPath()))
            return C;

        VirtualFile sourceRoots[] = ProjectRootManagerEx.getInstanceEx(myProject).getContentSourceRoots();

        for (VirtualFile sourceRoot : sourceRoots) {
            VirtualFile packagePath = sourceRoot.findFileByRelativePath(path);
            if (packagePath != null && packagePath.isDirectory()) {
                return new GoPackageImpl(packagePath, sourceRoot, PsiManager.getInstance(myProject));
            }
        }

        Sdk projectSdk = ProjectRootManagerEx.getInstanceEx(myProject).getProjectSdk();
        if ( projectSdk == null )
            return null;

        VirtualFile[] sdkSourceRoots = projectSdk.getRootProvider().getFiles(OrderRootType.SOURCES);

        for (VirtualFile sourceRoot : sdkSourceRoots) {
            VirtualFile packagePath = sourceRoot.findFileByRelativePath(path);
            if ( packagePath != null && packagePath.isDirectory()) {
                return new GoPackageImpl(packagePath, sourceRoot, PsiManager.getInstance(myProject));
            }
        }

        return null;
    }

    public GoPackage getBuiltinPackage() {
        return getPackage("builtin");
    }

    @Nullable
    public static GoPackage getPackageFor(@Nullable PsiElement element) {
        if ( element == null )
            return null;

        GoPackages goPackages = getInstance(element.getProject());

        GoFile goFile = getAs(GoFile.class, element.getContainingFile());

        if ( goFile == null )
            return null;

        String packageImportPath = goFile.getPackageImportPath();

        return goPackages.getPackage(packageImportPath);
    }

    @Nullable public static GoPackage getTargetPackageIfDifferent(PsiElement source, PsiElement target) {
        if ( source == null || target == null)
            return null;

        GoPackage sourcePackage = getPackageFor(source);
        GoPackage targetPackage = getPackageFor(target);

        if ( sourcePackage != null && targetPackage != null && !sourcePackage.equals(targetPackage) ) {
            GoPackage builtin = GoPackages.getInstance(source.getProject()).getBuiltinPackage();

            if ( !builtin.equals(targetPackage))
                return targetPackage;
        }

        return null;
    }
}
TOP

Related Classes of ro.redeul.google.go.lang.packages.GoPackages

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.