blob: f0cc660dcc8ab22ea3664b34a1bac3f45c9c30f6 [file] [log] [blame]
/*
* Copyright 2000-2014 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.jetbrains.idea.devkit.testAssistant;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.ManagingFS;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileInfoManager;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ProcessingContext;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import static com.intellij.patterns.PsiJavaPatterns.literalExpression;
import static org.jetbrains.idea.devkit.testAssistant.TestDataLineMarkerProvider.*;
/**
* @author zolotov
* @since 9/20/13
*/
public class TestDataReferenceContributor extends PsiReferenceContributor {
@Override
public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) {
registrar.registerReferenceProvider(literalExpression().annotationParam(TEST_DATA_PATH_ANNOTATION_QUALIFIED_NAME),
new TestDataReferenceProvider());
}
private static class TestDataReferenceProvider extends PsiReferenceProvider {
@NotNull
@Override
public PsiReference[] getReferencesByElement(@NotNull final PsiElement element, @NotNull final ProcessingContext context) {
final TestDataReferenceSet referenceSet = new TestDataReferenceSet(element);
referenceSet.addCustomization(FileReferenceSet.DEFAULT_PATH_EVALUATOR_OPTION, FileReferenceSet.ABSOLUTE_TOP_LEVEL);
return referenceSet.getAllReferences();
}
}
private static class TestDataReferenceSet extends FileReferenceSet {
public TestDataReferenceSet(@NotNull PsiElement element) {
super(element);
}
@Override
public boolean isEmptyPathAllowed() {
return false;
}
@Override
public boolean isAbsolutePathReference() {
return super.isAbsolutePathReference() || StringUtil.startsWithChar(getPathString(), '$');
}
@Override
public FileReference createFileReference(TextRange range, int index, String text) {
return new TestDataReference(this, range, index, text);
}
@NotNull
@Override
public Collection<PsiFileSystemItem> computeDefaultContexts() {
return toFileSystemItems(ManagingFS.getInstance().getLocalRoots());
}
@Override
protected Condition<PsiFileSystemItem> getReferenceCompletionFilter() {
return DIRECTORY_FILTER;
}
}
public static class TestDataReference extends FileReference {
public TestDataReference(@NotNull FileReferenceSet fileReferenceSet, TextRange range, int index, String text) {
super(fileReferenceSet, range, index, text);
}
@NotNull
@Override
public Object[] getVariants() {
if (getIndex() == 0 && !StringUtil.startsWithChar(getFileReferenceSet().getPathString(), '/')) {
Collection<Object> variants = ContainerUtil.newHashSet(super.getVariants());
final PsiDirectory projectPsiRoot = getProjectPsiRoot();
if (projectPsiRoot != null) {
variants.add(FileInfoManager.getFileLookupItem(projectPsiRoot, PROJECT_ROOT_VARIABLE, projectPsiRoot.getIcon(0))
.withTypeText(projectPsiRoot.getVirtualFile().getPath(), true));
}
final PsiDirectory contentPsiRoot = getContentPsiRoot();
if (contentPsiRoot != null) {
variants.add(FileInfoManager.getFileLookupItem(contentPsiRoot, CONTENT_ROOT_VARIABLE, contentPsiRoot.getIcon(0))
.withTypeText(contentPsiRoot.getVirtualFile().getPath(), true));
}
return ArrayUtil.toObjectArray(variants);
}
return super.getVariants();
}
@NotNull
@Override
protected ResolveResult[] innerResolve(boolean caseSensitive, @NotNull PsiFile containingFile) {
if (getIndex() == 0 && StringUtil.startsWithChar(getText(), '$')) {
if (PROJECT_ROOT_VARIABLE.equals(getText())) {
final PsiDirectory projectPsiRoot = getProjectPsiRoot();
if (projectPsiRoot != null) {
return new ResolveResult[]{new PsiElementResolveResult(projectPsiRoot)};
}
}
else if (CONTENT_ROOT_VARIABLE.equals(getText())) {
final PsiDirectory contentPsiRoot = getContentPsiRoot();
if (contentPsiRoot != null) {
return new ResolveResult[]{new PsiElementResolveResult(contentPsiRoot)};
}
}
}
return super.innerResolve(caseSensitive, containingFile);
}
@Nullable
private PsiDirectory getProjectPsiRoot() {
final Project project = getElement().getProject();
final VirtualFile projectDir = project.getBaseDir();
if (projectDir != null) {
final PsiManager psiManager = PsiManager.getInstance(project);
return psiManager.findDirectory(projectDir);
}
return null;
}
@Nullable
private PsiDirectory getContentPsiRoot() {
final Project project = getElement().getProject();
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
final VirtualFile file = getElement().getContainingFile().getOriginalFile().getVirtualFile();
if (file != null) {
final VirtualFile contentRoot = fileIndex.getContentRootForFile(file);
if (contentRoot != null) {
final PsiManager psiManager = PsiManager.getInstance(project);
return psiManager.findDirectory(contentRoot);
}
}
return null;
}
}
}