Merge branch 'master' of git.labs.intellij.net:idea/community

This commit is contained in:
Dmitry Jemerov
2010-01-18 20:26:42 +03:00
15 changed files with 133 additions and 576 deletions
@@ -440,8 +440,8 @@ public class MoveInstanceMethodProcessor extends BaseRefactoringProcessor{
}
@Override public void visitMethodCallExpression(PsiMethodCallExpression expression) {
super.visitMethodCallExpression(expression);
correctMethodCall(expression, true);
super.visitMethodCallExpression(expression);
}
});
}
@@ -308,37 +308,27 @@ public class JavaSafeDeleteProcessor implements SafeDeleteProcessorDelegate {
removeDeletedMethods(OverridingMethodsSearch.search(psiMethod, psiMethod.getUseScope(), true).toArray(PsiMethod.EMPTY_ARRAY),
allElementsToDelete);
boolean anyRefs = false;
for (PsiReference reference : references) {
final PsiElement element = reference.getElement();
if (!isInside(element, allElementsToDelete) && !isInside(element, overridingMethods)) {
usages.add(new SafeDeleteReferenceJavaDeleteUsageInfo(element, psiMethod, false));
anyRefs = true;
}
}
final Condition<PsiElement> usageInsideDeleted;
if (!anyRefs) {
HashMap<PsiMethod, Collection<PsiReference>> methodToReferences = new HashMap<PsiMethod, Collection<PsiReference>>();
for (PsiMethod overridingMethod : overridingMethods) {
final Collection<PsiReference> overridingReferences = ReferencesSearch.search(overridingMethod).findAll();
methodToReferences.put(overridingMethod, overridingReferences);
final HashMap<PsiMethod, Collection<PsiReference>> methodToReferences = new HashMap<PsiMethod, Collection<PsiReference>>();
for (PsiMethod overridingMethod : overridingMethods) {
final Collection<PsiReference> overridingReferences = ReferencesSearch.search(overridingMethod).findAll();
methodToReferences.put(overridingMethod, overridingReferences);
}
final Set<PsiMethod> validOverriding =
validateOverridingMethods(psiMethod, references, Arrays.asList(overridingMethods), methodToReferences, usages,
allElementsToDelete);
return new Condition<PsiElement>() {
public boolean value(PsiElement usage) {
if(usage instanceof PsiFile) return false;
return isInside(usage, allElementsToDelete) || isInside(usage, validOverriding);
}
final Set<PsiMethod> validOverriding =
validateOverridingMethods(psiMethod, references, Arrays.asList(overridingMethods), methodToReferences, usages,
allElementsToDelete);
usageInsideDeleted = new Condition<PsiElement>() {
public boolean value(PsiElement usage) {
if(usage instanceof PsiFile) return false;
return isInside(usage, allElementsToDelete) || isInside(usage, validOverriding);
}
};
}
else {
usageInsideDeleted = getUsageInsideDeletedFilter(allElementsToDelete);
}
return usageInsideDeleted;
};
}
private static PsiMethod[] removeDeletedMethods(PsiMethod[] methods, final PsiElement[] allElementsToDelete) {
@@ -0,0 +1,13 @@
public class A {
void f<caret>oo(B b) {
b.foo("");
}
}
class B {
void foo(String s) {
System.out.println(s);
}
}
@@ -0,0 +1,14 @@
public class A {
}
class B {
void foo(String s) {
System.out.println(s);
}
void foo() {
foo("");
}
}
@@ -0,0 +1,16 @@
public class A {
void f<caret>oo(B b) {
b.foo("");
if (false) {
foo(b);
}
}
}
class B {
void foo(String s) {
System.out.println(s);
}
}
@@ -0,0 +1,17 @@
public class A {
}
class B {
void foo(String s) {
System.out.println(s);
}
void foo() {
foo("");
if (false) {
foo();
}
}
}
@@ -0,0 +1,9 @@
public class A {
void foo() {
bar();
}
}
class B extends A {
}
@@ -0,0 +1,13 @@
public class A {
void foo() {
bar();
}
void b<caret>ar() {}
}
class B extends A {
void bar(){
super.bar();
}
}
@@ -1,14 +1,14 @@
package com.intellij.refactoring;
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.refactoring.safeDelete.SafeDeleteHandler;
import com.intellij.JavaTestUtil;
import com.intellij.testFramework.IdeaTestUtil;
import org.jetbrains.annotations.NonNls;
import java.io.File;
@@ -61,6 +61,17 @@ public class SafeDeleteTest extends MultiFileTestCase {
doTest("UserFlags");
}
public void testRemoveOverridersInspiteOfUnsafeUsages() throws Exception {
myDoCompare = false;
try {
BaseRefactoringProcessor.ConflictsInTestsException.setTestIgnore(true);
doTest("A");
}
finally {
BaseRefactoringProcessor.ConflictsInTestsException.setTestIgnore(false);
}
}
private void doTest(@NonNls final String qClassName) throws Exception {
doTest(new PerformAction() {
public void performAction(VirtualFile rootDir, VirtualFile rootAfter) throws Exception {
@@ -49,6 +49,14 @@ public class MoveInstanceMethodTest extends LightCodeInsightTestCase {
doTest(true, 0, VisibilityUtil.ESCALATE_VISIBILITY);
}
public void testSameNames() throws Exception {
doTest(true, 0);
}
public void testSameNamesRecursion() throws Exception {
doTest(true, 0);
}
private void doTest(boolean isTargetParameter, final int targetIndex) throws Exception {
doTest(isTargetParameter, targetIndex, null);
}
@@ -286,6 +286,7 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
new HighlightInfo(info.forcedTextAttributes, info.type, hostRange.getStartOffset(), hostRange.getEndOffset(),
info.description, info.toolTip, info.type.getSeverity(null), info.isAfterEndOfLine, null, false);
patched.setHint(info.hasHint());
patched.setGutterIconRenderer(info.getGutterIconRenderer());
if (info.quickFixActionRanges != null) {
for (Pair<HighlightInfo.IntentionActionDescriptor, TextRange> pair : info.quickFixActionRanges) {
@@ -465,11 +465,21 @@ public abstract class BaseRefactoringProcessor {
}
public static class ConflictsInTestsException extends RuntimeException {
private final Collection<? extends String> messages;
private final Collection<? extends String> messages;
public ConflictsInTestsException(Collection<? extends String> messages) {
this.messages = messages;
}
private static boolean myTestIgnore = false;
public ConflictsInTestsException(Collection<? extends String> messages) {
this.messages = messages;
}
public static void setTestIgnore(boolean myIgnore) {
myTestIgnore = myIgnore;
}
public static boolean isTestIgnore() {
return myTestIgnore;
}
public Collection<String> getMessages() {
List<String> result = new ArrayList<String>(messages);
@@ -171,7 +171,7 @@ public class SafeDeleteProcessor extends BaseRefactoringProcessor {
if (!conflicts.isEmpty()) {
if (ApplicationManager.getApplication().isUnitTestMode()) {
throw new ConflictsInTestsException(conflicts);
if (!ConflictsInTestsException.isTestIgnore()) throw new ConflictsInTestsException(conflicts);
}
else {
UnsafeUsagesDialog dialog = new UnsafeUsagesDialog(ArrayUtil.toStringArray(conflicts), myProject);
@@ -83,7 +83,6 @@
<fileBasedIndex implementation="com.intellij.xml.index.XmlTagNamesIndex"/>
<fileBasedIndex implementation="com.intellij.xml.index.XmlNamespaceIndex"/>
<fileBasedIndex implementation="com.intellij.html.HtmlLinkTagIndex"/>
<include.provider implementation="com.intellij.xml.util.XIncludeProvider"/>
<indexedRootsProvider implementation="com.intellij.xml.index.ExternalResourcesRootsProvider"/>
@@ -1,544 +0,0 @@
/*
* Copyright 2000-2009 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.intellij.html;
import com.intellij.lang.Language;
import com.intellij.lang.html.HTMLLanguage;
import com.intellij.lang.xhtml.XHTMLLanguage;
import com.intellij.lang.xml.XMLLanguage;
import com.intellij.lexer.FilterLexer;
import com.intellij.lexer.HtmlHighlightingLexer;
import com.intellij.lexer.Lexer;
import com.intellij.lexer.XHtmlHighlightingLexer;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
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.psi.impl.source.tree.Factory;
import com.intellij.psi.impl.source.tree.LeafElement;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.templateLanguages.OuterLanguageElement;
import com.intellij.psi.templateLanguages.TemplateLanguage;
import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.*;
import com.intellij.util.indexing.*;
import com.intellij.util.io.DataExternalizer;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author spleaner
*/
public class HtmlLinkTagIndex extends SingleEntryFileBasedIndexExtension<HtmlLinkTagIndex.InfoHolder<HtmlLinkTagIndex.LinkInfo>> {
public static final ID<Integer, InfoHolder<LinkInfo>> INDEX_ID = ID.create("HtmlLinkTagIndex");
@NonNls private static final String LINK = "link";
@NonNls private static final String HREF_ATTR = "href";
@NonNls private static final String MEDIA_ATTR = "media";
@NonNls private static final String REL_ATTR = "rel";
@NonNls private static final String TITLE_ATTR = "title";
@NonNls private static final String TYPE_ATTR = "type";
private final FileBasedIndex.InputFilter myInputFilter = new FileBasedIndex.InputFilter() {
public boolean acceptInput(final VirtualFile file) {
if (!(file.getFileSystem() instanceof LocalFileSystem)) {
return false;
}
final FileType fileType = file.getFileType();
if (!(fileType instanceof LanguageFileType)) {
return false;
}
final LanguageFileType languageFileType = (LanguageFileType)fileType;
final Language language = languageFileType.getLanguage();
return language instanceof TemplateLanguage || (language instanceof XMLLanguage && language != XMLLanguage.INSTANCE);
}
};
private final DataExternalizer<InfoHolder<LinkInfo>> myValueExternalizer = new DataExternalizer<InfoHolder<LinkInfo>>() {
public void save(DataOutput out, InfoHolder<LinkInfo> value) throws IOException {
out.writeInt(value.myValues.length);
for (final LinkInfo linkInfo : value.myValues) {
out.writeInt(linkInfo.offset);
out.writeBoolean(linkInfo.scripted);
if (!linkInfo.scripted) {
writeString(linkInfo.value, out);
}
writeString(linkInfo.media, out);
writeString(linkInfo.type, out);
writeString(linkInfo.rel, out);
writeString(linkInfo.title, out);
}
}
private void writeString(String s, DataOutput out) throws IOException {
out.writeBoolean(s != null);
if (s != null) {
out.writeUTF(s);
}
}
public InfoHolder<LinkInfo> read(DataInput in) throws IOException {
final int size = in.readInt();
final List<LinkInfo> list = new ArrayList<LinkInfo>(size);
for (int i = 0; i < size; i++) {
final int offset = in.readInt();
final boolean scripted = in.readBoolean();
final String href = !scripted ? (in.readBoolean() ? in.readUTF() : null) : null;
final String media = in.readBoolean() ? in.readUTF() : null;
final String type = in.readBoolean() ? in.readUTF() : null;
final String rel = in.readBoolean() ? in.readUTF() : null;
final String title = in.readBoolean() ? in.readUTF() : null;
list.add(new LinkInfo(offset, scripted, href, media, type, rel, title));
}
return new InfoHolder<LinkInfo>(list.toArray(new LinkInfo[list.size()]));
}
};
public ID<Integer, InfoHolder<LinkInfo>> getName() {
return INDEX_ID;
}
public interface LinkReferenceResult {
@Nullable
PsiFile getReferencedFile();
@Nullable
PsiFile resolve();
boolean isScriptedReference();
@Nullable
String getMediaValue();
@Nullable
String getRelValue();
@Nullable
String getTitleValue();
}
@NotNull
public static List<LinkReferenceResult> getReferencedFiles(@NotNull final VirtualFile _file, @NotNull final Project project) {
final List<LinkReferenceResult> result = new ArrayList<LinkReferenceResult>();
if (!(_file.getFileSystem() instanceof LocalFileSystem)) {
return result;
}
FileBasedIndex.getInstance()
.processValues(INDEX_ID, FileBasedIndex.getFileId(_file), null, new FileBasedIndex.ValueProcessor<InfoHolder<LinkInfo>>() {
public boolean process(final VirtualFile file, final InfoHolder<LinkInfo> value) {
final PsiManager psiManager = PsiManager.getInstance(project);
final PsiFile psiFile = psiManager.findFile(file);
if (psiFile != null) {
for (final LinkInfo linkInfo : value.myValues) {
if (linkInfo.value != null || linkInfo.scripted) {
final PsiFileSystemItem[] item = new PsiFileSystemItem[]{null};
if (linkInfo.value != null) {
final LeafElement newValueElement = Factory
.createSingleLeafElement(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN, "\"" + linkInfo.value + "\"", 0,
linkInfo.value.length() + 2, null, psiManager, psiFile);
final PsiElement element = newValueElement.getPsi();
final FileReferenceSet set =
new FileReferenceSet(StringUtil.stripQuotesAroundValue(element.getText()), element, 1, null, true);
final FileReference lastReference = set.getLastReference();
if (lastReference != null) {
final PsiFileSystemItem resolved = lastReference.resolve();
if (resolved instanceof PsiFile) {
item[0] = resolved;
}
}
}
result.add(new MyLinkReferenceResult(item, linkInfo, psiFile));
}
}
}
return true;
}
}, GlobalSearchScope.allScope(project));
return result;
}
public SingleEntryIndexer<InfoHolder<LinkInfo>> getIndexer() {
return new SingleEntryIndexer<InfoHolder<LinkInfo>>(false) {
protected InfoHolder<LinkInfo> computeValue(@NotNull FileContent inputData) {
final Language language = ((LanguageFileType)inputData.getFileType()).getLanguage();
final List<LinkInfo> result = new ArrayList<LinkInfo>();
if (HTMLLanguage.INSTANCE == language || XHTMLLanguage.INSTANCE == language) {
mapHtml(inputData, language, result);
}
else {
mapJsp(inputData, result);
}
return new InfoHolder<LinkInfo>(result.toArray(new LinkInfo[result.size()]));
}
};
}
private static void mapJsp(FileContent inputData, final List<LinkInfo> result) {
final FileViewProvider viewProvider = inputData.getPsiFile().getViewProvider();
PsiFile psiFile = null;
if (viewProvider instanceof TemplateLanguageFileViewProvider) {
final Language dataLanguage = ((TemplateLanguageFileViewProvider)viewProvider).getTemplateDataLanguage();
if (dataLanguage == HTMLLanguage.INSTANCE || dataLanguage == XHTMLLanguage.INSTANCE) {
psiFile = viewProvider.getPsi(dataLanguage);
}
}
else {
psiFile = viewProvider.getPsi(viewProvider.getBaseLanguage());
}
if (psiFile != null) {
final XmlRecursiveElementVisitor visitor = new XmlRecursiveElementVisitor() {
@Override
public void visitXmlTag(XmlTag tag) {
if (LINK.equalsIgnoreCase(tag.getLocalName())) {
final String href = getAttributeValue(tag, HREF_ATTR);
final String media = getAttributeValue(tag, MEDIA_ATTR);
final String type = getAttributeValue(tag, TYPE_ATTR);
final String rel = getAttributeValue(tag, REL_ATTR);
final String title = getAttributeValue(tag, TITLE_ATTR);
addResult(result, tag.getTextOffset(), href, media, type, rel, title, isHrefScripted(tag));
}
super.visitXmlTag(tag);
}
};
psiFile.accept(visitor);
}
}
private static void mapHtml(FileContent inputData, Language language, List<LinkInfo> result) {
final Lexer original = HTMLLanguage.INSTANCE == language ? new HtmlHighlightingLexer() : new XHtmlHighlightingLexer();
final Lexer lexer = new FilterLexer(original, new FilterLexer.Filter() {
public boolean reject(final IElementType type) {
return XmlElementType.XML_WHITE_SPACE == type;
}
});
final CharSequence data = inputData.getContentAsText();
lexer.start(data);
IElementType tokenType = lexer.getTokenType();
boolean linkTag = false;
while (tokenType != null) {
if (XmlElementType.XML_TAG_NAME == tokenType) {
final String tagName = data.subSequence(lexer.getTokenStart(), lexer.getTokenEnd()).toString();
linkTag = LINK.equalsIgnoreCase(tagName);
//if (BODY_TAG.equalsIgnoreCase(tagName)) {
// break; // there are no LINK tags under the body
//}
}
if (linkTag && XmlElementType.XML_NAME == tokenType) {
int linkTagOffset = lexer.getTokenStart();
String href = null;
String type = null;
String media = null;
String rel = null;
String title = null;
while (true) {
if (tokenType == null ||
tokenType == XmlTokenType.XML_END_TAG_START ||
tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END ||
tokenType == XmlTokenType.XML_START_TAG_START) {
break;
}
if (XmlElementType.XML_NAME == tokenType) {
final String attrName = data.subSequence(lexer.getTokenStart(), lexer.getTokenEnd()).toString();
if (HREF_ATTR.equalsIgnoreCase(attrName)) {
href = parseAttributeValue(lexer, data);
}
else if (MEDIA_ATTR.equalsIgnoreCase(attrName)) {
media = parseAttributeValue(lexer, data);
}
else if (TYPE_ATTR.equalsIgnoreCase(attrName)) {
type = parseAttributeValue(lexer, data);
}
else if (REL_ATTR.equalsIgnoreCase(attrName)) {
rel = parseAttributeValue(lexer, data);
}
else if (TITLE_ATTR.equalsIgnoreCase(attrName)) {
title = parseAttributeValue(lexer, data);
}
}
lexer.advance();
tokenType = lexer.getTokenType();
}
addResult(result, linkTagOffset, href, media, type, rel, title, false);
}
lexer.advance();
tokenType = lexer.getTokenType();
}
}
private static boolean isHrefScripted(final XmlTag tag) {
final XmlAttribute attribute = tag.getAttribute(HREF_ATTR);
if (attribute != null) {
final XmlAttributeValue value = attribute.getValueElement();
if (value != null) {
if (PsiTreeUtil.getChildOfType(value, OuterLanguageElement.class) != null) {
return true;
}
}
}
return false;
}
@Nullable
private static String getAttributeValue(final XmlTag tag, final String attrName) {
final XmlAttribute attribute = tag.getAttribute(attrName);
if (attribute != null) {
final XmlAttributeValue value = attribute.getValueElement();
if (value != null) {
if (PsiTreeUtil.getChildOfType(value, OuterLanguageElement.class) == null) {
return value.getValue();
}
}
}
return null;
}
@Nullable
private static String parseAttributeValue(final Lexer lexer, CharSequence data) {
lexer.advance();
IElementType tokenType = lexer.getTokenType();
if (XmlElementType.XML_EQ == tokenType) {
lexer.advance();
tokenType = lexer.getTokenType();
if (tokenType == XmlElementType.XML_ATTRIBUTE_VALUE_START_DELIMITER) {
lexer.advance();
tokenType = lexer.getTokenType();
if (XmlElementType.XML_ATTRIBUTE_VALUE_TOKEN == tokenType) {
return data.subSequence(lexer.getTokenStart(), lexer.getTokenEnd()).toString();
}
}
else if (tokenType != XmlTokenType.XML_TAG_END && tokenType != XmlTokenType.XML_EMPTY_ELEMENT_END) {
return data.subSequence(lexer.getTokenStart(), lexer.getTokenEnd()).toString();
}
}
return null;
}
private static void addResult(final List<LinkInfo> result,
final int offset,
final String hrefValue,
final String mediaValue,
final String typeValue,
final String relValue,
final String titleValue,
final boolean scripted) {
result.add(new LinkInfo(offset, scripted, hrefValue, mediaValue, typeValue, relValue, titleValue));
}
public DataExternalizer<InfoHolder<LinkInfo>> getValueExternalizer() {
return myValueExternalizer;
}
public FileBasedIndex.InputFilter getInputFilter() {
return myInputFilter;
}
public int getVersion() {
return 4;
}
public static class LinkInfo {
public int offset;
public String value;
public String media;
public String type;
public String rel;
public String title;
public boolean scripted;
public LinkInfo(final int textOffset,
final boolean scriptedRef,
@Nullable final String hrefValue,
@Nullable final String mediaValue,
@Nullable final String typeValue,
@Nullable final String relValue,
@Nullable final String titleValue) {
offset = textOffset;
scripted = scriptedRef;
value = hrefValue;
media = mediaValue;
type = typeValue;
rel = relValue;
title = titleValue;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final LinkInfo linkInfo = (LinkInfo)o;
if (offset != linkInfo.offset) return false;
if (scripted != linkInfo.scripted) return false;
if (media != null ? !media.equals(linkInfo.media) : linkInfo.media != null) return false;
if (rel != null ? !rel.equals(linkInfo.rel) : linkInfo.rel != null) return false;
if (title != null ? !title.equals(linkInfo.title) : linkInfo.title != null) return false;
if (type != null ? !type.equals(linkInfo.type) : linkInfo.type != null) return false;
if (value != null ? !value.equals(linkInfo.value) : linkInfo.value != null) return false;
return true;
}
@Override
public int hashCode() {
int result = offset;
result = 31 * result + (value != null ? value.hashCode() : 0);
result = 31 * result + (media != null ? media.hashCode() : 0);
result = 31 * result + (type != null ? type.hashCode() : 0);
result = 31 * result + (rel != null ? rel.hashCode() : 0);
result = 31 * result + (title != null ? title.hashCode() : 0);
result = 31 * result + (scripted ? 1 : 0);
return result;
}
}
private static class MyLinkReferenceResult implements LinkReferenceResult {
private final PsiFileSystemItem[] myItem;
private final LinkInfo myLinkInfo;
private final PsiFile myPsiFile;
public MyLinkReferenceResult(final PsiFileSystemItem[] item, final LinkInfo linkInfo, final PsiFile psiFile) {
myItem = item;
myLinkInfo = linkInfo;
myPsiFile = psiFile;
}
public PsiFile getReferencedFile() {
return (PsiFile)myItem[0];
}
public PsiFile resolve() {
final PsiFile referencedFile = getReferencedFile();
if (referencedFile != null) {
return referencedFile;
}
if (myPsiFile != null) {
final PsiElement psiElement = myPsiFile.findElementAt(myLinkInfo.offset);
if (psiElement != null) {
final PsiElement parent = psiElement.getParent();
if (parent instanceof XmlTag) {
final XmlAttribute attribute = ((XmlTag)parent).getAttribute(HREF_ATTR);
if (attribute != null) {
final XmlAttributeValue value = attribute.getValueElement();
if (value != null) {
final PsiReference[] references = value.getReferences();
for (PsiReference reference : references) {
final PsiElement element = reference.resolve();
if (element instanceof PsiFile) {
return (PsiFile)element;
}
}
}
}
}
}
}
return null;
}
public boolean isScriptedReference() {
return myLinkInfo.scripted;
}
public String getMediaValue() {
return myLinkInfo.media;
}
public String getRelValue() {
return myLinkInfo.rel;
}
public String getTitleValue() {
return myLinkInfo.title;
}
}
static class InfoHolder<T> {
public T[] myValues;
InfoHolder(final T[] values) {
myValues = values;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final InfoHolder that = (InfoHolder)o;
if (!Arrays.equals(myValues, that.myValues)) return false;
return true;
}
@Override
public int hashCode() {
return myValues != null ? Arrays.hashCode(myValues) : 0;
}
}
}