diff --git a/java/java-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java index 9eb3954df378..f71306d568fc 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java @@ -26,6 +26,7 @@ import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; +import com.intellij.psi.augment.PsiAugmentProvider; import com.intellij.psi.impl.InheritanceImplUtil; import com.intellij.psi.impl.PsiClassImplUtil; import com.intellij.psi.impl.PsiImplUtil; @@ -50,6 +51,7 @@ import com.intellij.psi.stubs.IStubElementType; import com.intellij.psi.stubs.PsiFileStub; import com.intellij.psi.stubs.StubElement; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -300,12 +302,16 @@ public class PsiClassImpl extends JavaStubPsiElement> implements @NotNull public PsiField[] getFields() { - return getStubOrPsiChildren(Constants.FIELD_BIT_SET, PsiField.ARRAY_FACTORY); + final PsiField[] owns = getStubOrPsiChildren(Constants.FIELD_BIT_SET, PsiField.ARRAY_FACTORY); + final List augments = PsiAugmentProvider.collectAugments(this, PsiField.class); + return ArrayUtil.mergeArrayAndCollection(owns, augments, PsiField.ARRAY_FACTORY); } @NotNull public PsiMethod[] getMethods() { - return getStubOrPsiChildren(Constants.METHOD_BIT_SET, PsiMethod.ARRAY_FACTORY); + final PsiMethod[] owns = getStubOrPsiChildren(Constants.METHOD_BIT_SET, PsiMethod.ARRAY_FACTORY); + final List augments = PsiAugmentProvider.collectAugments(this, PsiMethod.class); + return ArrayUtil.mergeArrayAndCollection(owns, augments, PsiMethod.ARRAY_FACTORY); } @NotNull diff --git a/java/java-impl/src/com/intellij/psi/impl/source/PsiFieldImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/PsiFieldImpl.java index 5934af0584cf..4cec786ca1ac 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/PsiFieldImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/PsiFieldImpl.java @@ -93,7 +93,7 @@ public class PsiFieldImpl extends JavaStubPsiElement implements Ps } @NotNull - public final PsiIdentifier getNameIdentifier(){ + public PsiIdentifier getNameIdentifier() { return (PsiIdentifier)getNode().findChildByRoleAsPsiElement(ChildRole.NAME); } diff --git a/java/java-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java index 5144c7793908..2ce9002a3470 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java @@ -545,7 +545,8 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme final boolean preserveQualification = CodeStyleSettingsManager.getSettings(getProject()).USE_FQ_CLASS_NAMES && isFullyQualified(); final PsiManager manager = aClass.getManager(); - String text = qName + getParameterList().getText(); + final PsiReferenceParameterList parameterList = getParameterList(); + String text = (parameterList != null ? qName + parameterList.getText() : qName); ASTNode ref = Parsing.parseJavaCodeReferenceText(manager, text, SharedImplUtil.findCharTableByTree(this)); LOG.assertTrue(ref != null, "Failed to parse reference from text '" + text + "'"); getTreeParent().replaceChildInternal(this, (TreeElement)ref); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java index a66bc09749ff..c392f81edfbb 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java @@ -19,6 +19,7 @@ import com.intellij.codeInsight.daemon.impl.analysis.AnnotationsHighlightUtil; import com.intellij.lang.ASTNode; import com.intellij.openapi.util.Condition; import com.intellij.psi.*; +import com.intellij.psi.augment.PsiAugmentProvider; import com.intellij.psi.impl.CheckUtil; import com.intellij.psi.impl.PsiImplUtil; import com.intellij.psi.impl.cache.ModifierFlags; @@ -29,6 +30,7 @@ import com.intellij.psi.impl.source.tree.Factory; import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.impl.source.tree.TreeElement; import com.intellij.psi.tree.IElementType; +import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashMap; @@ -254,7 +256,9 @@ public class PsiModifierListImpl extends JavaStubPsiElement @NotNull public PsiAnnotation[] getAnnotations() { - return getStubOrPsiChildren(JavaStubElementTypes.ANNOTATION, PsiAnnotation.ARRAY_FACTORY); + final PsiAnnotation[] owns = getStubOrPsiChildren(JavaStubElementTypes.ANNOTATION, PsiAnnotation.ARRAY_FACTORY); + final List augments = PsiAugmentProvider.collectAugments(this, PsiAnnotation.class); + return ArrayUtil.mergeArrayAndCollection(owns, augments, PsiAnnotation.ARRAY_FACTORY); } @NotNull diff --git a/java/java-impl/src/com/intellij/psi/impl/source/PsiReferenceListImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/PsiReferenceListImpl.java index 4fd991128651..e4bebf7d64b2 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/PsiReferenceListImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/PsiReferenceListImpl.java @@ -18,13 +18,17 @@ package com.intellij.psi.impl.source; import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.*; +import com.intellij.psi.augment.PsiAugmentProvider; import com.intellij.psi.impl.java.stubs.PsiClassReferenceListStub; import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.stubs.IStubElementType; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; +import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; +import java.util.List; + public final class PsiReferenceListImpl extends JavaStubPsiElement implements PsiReferenceList { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.PsiReferenceListImpl"); private static final TokenSet REFERENCE_BIT_SET = TokenSet.create(Constants.JAVA_CODE_REFERENCE); @@ -39,7 +43,10 @@ public final class PsiReferenceListImpl extends JavaStubPsiElement augments = PsiAugmentProvider.collectAugments(this, PsiJavaCodeReferenceElement.class); + return ArrayUtil.mergeArrayAndCollection(owns, augments, PsiJavaCodeReferenceElement.ARRAY_FACTORY); } @NotNull diff --git a/java/java-impl/src/com/intellij/psi/impl/source/parsing/DeclarationParsing.java b/java/java-impl/src/com/intellij/psi/impl/source/parsing/DeclarationParsing.java index a65fc59100ff..2c15cf9eacae 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/parsing/DeclarationParsing.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/parsing/DeclarationParsing.java @@ -469,6 +469,20 @@ public class DeclarationParsing extends Parsing { return first; } + @NotNull + public CompositeElement parseAnnotationParamsFromText(PsiManager manager, CharSequence text, final LanguageLevel languageLevel) { + Lexer originalLexer = new JavaLexer(languageLevel); + FilterLexer lexer = new FilterLexer(originalLexer, new FilterLexer.SetFilter(StdTokenSets.WHITE_SPACE_OR_COMMENT_BIT_SET)); + lexer.start(text); + CompositeElement first = parseAnnotationParameterList(lexer); + + final FileElement dummyRoot = DummyHolderFactory.createHolder(manager, null, myContext.getCharTable()).getTreeElement(); + dummyRoot.rawAddChildren(first); + + ParseUtil.insertMissingTokens(dummyRoot, originalLexer, 0, text.length(), -1, WhiteSpaceAndCommentsProcessor.INSTANCE, myContext); + return first; + } + @NotNull CompositeElement parseAnnotation(Lexer lexer) { CompositeElement annotation = ASTFactory.composite(JavaElementType.ANNOTATION); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationImpl.java index 2134a2161f72..7ebc1293e783 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationImpl.java @@ -24,9 +24,8 @@ import com.intellij.psi.impl.java.stubs.JavaStubElementTypes; import com.intellij.psi.impl.java.stubs.PsiAnnotationStub; import com.intellij.psi.impl.meta.MetaRegistry; import com.intellij.psi.impl.source.JavaStubPsiElement; -import com.intellij.psi.impl.source.tree.ChildRole; -import com.intellij.psi.impl.source.tree.CompositeElement; import com.intellij.psi.meta.PsiMetaData; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.PairFunction; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -51,17 +50,7 @@ public class PsiAnnotationImpl extends JavaStubPsiElement imp } public PsiJavaCodeReferenceElement getNameReferenceElement() { - return (PsiJavaCodeReferenceElement)getMirrorTreeElement().findChildByRoleAsPsiElement(ChildRole.CLASS_REFERENCE); - } - - - private CompositeElement getMirrorTreeElement() { - final PsiAnnotationStub stub = getStub(); - if (stub != null) { - return stub.getTreeElement(); - } - - return (CompositeElement)getNode(); + return PsiTreeUtil.getChildOfType(this, PsiJavaCodeReferenceElement.class); } public PsiAnnotationMemberValue findAttributeValue(String attributeName) { @@ -83,7 +72,7 @@ public class PsiAnnotationImpl extends JavaStubPsiElement imp @NotNull public PsiAnnotationParameterList getParameterList() { - return (PsiAnnotationParameterList)getMirrorTreeElement().findChildByRoleAsPsiElement(ChildRole.PARAMETER_LIST); + return PsiTreeUtil.getRequiredChildOfType(this, PsiAnnotationParameterList.class); } @Nullable public String getQualifiedName() { diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiNameValuePairImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiNameValuePairImpl.java index ef6b927611cd..a24afb5db17b 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiNameValuePairImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiNameValuePairImpl.java @@ -126,8 +126,8 @@ public class PsiNameValuePairImpl extends CompositePsiElement implements PsiName public PsiReference getReference() { return new PsiReference() { private PsiClass getReferencedClass () { - LOG.assertTrue(getTreeParent().getElementType() == ANNOTATION_PARAMETER_LIST && getTreeParent().getTreeParent().getElementType() == ANNOTATION); - PsiAnnotationImpl annotation = (PsiAnnotationImpl)getTreeParent().getTreeParent().getPsi(); + LOG.assertTrue(getParent() instanceof PsiAnnotationParameterList && getParent().getParent() instanceof PsiAnnotation); + PsiAnnotation annotation = (PsiAnnotation)getParent().getParent(); PsiJavaCodeReferenceElement nameRef = annotation.getNameReferenceElement(); return nameRef == null ? null : (PsiClass)nameRef.resolve(); } diff --git a/java/openapi/src/com/intellij/psi/PsiJavaCodeReferenceElement.java b/java/openapi/src/com/intellij/psi/PsiJavaCodeReferenceElement.java index d48a153b7538..695d56b9dec7 100644 --- a/java/openapi/src/com/intellij/psi/PsiJavaCodeReferenceElement.java +++ b/java/openapi/src/com/intellij/psi/PsiJavaCodeReferenceElement.java @@ -15,6 +15,7 @@ */ package com.intellij.psi; +import com.intellij.util.ArrayFactory; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,6 +29,12 @@ public interface PsiJavaCodeReferenceElement extends PsiJavaReference, PsiQualif */ PsiJavaCodeReferenceElement[] EMPTY_ARRAY = new PsiJavaCodeReferenceElement[0]; + ArrayFactory ARRAY_FACTORY = new ArrayFactory() { + public PsiJavaCodeReferenceElement[] create(int count) { + return count == 0 ? EMPTY_ARRAY : new PsiJavaCodeReferenceElement[count]; + } + }; + /** * Returns the element representing the name of the referenced element. * diff --git a/java/openapi/src/com/intellij/psi/augment/PsiAugmentProvider.java b/java/openapi/src/com/intellij/psi/augment/PsiAugmentProvider.java new file mode 100644 index 000000000000..6e0c5d121934 --- /dev/null +++ b/java/openapi/src/com/intellij/psi/augment/PsiAugmentProvider.java @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2010 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.psi.augment; + +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + + +public abstract class PsiAugmentProvider { + public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.lang.psiAugmentProvider"); + + private static final PsiAugmentProvider[] PROVIDERS = Extensions.getExtensions(EP_NAME); + + @NotNull + public abstract List getAugments(@NotNull PsiElement element, @NotNull Class type); + + @NotNull + public static List collectAugments(@NotNull final PsiElement element, @NotNull final Class type) { + final List augments = new ArrayList(); + for (PsiAugmentProvider provider : PROVIDERS) { + final List list = provider.getAugments(element, type); + augments.addAll(list); + } + + return augments; + } +} diff --git a/platform/lang-api/src/com/intellij/codeInspection/ProblemsHolder.java b/platform/lang-api/src/com/intellij/codeInspection/ProblemsHolder.java index 4d939237a213..de40323c0f24 100644 --- a/platform/lang-api/src/com/intellij/codeInspection/ProblemsHolder.java +++ b/platform/lang-api/src/com/intellij/codeInspection/ProblemsHolder.java @@ -19,9 +19,13 @@ package com.intellij.codeInspection; import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.ExternallyDefinedPsiElement; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiReference; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; @@ -58,11 +62,17 @@ public class ProblemsHolder { } public void registerProblem(@NotNull ProblemDescriptor problemDescriptor) { - if (myProblems == null) { - myProblems = new ArrayList(1); - } PsiElement element = problemDescriptor.getPsiElement(); if (element != null && !isInPsiFile(element)) { + ExternallyDefinedPsiElement external = PsiTreeUtil.getParentOfType(element, ExternallyDefinedPsiElement.class, false); + if (external != null) { + PsiElement newTarget = external.getProblemTarget(); + if (newTarget != null) { + redirectProblem(problemDescriptor, newTarget); + return; + } + } + PsiFile containingFile = element.getContainingFile(); PsiElement context = containingFile.getContext(); PsiElement myContext = myFile.getContext(); @@ -71,6 +81,10 @@ public class ProblemsHolder { +"Inspection invoked for file: "+ myFile +"; context: "+(myContext == null ? null : myContext.getContainingFile())+"\n" ); } + + if (myProblems == null) { + myProblems = new ArrayList(1); + } myProblems.add(problemDescriptor); } @@ -79,6 +93,31 @@ public class ProblemsHolder { return ArrayUtil.indexOf(myFile.getPsiRoots(), file) != -1; } + private void redirectProblem(@NotNull final ProblemDescriptor problem, @NotNull final PsiElement target) { + final PsiElement original = problem.getPsiElement(); + final VirtualFile vFile = original.getContainingFile().getVirtualFile(); + assert vFile != null; + final String path = FileUtil.toSystemIndependentName(vFile.getPath()); + + String description = problem.getDescriptionTemplate(); + if (description.startsWith("")) { + description = description.replace("", "").replace("", ""); + } + if (description.startsWith("")) { + description = description.replace("", "").replace("", ""); + } + + final String template = + InspectionsBundle.message("inspection.redirect.template", + description, path, original.getTextRange().getStartOffset(), vFile.getName()); + + + final InspectionManager manager = InspectionManager.getInstance(original.getProject()); + final ProblemDescriptor newProblem = + manager.createProblemDescriptor(target, template, (LocalQuickFix)null, problem.getHighlightType(), isOnTheFly()); + registerProblem(newProblem); + } + public void registerProblem(@NotNull PsiReference reference, String descriptionTemplate, ProblemHighlightType highlightType) { LocalQuickFix[] fixes = null; if (reference instanceof LocalQuickFixProvider) { diff --git a/platform/lang-api/src/com/intellij/psi/ExternallyDefinedPsiElement.java b/platform/lang-api/src/com/intellij/psi/ExternallyDefinedPsiElement.java new file mode 100644 index 000000000000..a08b5862e735 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/ExternallyDefinedPsiElement.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2010 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.psi; + +import org.jetbrains.annotations.Nullable; + + +/** + * Interface for PSI elements which may be injected into other elements but physically belongs + * to other file - like AspectJ inter-type fields/methods. + */ +public interface ExternallyDefinedPsiElement extends PsiElement, SyntheticElement { + /** + * If inspection started for files with injections founds any problem in them (or their child) + * it should be able to display them locally. This method allows to define such substitution element. + * E.g. it may be a class name identifier element for fields/methods injected in that class.
+ * See ProblemsHolder.redirectProblem() for details. + * + * @return PSI element to which problem descriptions should be redirected + */ + @Nullable + PsiElement getProblemTarget(); +} diff --git a/platform/lang-api/src/com/intellij/psi/util/PsiTreeUtil.java b/platform/lang-api/src/com/intellij/psi/util/PsiTreeUtil.java index a9937d396b91..ba50a6d79dd9 100644 --- a/platform/lang-api/src/com/intellij/psi/util/PsiTreeUtil.java +++ b/platform/lang-api/src/com/intellij/psi/util/PsiTreeUtil.java @@ -172,6 +172,13 @@ public class PsiTreeUtil { } return null; } + + @NotNull public static T getRequiredChildOfType(@NotNull PsiElement element, @NotNull Class aClass) { + final T child = getChildOfType(element, aClass); + assert child != null: "Missing required child of type " + aClass.getName(); + return child; + } + @Nullable public static T[] getChildrenOfType(@NotNull PsiElement element, @NotNull Class aClass) { List result = null; for(PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()){ diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hint/NavigationLinkHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/hint/NavigationLinkHandler.java new file mode 100644 index 000000000000..de9cbf93c29a --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/hint/NavigationLinkHandler.java @@ -0,0 +1,62 @@ +/* + * Copyright 2000-2010 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.codeInsight.hint; + +import com.intellij.codeInsight.highlighting.TooltipLinkHandler; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.fileEditor.OpenFileDescriptor; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; + + +/** + * Handles tooltip links in format #navigation/file path:offset. + */ +public class NavigationLinkHandler extends TooltipLinkHandler { + private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.hint.NavigationLinkHandler"); + + @Override + public void handleLink(@NotNull final String suffix, @NotNull final Editor editor, @NotNull final JEditorPane tooltip) { + final int pos = suffix.lastIndexOf(':'); + if (pos <= 0 || pos == suffix.length()-1) { + LOG.error("Malformed suffix: " + suffix); + return; + } + + final String path = suffix.substring(0, pos); + final VirtualFile vFile = LocalFileSystem.getInstance().findFileByPath(path); + if (vFile == null) { + LOG.error("Unknown file: " + path); + return; + } + + final int offset; + try { + offset = Integer.parseInt(suffix.substring(pos+1)); + } + catch (NumberFormatException e) { + LOG.error("Malformed suffix: " + suffix); + return; + } + + tooltip.setVisible(false); + new OpenFileDescriptor(editor.getProject(), vFile, offset).navigate(true); + } +} diff --git a/platform/platform-resources-en/src/messages/InspectionsBundle.properties b/platform/platform-resources-en/src/messages/InspectionsBundle.properties index 464ad78aea1f..c4ba9849fdbc 100644 --- a/platform/platform-resources-en/src/messages/InspectionsBundle.properties +++ b/platform/platform-resources-en/src/messages/InspectionsBundle.properties @@ -617,3 +617,5 @@ inspection.application.chosen.profile.log\ message=Inspecting with profile ''{0} detach.library.quickfix.name=Detach library detach.library.roots.quickfix.name=Detach unused library roots inspection.javadoc.problem.pointing.to.itself=Javadoc pointing to itself + +inspection.redirect.template=Injected element has problem: {0} (in {3}). diff --git a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml index f7e1a8408572..20ab2cd85189 100644 --- a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml @@ -115,6 +115,8 @@ + + + diff --git a/platform/util/src/com/intellij/util/ArrayUtil.java b/platform/util/src/com/intellij/util/ArrayUtil.java index 879d4539fffc..444f20fe425b 100644 --- a/platform/util/src/com/intellij/util/ArrayUtil.java +++ b/platform/util/src/com/intellij/util/ArrayUtil.java @@ -155,6 +155,32 @@ public class ArrayUtil { return a; } + /** + * Allocates new array of size array.length + collection.size() and copies elements of array and + * collection to it. + * @param array source array + * @param collection source collection + * @param factory array factory used to create destination array of type T + * @return destination array + */ + @NotNull + public static T[] mergeArrayAndCollection(@NotNull T[] array, @NotNull Collection collection, + @NotNull final ArrayFactory factory) { + if (collection.size() == 0) { + return array; + } + + final T[] array2 = collection.toArray(factory.create(collection.size())); + if (array.length == 0) { + return array2; + } + + final T[] result = factory.create(array.length + collection.size()); + System.arraycopy(array, 0, result, 0, array.length); + System.arraycopy(array2, 0, result, array.length, array2.length); + return result; + } + /** * Appends element to the src array. As you can * imagine the appended element will be the last one in the returned result.