// Copyright 2014 Pants project contributors (see CONTRIBUTORS.md). // Licensed under the Apache License, Version 2.0 (see LICENSE). package com.twitter.intellij.pants.psi.reference; import com.intellij.codeInsight.lookup.LookupElementBuilder; 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.PsiManager; import com.jetbrains.python.psi.PyCallExpression; import com.twitter.intellij.pants.util.PantsPsiUtil; import com.twitter.intellij.pants.util.PantsUtil; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.Collections; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; public class PantsTargetReference extends PantsPsiReferenceBase { public PantsTargetReference(@NotNull PsiElement element, @NotNull TextRange range, @Nls String text, @Nls String relativePath) { super(element, range, text, relativePath); } @NotNull private Collection<PsiFile> findBuildFiles() { if (StringUtil.isEmpty(getRelativePath())) { // same file reference return Collections.singleton(getElement().getContainingFile()); } Optional<VirtualFile> file = findFile(); if (!file.isPresent()) { return Collections.emptyList(); } Collection<VirtualFile> buildFiles = PantsUtil.findBUILDFiles(file.get()); final PsiManager psiManager = PsiManager.getInstance(getElement().getProject()); return buildFiles.stream().map(psiManager::findFile).collect(Collectors.toSet()); } @NotNull @Override public Object[] getVariants() { return findBuildFiles().stream() .map(PantsPsiUtil::findTargets) .map(Map::keySet) .flatMap(Collection::stream) .map(LookupElementBuilder::create) .toArray(); } @Nullable @Override public PsiElement resolve() { Collection<PsiFile> files = findBuildFiles(); for(PsiFile file: files) { Map<String, PyCallExpression> targets = PantsPsiUtil.findTargets(file); if (targets.containsKey(getText())) { return targets.get(getText()); } } return files.stream().findFirst().orElse(null); } }