| /* |
| * 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; |
| } |
| } |
| } |