org.napile.compiler.lang.resolve.calls.ResolutionTaskHolder.java Source code

Java tutorial

Introduction

Here is the source code for org.napile.compiler.lang.resolve.calls.ResolutionTaskHolder.java

Source

/*
 * Copyright 2010-2012 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.napile.compiler.lang.resolve.calls;

import java.util.Collection;
import java.util.List;

import org.jetbrains.annotations.NotNull;
import org.napile.compiler.lang.descriptors.CallableDescriptor;
import org.napile.compiler.lang.psi.NapilePsiUtil;
import org.napile.compiler.lang.psi.NapileReferenceExpression;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

/**
 * @author svtk
 */
public class ResolutionTaskHolder<D extends CallableDescriptor, F extends D> {
    private final NapileReferenceExpression reference;
    private final BasicResolutionContext basicResolutionContext;
    private final Predicate<ResolutionCandidate<D>> visibleStrategy;
    private final boolean isSafeCall;

    private final Collection<Collection<ResolutionCandidate<D>>> localExtensions = Sets.newLinkedHashSet();
    private final Collection<Collection<ResolutionCandidate<D>>> members = Sets.newLinkedHashSet();
    private final Collection<Collection<ResolutionCandidate<D>>> nonLocalExtensions = Sets.newLinkedHashSet();

    private List<ResolutionTask<D, F>> tasks = null;

    public ResolutionTaskHolder(@NotNull NapileReferenceExpression reference,
            @NotNull BasicResolutionContext basicResolutionContext,
            @NotNull Predicate<ResolutionCandidate<D>> visibleStrategy) {
        this.reference = reference;
        this.basicResolutionContext = basicResolutionContext;
        this.visibleStrategy = visibleStrategy;
        this.isSafeCall = NapilePsiUtil.isSafeCall(basicResolutionContext.call);
    }

    public Collection<ResolutionCandidate<D>> setIsSafeCall(
            @NotNull Collection<ResolutionCandidate<D>> candidates) {
        for (ResolutionCandidate<D> candidate : candidates) {
            candidate.setSafeCall(isSafeCall);
        }
        return candidates;
    }

    public void addLocalExtensions(@NotNull Collection<ResolutionCandidate<D>> candidates) {
        if (!candidates.isEmpty()) {
            localExtensions.add(setIsSafeCall(candidates));
        }
    }

    public void addMembers(@NotNull Collection<ResolutionCandidate<D>> candidates) {
        if (!candidates.isEmpty()) {
            members.add(setIsSafeCall(candidates));
        }
    }

    public void addNonLocalExtensions(@NotNull Collection<ResolutionCandidate<D>> candidates) {
        if (!candidates.isEmpty()) {
            nonLocalExtensions.add(setIsSafeCall(candidates));
        }
    }

    public List<ResolutionTask<D, F>> getTasks() {
        if (tasks == null) {
            tasks = Lists.newArrayList();
            List<Collection<ResolutionCandidate<D>>> candidateList = Lists.newArrayList();
            // If the call is of the form super.foo(), it can actually be only a member
            // But  if there's no appropriate member, we would like to report that super cannot be a receiver for an extension
            // Thus, put members first
            if (TaskPrioritizer.getReceiverSuper(basicResolutionContext.call.getExplicitReceiver()) != null) {
                candidateList.addAll(members);
                candidateList.addAll(localExtensions);
            } else {
                candidateList.addAll(localExtensions);
                candidateList.addAll(members);
            }
            candidateList.addAll(nonLocalExtensions);

            for (Predicate<ResolutionCandidate<D>> visibilityStrategy : Lists.newArrayList(visibleStrategy,
                    Predicates.not(visibleStrategy))) {
                for (Collection<ResolutionCandidate<D>> candidates : candidateList) {
                    Collection<ResolutionCandidate<D>> filteredCandidates = Collections2.filter(candidates,
                            visibilityStrategy);
                    if (!filteredCandidates.isEmpty()) {
                        tasks.add(new ResolutionTask<D, F>(filteredCandidates, reference, basicResolutionContext));
                    }
                }
            }
        }
        return tasks;
    }
}