package com.jetbrains.lang.dart.psi;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
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.IncorrectOperationException;
import com.jetbrains.lang.dart.util.DartResolveUtil;
import com.jetbrains.lang.dart.util.DartUrlResolver;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import static com.jetbrains.lang.dart.util.DartUrlResolver.PACKAGES_FOLDER_NAME;
import static com.jetbrains.lang.dart.util.DartUrlResolver.PACKAGE_PREFIX;
class DartPackageAwareFileReference extends FileReference {
@NotNull private final DartUrlResolver myDartResolver;
public DartPackageAwareFileReference(@NotNull final FileReferenceSet fileReferenceSet,
final TextRange range,
final int index,
final String text,
@NotNull final DartUrlResolver dartResolver) {
super(fileReferenceSet, range, index, text);
myDartResolver = dartResolver;
}
@NotNull
protected ResolveResult[] innerResolve(final boolean caseSensitive, @NotNull final PsiFile containingFile) {
if (PACKAGES_FOLDER_NAME.equals(getText())) {
final VirtualFile pubspecYamlFile = myDartResolver.getPubspecYamlFile();
final VirtualFile packagesDir = pubspecYamlFile == null ? null : pubspecYamlFile.getParent().findChild(PACKAGES_FOLDER_NAME);
final PsiDirectory psiDirectory = packagesDir == null ? null : containingFile.getManager().findDirectory(packagesDir);
if (psiDirectory != null) {
return new ResolveResult[]{new PsiElementResolveResult(psiDirectory)};
}
}
final int index = getIndex();
if (index > 0 && PACKAGES_FOLDER_NAME.equals(getFileReferenceSet().getReference(index - 1).getText())) {
final VirtualFile packageDir = myDartResolver.getPackageDirIfLivePackageOrFromPubListPackageDirs(getText());
final PsiDirectory psiDirectory = packageDir == null ? null : containingFile.getManager().findDirectory(packageDir);
if (psiDirectory != null) {
return new ResolveResult[]{new PsiElementResolveResult(psiDirectory)};
}
}
return super.innerResolve(caseSensitive, containingFile);
}
@NotNull
public Object[] getVariants() {
final Object[] superVariants = super.getVariants();
if (getIndex() == 0) {
final VirtualFile pubspecYamlFile = myDartResolver.getPubspecYamlFile();
final VirtualFile packagesDir = pubspecYamlFile == null ? null : pubspecYamlFile.getParent().findChild(PACKAGES_FOLDER_NAME);
final PsiDirectory psiDirectory = packagesDir == null ? null : getElement().getManager().findDirectory(packagesDir);
if (psiDirectory != null) {
return ArrayUtil.append(superVariants, psiDirectory);
}
}
if (getIndex() == 1 && PACKAGES_FOLDER_NAME.equals(getFileReferenceSet().getReference(0).getText())) {
final Collection<Object> result = new ArrayList<Object>(myDartResolver.getLivePackageNames());
if (!result.isEmpty()) {
Collections.addAll(result, superVariants);
return ArrayUtil.toObjectArray(result);
}
}
return superVariants;
}
@Override
public PsiElement bindToElement(@NotNull final PsiElement element, final boolean absolute) throws IncorrectOperationException {
final String path = getFileReferenceSet().getPathString();
if (path.startsWith(PACKAGES_FOLDER_NAME + "/") || path.contains("/" + PACKAGES_FOLDER_NAME + "/")) {
final VirtualFile contextFile = DartResolveUtil.getRealVirtualFile(getElement().getContainingFile());
final VirtualFile targetFile = DartResolveUtil.getRealVirtualFile(element.getContainingFile());
if (contextFile != null && targetFile != null) {
final DartUrlResolver urlResolver = DartUrlResolver.getInstance(element.getProject(), contextFile);
final String newUrl = urlResolver.getDartUrlForFile(targetFile);
if (newUrl.startsWith(PACKAGE_PREFIX)) {
final int index = path.startsWith(PACKAGES_FOLDER_NAME + "/") ? 0 : (path.indexOf("/" + PACKAGES_FOLDER_NAME + "/") + 1);
final String newName = path.substring(0, index) + PACKAGES_FOLDER_NAME + "/" + newUrl.substring(PACKAGE_PREFIX.length());
return rename(newName);
}
}
}
return super.bindToElement(element, absolute);
}
}