blob: 84760d87eed36a6e2d0262819244334999a885e2 [file] [log] [blame]
/*
* Copyright 2000-2013 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 com.jetbrains.python.templateLanguages;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.ElementManipulators;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileSystemItem;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceHelper;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.PsiFileSystemItemUtil;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.psi.WeakFileReference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
/**
* @author yole
*/
public class TemplateFileReference extends WeakFileReference {
public TemplateFileReference(@NotNull FileReferenceSet fileReferenceSet, TextRange range, int index, String text) {
super(fileReferenceSet, range, index, text);
}
@Nullable
@Override
public String getUnresolvedDescription() {
return "Template file '" + getCanonicalText() + "' not found";
}
@Override
public PsiElement bindToElement(@NotNull PsiElement element, boolean absolute) throws IncorrectOperationException {
if (!(element instanceof PsiFileSystemItem)) {
throw new IncorrectOperationException("Cannot bind to element, should be instanceof PsiFileSystemItem: " + element);
}
final PsiFileSystemItem fileSystemItem = (PsiFileSystemItem)element;
VirtualFile dstVFile = fileSystemItem.getVirtualFile();
if (dstVFile == null) throw new IncorrectOperationException("Cannot bind to non-physical element:" + element);
PsiFile file = getElement().getContainingFile();
PsiElement contextPsiFile = InjectedLanguageManager.getInstance(file.getProject()).getInjectionHost(file);
if (contextPsiFile != null) file = contextPsiFile.getContainingFile(); // use host file!
final VirtualFile curVFile = file.getVirtualFile();
if (curVFile == null) throw new IncorrectOperationException("Cannot bind from non-physical element:" + file);
String newName;
PsiFileSystemItem curItem = null;
PsiFileSystemItem dstItem = null;
PsiFileSystemItem _dstItem = FileReferenceHelper.getPsiFileSystemItem(file.getManager(), dstVFile);
PsiFileSystemItem _curItem = FileReferenceHelper.getPsiFileSystemItem(file.getManager(), curVFile);
if (_dstItem != null && _curItem != null) {
curItem = _curItem;
dstItem = _dstItem;
}
final Collection<PsiFileSystemItem> contexts = getContexts();
switch (contexts.size()) {
case 0:
break;
default:
for (PsiFileSystemItem context : contexts) {
final VirtualFile contextFile = context.getVirtualFile();
assert contextFile != null;
if (VfsUtil.isAncestor(contextFile, dstVFile, true)) {
final String path = VfsUtilCore.getRelativePath(dstVFile, contextFile, '/');
if (path != null) {
return rename(path.replace("/", getFileReferenceSet().getSeparatorString()));
}
}
}
}
if (curItem == null) {
throw new IncorrectOperationException("Cannot find path between files; " +
"src = " + curVFile.getPresentableUrl() + "; " +
"dst = " + dstVFile.getPresentableUrl() + "; " +
"Contexts: " + contexts);
}
if (curItem.equals(dstItem)) {
if (getCanonicalText().equals(dstItem.getName())) {
return getElement();
}
return ElementManipulators.getManipulator(getElement()).handleContentChange(getElement(), getRangeInElement(), file.getName());
}
newName = PsiFileSystemItemUtil.getRelativePath(curItem, dstItem);
if (newName == null) {
return getElement();
}
return rename(newName);
}
}