Prevent annotated references from being shortened

This commit is contained in:
Roman Shevchenko
2013-03-14 13:27:28 +01:00
parent 3974ecd479
commit b6a22dcebc
6 changed files with 141 additions and 45 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* 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.
@@ -20,6 +20,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.source.PsiJavaCodeReferenceElementImpl;
import com.intellij.psi.impl.source.SourceJavaCodeReference;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
@@ -27,6 +28,7 @@ import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
import com.intellij.psi.impl.source.tree.*;
import com.intellij.psi.jsp.JspFile;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -51,7 +53,7 @@ public class ReferenceAdjuster {
public TreeElement process(TreeElement element, boolean addImports, boolean uncompleteCode) {
IElementType elementType = element.getElementType();
if (elementType == JavaElementType.JAVA_CODE_REFERENCE || elementType == JavaElementType.REFERENCE_EXPRESSION) {
if ((elementType == JavaElementType.JAVA_CODE_REFERENCE || elementType == JavaElementType.REFERENCE_EXPRESSION) && !isAnnotated(element)) {
final IElementType parentElementType = element.getTreeParent().getElementType();
if (elementType == JavaElementType.JAVA_CODE_REFERENCE || parentElementType == JavaElementType.REFERENCE_EXPRESSION || parentElementType == JavaElementType.METHOD_REF_EXPRESSION || uncompleteCode) {
final PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement)SourceTreeToPsiMap.treeElementToPsi(element);
@@ -126,6 +128,26 @@ public class ReferenceAdjuster {
return element;
}
private static boolean isAnnotated(TreeElement element) {
PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement)element.getPsi();
PsiElement qualifier = ref.getQualifier();
if (qualifier instanceof PsiJavaCodeReferenceElement && PsiTreeUtil.getChildOfType(qualifier, PsiAnnotation.class) != null) {
return true;
}
PsiModifierList modifierList = PsiImplUtil.findNeighbourModifierList(ref);
if (modifierList != null) {
for (PsiAnnotation annotation : modifierList.getAnnotations()) {
if (PsiImplUtil.findApplicableTarget(annotation, PsiAnnotation.TargetType.TYPE_USE) != null) {
return true;
}
}
}
return false;
}
private boolean makeFQ(boolean isInsideDocComment) {
if (isInsideDocComment) {
return myUseFqClassnamesInJavadoc;

View File

@@ -717,4 +717,17 @@ public class PsiImplUtil {
public static PsiElement handleMirror(PsiElement element) {
return element instanceof PsiMirrorElement ? ((PsiMirrorElement)element).getPrototype() : element;
}
@Nullable
public static PsiModifierList findNeighbourModifierList(@NotNull PsiJavaCodeReferenceElement ref) {
PsiElement parent = PsiTreeUtil.skipParentsOfType(ref, PsiJavaCodeReferenceElement.class);
if (parent instanceof PsiTypeElement) {
PsiElement prevElement = PsiTreeUtil.skipSiblingsBackward(parent, PsiComment.class, PsiWhiteSpace.class, PsiTypeParameterList.class);
if (prevElement instanceof PsiModifierList) {
return (PsiModifierList)prevElement;
}
}
return null;
}
}

View File

@@ -49,6 +49,8 @@ import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement implements PsiJavaCodeReferenceElement, SourceJavaCodeReference {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.PsiJavaCodeReferenceElementImpl");
@@ -193,15 +195,27 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
}
@Override
public void deleteChildInternal(@NotNull final ASTNode child) {
public void deleteChildInternal(@NotNull ASTNode child) {
if (getChildRole(child) == ChildRole.QUALIFIER) {
ASTNode dot = findChildByRole(ChildRole.DOT);
ASTNode dot = findChildByType(JavaTokenType.DOT, child);
assert dot != null : this;
deleteChildRange(child.getPsi(), dot.getPsi());
List<PsiAnnotation> annotations = PsiTreeUtil.getChildrenOfTypeAsList(this, PsiAnnotation.class);
if (!annotations.isEmpty()) {
PsiModifierList modifierList = PsiImplUtil.findNeighbourModifierList(this);
if (modifierList != null) {
for (PsiAnnotation annotation : annotations) {
modifierList.add(annotation);
annotation.delete();
}
}
}
return;
}
else {
super.deleteChildInternal(child);
}
super.deleteChildInternal(child);
}
@Override

View File

@@ -0,0 +1,15 @@
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
@Target({TYPE_USE}) @interface TA { }
class Outer {
class Middle {
class Inner {
void m1(Outer.Middle.Inner p) { }
void m2(@TA Outer.Middle.Inner p) { }
void m3(Outer.@TA Middle.Inner p) { }
void m4(Outer.Middle.@TA @TA Inner p) { }
}
}
}

View File

@@ -0,0 +1,15 @@
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
@Target({TYPE_USE}) @interface TA { }
class Outer {
class Middle {
class Inner {
void m1(Inner p) { }
void m2(@TA Outer.Middle.Inner p) { }
void m3(@TA Middle.Inner p) { }
void m4(@TA @TA Inner p) { }
}
}
}

View File

@@ -1,3 +1,18 @@
/*
* 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.intellij.psi.impl.source.tree.java;
import com.intellij.openapi.application.ApplicationManager;
@@ -5,14 +20,15 @@ import com.intellij.openapi.application.ex.PathManagerEx;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.JavaPsiFacadeEx;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.testFramework.PsiTestCase;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
/**
* @author dsl
*/
public class ShortenClassReferencesTest extends PsiTestCase {
public class ShortenClassReferencesTest extends LightCodeInsightFixtureTestCase {
private static final String BASE_PATH = PathManagerEx.getTestDataPath() + "/psi/shortenClassRefs";
@Override
@@ -20,56 +36,57 @@ public class ShortenClassReferencesTest extends PsiTestCase {
return BASE_PATH;
}
public void testSCR22368() throws Exception { doTest(); }
public void testSCR37254() throws Exception { doTest(); }
public void testSCR22368_1() throws Exception {
final PsiElementFactory factory = myJavaFacade.getElementFactory();
final PsiClass aClass = factory.createClass("X");
final PsiMethod methodFromText = factory.createMethodFromText(
"void method() {\n" +
" IntelliJIDEARulezz<\n" +
"}", null);
final PsiMethod method = (PsiMethod)aClass.add(methodFromText);
final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement) method.getBody().getStatements()[0];
final PsiJavaCodeReferenceElement referenceElement = (PsiJavaCodeReferenceElement) declarationStatement.getFirstChild().getFirstChild();
final PsiClass javaUtilListClass = myJavaFacade.findClass(CommonClassNames.JAVA_UTIL_LIST, GlobalSearchScope.allScope(myPsiManager.getProject()));
public void testSCR22368() { doTest(); }
public void testSCR22368_1() {
JavaPsiFacadeEx facade = JavaPsiFacadeEx.getInstanceEx(getProject());
PsiElementFactory factory = facade.getElementFactory();
PsiClass aClass = factory.createClass("X");
PsiMethod methodFromText = factory.createMethodFromText("void method() {\n" +
" IntelliJIDEARulezz<\n" +
"}", null);
PsiMethod method = (PsiMethod)aClass.add(methodFromText);
PsiCodeBlock body = method.getBody();
assertNotNull(body);
PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement)body.getStatements()[0];
PsiJavaCodeReferenceElement referenceElement = (PsiJavaCodeReferenceElement)declarationStatement.getFirstChild().getFirstChild();
PsiClass javaUtilListClass = facade.findClass(CommonClassNames.JAVA_UTIL_LIST);
assertNotNull(javaUtilListClass);
final PsiElement resultingElement = referenceElement.bindToElement(javaUtilListClass);
PsiElement resultingElement = referenceElement.bindToElement(javaUtilListClass);
assertEquals("List<", resultingElement.getText());
assertEquals("void method() {\n" +
" List<\n" +
"}", method.getText());
}
private void doTest() throws Exception {
String fileName = getTestName(false) + ".java";
String text = loadFile(fileName);
final PsiFile file = createFile(fileName, text);
CommandProcessor.getInstance().executeCommand(
getProject(), new Runnable() {
public void testSCR37254() { doTest(); }
public void testTypeAnnotatedRef() {
doTest();
for (PsiParameter parameter : PsiTreeUtil.findChildrenOfType(myFixture.getFile(), PsiParameter.class)) {
PsiTypeElement typeElement = parameter.getTypeElement();
assertNotNull(typeElement);
PsiJavaCodeReferenceElement ref = typeElement.getInnermostComponentReferenceElement();
assertNotNull(ref);
PsiAnnotation annotation = PsiTreeUtil.getChildOfType(ref, PsiAnnotation.class);
assertNull(annotation);
}
}
private void doTest() {
myFixture.configureByFile(getTestName(false) + ".java");
CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() {
@Override
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
try {
JavaCodeStyleManager.getInstance(myProject).shortenClassReferences(file);
String textAfter = loadFile(getTestName(false) + "_after.java");
PostprocessReformattingAspect.getInstance(getProject()).doPostponedFormatting();
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
String fileText = file.getText();
assertEquals(textAfter, fileText);
}
catch (Exception e) {
LOG.error(e);
}
JavaCodeStyleManager.getInstance(getProject()).shortenClassReferences(myFixture.getFile());
PostprocessReformattingAspect.getInstance(getProject()).doPostponedFormatting();
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
}
});
}
}, "", "");
myFixture.checkResultByFile(getTestName(false) + "_after.java");
}
}