Package ro.redeul.google.go.services

Source Code of ro.redeul.google.go.services.GoPsiManager

package ro.redeul.google.go.services;

import com.intellij.ProjectTopics;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootEvent;
import com.intellij.openapi.roots.ModuleRootListener;
import com.intellij.openapi.util.RecursionGuard;
import com.intellij.openapi.util.RecursionManager;
import com.intellij.psi.PsiManager;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ConcurrentWeakHashMap;
import org.jetbrains.annotations.NotNull;
import ro.redeul.google.go.lang.psi.GoPsiElement;
import ro.redeul.google.go.lang.psi.typing.GoType;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
* Author: Toader Mihai Claudiu <mtoader@gmail.com>
* <p/>
* Date: 7/15/11
* Time: 7:50 AM
*/
public class GoPsiManager {

    private static final Logger LOG = Logger.getInstance("ro.redeul.google.go.services.GoPsiManager");

    private final ConcurrentMap<GoPsiElement, GoType[]> myCalculatedTypes =
            new ConcurrentWeakHashMap<GoPsiElement, GoType[]>();

    private final ConcurrentMap<GoPsiElement, GoType> myComputedType =
            new ConcurrentHashMap<GoPsiElement, GoType>();

    private static final RecursionGuard ourGuard =
            RecursionManager.createGuard("goPsiManager");

    private static final RecursionGuard outSecondGuard =
            RecursionManager.createGuard("goPsiManagerSecond");

    private GoPsiManager(Project project) {

        ((PsiManagerEx) PsiManager.getInstance(project)).registerRunnableToRunOnAnyChange(new Runnable() {
            public void run() {
                myCalculatedTypes.clear();
                myComputedType.clear();
            }
        });
        ((PsiManagerEx) PsiManager.getInstance(project)).registerRunnableToRunOnChange(new Runnable() {
            public void run() {
                myComputedType.clear();
                myCalculatedTypes.clear();
            }
        });

        project.getMessageBus().connect().subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootListener() {
            public void beforeRootsChange(ModuleRootEvent event) {
            }

            public void rootsChanged(ModuleRootEvent event) {
                myCalculatedTypes.clear();
                myComputedType.clear();
            }
        });
    }

    public static GoPsiManager getInstance(Project project) {
        return ServiceManager.getService(project, GoPsiManager.class);
    }

    @NotNull
    public <T extends GoPsiElement, V> GoType getOrCompute(T element, Function<T, GoType> valueCalculator) {
        GoType type = myComputedType.get(element);
//        GoType type = null;
        if (type == null) {
            RecursionGuard.StackStamp stamp = outSecondGuard.markStack();
            type = valueCalculator.fun(element);
            if ( type != null ) {
                if (stamp.mayCacheNow()) {
                    type = ConcurrencyUtil.cacheOrGet(myComputedType, element, type);
                } else {
                    final GoType alreadyInferred = myComputedType.get(element);
                    if (alreadyInferred != null) {
                        type = alreadyInferred;
                    }
                }
            }
        }

        return type != null ? type : GoType.Unknown;
    }

    @NotNull
    public <T extends GoPsiElement> GoType[] getType(T element, Function<T, GoType[]> calculator) {
        GoType[] types = myCalculatedTypes.get(element);
//        GoType[] types = null;
        if (types == null) {
            RecursionGuard.StackStamp stamp = ourGuard.markStack();
            types = calculator.fun(element);
            if (types == null) {
                types = GoType.EMPTY_ARRAY;
            }
            if (stamp.mayCacheNow()) {
                types = ConcurrencyUtil.cacheOrGet(myCalculatedTypes, element, types);
            } else {
                final GoType[] alreadyInferred = myCalculatedTypes.get(element);
                if (alreadyInferred != null) {
                    types = alreadyInferred;
                }
            }
        }

        return types;
    }
}
TOP

Related Classes of ro.redeul.google.go.services.GoPsiManager

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.