diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaTreeCopyHandler.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaTreeCopyHandler.java index e47717516b80..ad008bb519d6 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaTreeCopyHandler.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaTreeCopyHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -35,24 +35,28 @@ import java.util.Map; public class JavaTreeCopyHandler implements TreeCopyHandler { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.JavaTreeCopyHandler"); + private static final Key ALREADY_ESCAPED = new Key<>("ALREADY_ESCAPED"); + private static final Key ESCAPEMENT_ENGAGED = new Key<>("ESCAPEMENT_ENGAGED"); + private static final Key INTERFACE_MODIFIERS_FLAG_KEY = Key.create("INTERFACE_MODIFIERS_FLAG_KEY"); + @Override - public TreeElement decodeInformation(TreeElement element, final Map decodingState) { + public TreeElement decodeInformation(TreeElement element, Map decodingState) { boolean shallDecodeEscapedTexts = shallEncodeEscapedTexts(element, decodingState); if (element instanceof CompositeElement) { - final IElementType elementType = element.getElementType(); + IElementType elementType = element.getElementType(); if (elementType == JavaElementType.JAVA_CODE_REFERENCE || elementType == JavaElementType.REFERENCE_EXPRESSION || elementType == JavaElementType.METHOD_REF_EXPRESSION) { - PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement)SourceTreeToPsiMap.treeElementToPsi(element); - final PsiClass refClass = element.getCopyableUserData(JavaTreeGenerator.REFERENCED_CLASS_KEY); + PsiJavaCodeReferenceElement ref = SourceTreeToPsiMap.treeToPsiNotNull(element); + PsiClass refClass = element.getCopyableUserData(JavaTreeGenerator.REFERENCED_CLASS_KEY); if (refClass != null) { element.putCopyableUserData(JavaTreeGenerator.REFERENCED_CLASS_KEY, null); PsiManager manager = refClass.getManager(); JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(refClass.getProject()); - PsiElement refElement1 = ref.resolve(); + PsiElement refElement = ref.resolve(); try { - if (refClass != refElement1 && !manager.areElementsEquivalent(refClass, refElement1)) { + if (refClass != refElement && !manager.areElementsEquivalent(refClass, refElement)) { if (((CompositeElement)element).findChildByRole(ChildRole.QUALIFIER) == null) { // can restore only if short (otherwise qualifier should be already restored) ref = (PsiJavaCodeReferenceElement)ref.bindToElement(refClass); @@ -65,23 +69,26 @@ public class JavaTreeCopyHandler implements TreeCopyHandler { return (TreeElement)SourceTreeToPsiMap.psiElementToTree(ref); } catch (IncorrectOperationException e) { - ((PsiImportHolder) ref.getContainingFile()).importClass(refClass); + ((PsiImportHolder)ref.getContainingFile()).importClass(refClass); } } else { - final PsiMember refMember = element.getCopyableUserData(JavaTreeGenerator.REFERENCED_MEMBER_KEY); + PsiMember refMember = element.getCopyableUserData(JavaTreeGenerator.REFERENCED_MEMBER_KEY); if (refMember != null) { LOG.assertTrue(ref instanceof PsiReferenceExpression); element.putCopyableUserData(JavaTreeGenerator.REFERENCED_MEMBER_KEY, null); - PsiElement refElement1 = ref.resolve(); - if (refMember != refElement1 && !refMember.getManager().areElementsEquivalent(refMember, refElement1)) { - try { - ref = (PsiJavaCodeReferenceElement) ((PsiReferenceExpression)ref).bindToElementViaStaticImport(refMember.getContainingClass()); + PsiElement refElement = ref.resolve(); + if (refMember != refElement && !refMember.getManager().areElementsEquivalent(refMember, refElement)) { + PsiClass containingClass = refMember.getContainingClass(); + if (containingClass != null) { + try { + ref = (PsiJavaCodeReferenceElement)((PsiReferenceExpression)ref).bindToElementViaStaticImport(containingClass); + } + catch (IncorrectOperationException e) { + // TODO[yole] ignore? + } } - catch (IncorrectOperationException e) { - // TODO[yole] ignore? - } - return (TreeElement)SourceTreeToPsiMap.psiElementToTree(ref); + return SourceTreeToPsiMap.psiToTreeNotNull(ref); } } } @@ -90,7 +97,7 @@ public class JavaTreeCopyHandler implements TreeCopyHandler { if (element.getUserData(INTERFACE_MODIFIERS_FLAG_KEY) != null) { element.putUserData(INTERFACE_MODIFIERS_FLAG_KEY, null); try { - PsiModifierList modifierList = (PsiModifierList)SourceTreeToPsiMap.treeElementToPsi(element); + PsiModifierList modifierList = SourceTreeToPsiMap.treeToPsiNotNull(element); if (element.getTreeParent().getElementType() == JavaElementType.FIELD) { modifierList.setModifierProperty(PsiModifier.PUBLIC, true); modifierList.setModifierProperty(PsiModifier.STATIC, true); @@ -110,8 +117,8 @@ public class JavaTreeCopyHandler implements TreeCopyHandler { } else if (shallDecodeEscapedTexts && element instanceof LeafElement && !(element instanceof OuterLanguageElement)) { if (!isInCData(element)) { - final String original = element.getText(); - final String escaped = StringUtil.escapeXml(original); + String original = element.getText(); + String escaped = StringUtil.escapeXml(original); if (!Comparing.equal(original, escaped) && element.getCopyableUserData(ALREADY_ESCAPED) == null) { LeafElement copy = ((LeafElement)element).replaceWithText(escaped); copy.putCopyableUserData(ALREADY_ESCAPED, Boolean.TRUE); @@ -123,48 +130,54 @@ public class JavaTreeCopyHandler implements TreeCopyHandler { return null; } - private static final Key ALREADY_ESCAPED = new Key<>("ALREADY_ESCAPED"); - private static final Key ESCAPEMENT_ENGAGED = new Key<>("ESCAPEMENT_ENGAGED"); private static boolean conversionMayApply(ASTNode element) { PsiElement psi = element.getPsi(); if (psi == null || !psi.isValid()) return false; - final PsiFile file = psi.getContainingFile(); - final Language baseLanguage = file.getViewProvider().getBaseLanguage(); + PsiFile file = psi.getContainingFile(); + Language baseLanguage = file.getViewProvider().getBaseLanguage(); return baseLanguage == StdLanguages.JSPX && file.getLanguage() != baseLanguage; } - @Override - public void encodeInformation(final TreeElement element, final ASTNode original, final Map encodingState) { + public void encodeInformation(TreeElement element, ASTNode original, Map encodingState) { boolean shallEncodeEscapedTexts = shallEncodeEscapedTexts(original, encodingState); if (original instanceof CompositeElement) { - if (original.getElementType() == JavaElementType.JAVA_CODE_REFERENCE || original.getElementType() == JavaElementType.REFERENCE_EXPRESSION) { + IElementType originalType = original.getElementType(); + if (originalType == JavaElementType.JAVA_CODE_REFERENCE || originalType == JavaElementType.REFERENCE_EXPRESSION) { encodeInformationInRef(element, original); } - else if (original.getElementType() == JavaElementType.MODIFIER_LIST - && (original.getTreeParent().getElementType() == JavaElementType.FIELD || original.getTreeParent().getElementType() == JavaElementType.METHOD || original.getTreeParent().getElementType() == JavaElementType.ANNOTATION_METHOD) - && original.getTreeParent().getTreeParent().getElementType() == JavaElementType.CLASS - && (((PsiClass)SourceTreeToPsiMap.treeElementToPsi(original.getTreeParent().getTreeParent())).isInterface() - || ((PsiClass)SourceTreeToPsiMap.treeElementToPsi(original.getTreeParent().getTreeParent())).isAnnotationType())) { - element.putUserData(INTERFACE_MODIFIERS_FLAG_KEY, Boolean.TRUE); + else if (originalType == JavaElementType.MODIFIER_LIST) { + ASTNode parent = original.getTreeParent(); + IElementType parentType = parent.getElementType(); + if (parentType == JavaElementType.FIELD || + parentType == JavaElementType.METHOD || + parentType == JavaElementType.ANNOTATION_METHOD) { + ASTNode grand = parent.getTreeParent(); + if (grand.getElementType() == JavaElementType.CLASS && + (SourceTreeToPsiMap.treeToPsiNotNull(grand).isInterface() || + SourceTreeToPsiMap.treeToPsiNotNull(grand).isAnnotationType())) { + element.putUserData(INTERFACE_MODIFIERS_FLAG_KEY, Boolean.TRUE); + } + } } } - else if (shallEncodeEscapedTexts && original instanceof LeafElement && !(original instanceof OuterLanguageElement)) { - if (!isInCData(original)) { - final String originalText = element.getText(); - final String unescapedText = StringUtil.unescapeXml(originalText); - if (!Comparing.equal(originalText, unescapedText)) { - LeafElement replaced = ((LeafElement)element).rawReplaceWithText(unescapedText); - element.putCopyableUserData(ALREADY_ESCAPED, null); - replaced.putCopyableUserData(ALREADY_ESCAPED, null); - } + else if (shallEncodeEscapedTexts && + original instanceof LeafElement && + !(original instanceof OuterLanguageElement) && + !isInCData(original)) { + String originalText = element.getText(); + String unescapedText = StringUtil.unescapeXml(originalText); + if (!Comparing.equal(originalText, unescapedText)) { + LeafElement replaced = ((LeafElement)element).rawReplaceWithText(unescapedText); + element.putCopyableUserData(ALREADY_ESCAPED, null); + replaced.putCopyableUserData(ALREADY_ESCAPED, null); } } } - private static Boolean shallEncodeEscapedTexts(final ASTNode original, final Map encodingState) { + private static Boolean shallEncodeEscapedTexts(ASTNode original, Map encodingState) { Boolean shallEncodeEscapedTexts = (Boolean)encodingState.get(ESCAPEMENT_ENGAGED); if (shallEncodeEscapedTexts == null) { shallEncodeEscapedTexts = conversionMayApply(original); @@ -177,7 +190,7 @@ public class JavaTreeCopyHandler implements TreeCopyHandler { ASTNode leaf = element; while (leaf != null) { if (leaf instanceof OuterLanguageElement) { - return leaf.getText().indexOf("= 0; + return leaf.getText().contains("treeToPsiNotNull(original).resolve(); - if (target instanceof PsiClass) { - ref.putCopyableUserData(JavaTreeGenerator.REFERENCED_CLASS_KEY, (PsiClass)target); - } - break; + else if (originalType == JavaElementType.JAVA_CODE_REFERENCE) { + int kind = ((PsiJavaCodeReferenceElementImpl)original).getKind(((PsiJavaCodeReferenceElementImpl)original).getContainingFile()); + switch (kind) { + case PsiJavaCodeReferenceElementImpl.CLASS_NAME_KIND: + case PsiJavaCodeReferenceElementImpl.CLASS_OR_PACKAGE_NAME_KIND: + case PsiJavaCodeReferenceElementImpl.CLASS_IN_QUALIFIED_NEW_KIND: + PsiElement target = SourceTreeToPsiMap.treeToPsiNotNull(original).resolve(); + if (target instanceof PsiClass) { + ref.putCopyableUserData(JavaTreeGenerator.REFERENCED_CLASS_KEY, (PsiClass)target); + } + break; - case PsiJavaCodeReferenceElementImpl.PACKAGE_NAME_KIND: - case PsiJavaCodeReferenceElementImpl.CLASS_FQ_NAME_KIND: - case PsiJavaCodeReferenceElementImpl.CLASS_FQ_OR_PACKAGE_NAME_KIND: - break; + case PsiJavaCodeReferenceElementImpl.PACKAGE_NAME_KIND: + case PsiJavaCodeReferenceElementImpl.CLASS_FQ_NAME_KIND: + case PsiJavaCodeReferenceElementImpl.CLASS_FQ_OR_PACKAGE_NAME_KIND: + break; - default: - LOG.assertTrue(false); + default: + LOG.error("Unknown kind: " + kind); } } else { - LOG.error("Wrong element type: " + original.getElementType()); + LOG.error("Wrong element type: " + originalType); } } - - private static final Key INTERFACE_MODIFIERS_FLAG_KEY = Key.create("INTERFACE_MODIFIERS_FLAG_KEY"); -} +} \ No newline at end of file