register TreeGenerator and TreeCopyHandler via extension points

This commit is contained in:
Dmitry Jemerov
2011-10-04 16:03:43 +02:00
parent bf490a0ef8
commit 83636a9f46
10 changed files with 254 additions and 263 deletions
@@ -40,7 +40,6 @@ import com.intellij.psi.impl.source.JavaDummyHolderFactory;
import com.intellij.psi.impl.source.jsp.jspXml.JspDirective;
import com.intellij.psi.impl.source.resolve.FileContextUtil;
import com.intellij.psi.impl.source.resolve.PsiResolveHelperImpl;
import com.intellij.psi.impl.source.tree.JavaChangeUtilSupport;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiModificationTracker;
@@ -120,7 +119,6 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx implements Disposable {
);
JavaChangeUtilSupport.setup();
DummyHolderFactory.setFactory(new JavaDummyHolderFactory());
JavaElementType.ANNOTATION.getIndex(); // Initialize stubs.
Disposer.register(project, this);
@@ -0,0 +1,226 @@
/*
* Copyright 2000-2011 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;
import com.intellij.lang.ASTNode;
import com.intellij.lang.Language;
import com.intellij.lang.StdLanguages;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.source.PsiJavaCodeReferenceElementImpl;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.templateLanguages.OuterLanguageElement;
import com.intellij.util.IncorrectOperationException;
import java.util.Map;
public class JavaTreeCopyHandler implements TreeCopyHandler {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.JavaTreeCopyHandler");
public TreeElement decodeInformation(TreeElement element, final Map<Object, Object> decodingState) {
boolean shallDecodeEscapedTexts = shallEncodeEscapedTexts(element, decodingState);
if (element instanceof CompositeElement) {
if (element.getElementType() == JavaElementType.JAVA_CODE_REFERENCE ||
element.getElementType() == JavaElementType.REFERENCE_EXPRESSION) {
PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement)SourceTreeToPsiMap.treeElementToPsi(element);
final 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();
try {
if (refClass != refElement1 && !manager.areElementsEquivalent(refClass, refElement1)) {
if (((CompositeElement)element).findChildByRole(ChildRole.QUALIFIER) == null) {
// can restore only if short (otherwise qualifier should be already restored)
ref = (PsiJavaCodeReferenceElement)ref.bindToElement(refClass);
}
}
else {
// shorten references to the same package and to inner classes that can be accessed by short name
ref = (PsiJavaCodeReferenceElement)codeStyleManager.shortenClassReferences(ref, JavaCodeStyleManager.DO_NOT_ADD_IMPORTS);
}
return (TreeElement)SourceTreeToPsiMap.psiElementToTree(ref);
}
catch (IncorrectOperationException e) {
((PsiImportHolder) ref.getContainingFile()).importClass(refClass);
}
}
else {
final 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());
}
catch (IncorrectOperationException e) {
// TODO[yole] ignore?
}
return (TreeElement)SourceTreeToPsiMap.psiElementToTree(ref);
}
}
}
}
else if (element.getElementType() == JavaElementType.MODIFIER_LIST) {
if (element.getUserData(INTERFACE_MODIFIERS_FLAG_KEY) != null) {
element.putUserData(INTERFACE_MODIFIERS_FLAG_KEY, null);
try {
PsiModifierList modifierList = (PsiModifierList)SourceTreeToPsiMap.treeElementToPsi(element);
if (element.getTreeParent().getElementType() == JavaElementType.FIELD) {
modifierList.setModifierProperty(PsiModifier.PUBLIC, true);
modifierList.setModifierProperty(PsiModifier.STATIC, true);
modifierList.setModifierProperty(PsiModifier.FINAL, true);
}
else if (element.getTreeParent().getElementType() == JavaElementType.METHOD ||
element.getTreeParent().getElementType() == JavaElementType.ANNOTATION_METHOD) {
modifierList.setModifierProperty(PsiModifier.PUBLIC, true);
modifierList.setModifierProperty(PsiModifier.ABSTRACT, true);
}
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
}
}
else if (shallDecodeEscapedTexts && element instanceof LeafElement && !(element instanceof OuterLanguageElement)) {
if (!isInCData(element)) {
final String original = element.getText();
final 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);
return copy;
}
}
}
return null;
}
private static final Key<Boolean> ALREADY_ESCAPED = new Key<Boolean>("ALREADY_ESCAPED");
private static final Key<Boolean> ESCAPEMENT_ENGAGED = new Key<Boolean>("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();
return baseLanguage == StdLanguages.JSPX && file.getLanguage() != baseLanguage;
}
public void encodeInformation(final TreeElement element, final ASTNode original, final Map<Object, Object> encodingState) {
boolean shallEncodeEscapedTexts = shallEncodeEscapedTexts(original, encodingState);
if (original instanceof CompositeElement) {
if (original.getElementType() == JavaElementType.JAVA_CODE_REFERENCE || original.getElementType() == 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 (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);
}
}
}
}
private static Boolean shallEncodeEscapedTexts(final ASTNode original, final Map<Object, Object> encodingState) {
Boolean shallEncodeEscapedTexts = (Boolean)encodingState.get(ESCAPEMENT_ENGAGED);
if (shallEncodeEscapedTexts == null) {
shallEncodeEscapedTexts = conversionMayApply(original);
encodingState.put(ESCAPEMENT_ENGAGED, shallEncodeEscapedTexts);
}
return shallEncodeEscapedTexts;
}
private static boolean isInCData(ASTNode element) {
ASTNode leaf = element;
while (leaf != null) {
if (leaf instanceof OuterLanguageElement) {
return leaf.getText().indexOf("<![CDATA[") >= 0;
}
leaf = TreeUtil.prevLeaf(leaf);
}
return false;
}
private static void encodeInformationInRef(TreeElement ref, ASTNode original) {
if (original.getElementType() == JavaElementType.REFERENCE_EXPRESSION) {
final PsiJavaCodeReferenceElement javaRefElement = (PsiJavaCodeReferenceElement)SourceTreeToPsiMap.treeElementToPsi(original);
assert javaRefElement != null;
final JavaResolveResult resolveResult = javaRefElement.advancedResolve(false);
final PsiElement target = resolveResult.getElement();
if (target instanceof PsiClass &&
original.getTreeParent().getElementType() == JavaElementType.REFERENCE_EXPRESSION) {
ref.putCopyableUserData(JavaTreeGenerator.REFERENCED_CLASS_KEY, (PsiClass)target);
}
else if ((target instanceof PsiMethod || target instanceof PsiField) &&
((PsiMember) target).hasModifierProperty(PsiModifier.STATIC) &&
resolveResult.getCurrentFileResolveScope() instanceof PsiImportStaticStatement) {
ref.putCopyableUserData(JavaTreeGenerator.REFERENCED_MEMBER_KEY, (PsiMember) target);
}
}
else if (original.getElementType() == JavaElementType.JAVA_CODE_REFERENCE) {
switch (((PsiJavaCodeReferenceElementImpl)original).getKind()) {
case PsiJavaCodeReferenceElementImpl.CLASS_NAME_KIND:
case PsiJavaCodeReferenceElementImpl.CLASS_OR_PACKAGE_NAME_KIND:
case PsiJavaCodeReferenceElementImpl.CLASS_IN_QUALIFIED_NEW_KIND:
final PsiElement target = SourceTreeToPsiMap.<PsiJavaCodeReferenceElement>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;
default:
LOG.assertTrue(false);
}
}
else {
LOG.error("Wrong element type: " + original.getElementType());
}
}
private static final Key<Boolean> INTERFACE_MODIFIERS_FLAG_KEY = Key.create("INTERFACE_MODIFIERS_FLAG_KEY");
}
@@ -16,39 +16,34 @@
package com.intellij.psi.impl.source.tree;
import com.intellij.lang.*;
import com.intellij.lang.ASTFactory;
import com.intellij.lang.ASTNode;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.java.parser.DeclarationParser;
import com.intellij.lang.java.parser.JavaParserUtil;
import com.intellij.lexer.JavaLexer;
import com.intellij.lexer.Lexer;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.GeneratedMarkerVisitor;
import com.intellij.psi.impl.light.LightTypeElement;
import com.intellij.psi.impl.source.*;
import com.intellij.psi.impl.source.codeStyle.CodeEditUtil;
import com.intellij.psi.impl.source.parsing.ParseUtilBase;
import com.intellij.psi.templateLanguages.OuterLanguageElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.CharTable;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
/**
* @author max
*/
public class JavaChangeUtilSupport implements TreeGenerator, TreeCopyHandler {
public class JavaTreeGenerator implements TreeGenerator {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.JavaTreeGenerator");
private static final JavaParserUtil.ParserWrapper MOD_LIST = new JavaParserUtil.ParserWrapper() {
@@ -58,16 +53,6 @@ public class JavaChangeUtilSupport implements TreeGenerator, TreeCopyHandler {
}
};
static {
final JavaChangeUtilSupport instance = new JavaChangeUtilSupport();
ChangeUtil.registerCopyHandler(instance);
ChangeUtil.registerTreeGenerator(instance);
}
public static void setup() {
// Does nothing, initialization is done in class initializer.
}
@Nullable
public TreeElement generateTreeFor(PsiElement original, final CharTable table, final PsiManager manager) {
if (original instanceof PsiKeyword || original instanceof PsiIdentifier) {
@@ -231,194 +216,6 @@ public class JavaChangeUtilSupport implements TreeGenerator, TreeCopyHandler {
return element;
}
public TreeElement decodeInformation(TreeElement element, final Map<Object, Object> decodingState) {
boolean shallDecodeEscapedTexts = shallEncodeEscapedTexts(element, decodingState);
if (element instanceof CompositeElement) {
if (element.getElementType() == JavaElementType.JAVA_CODE_REFERENCE ||
element.getElementType() == JavaElementType.REFERENCE_EXPRESSION) {
PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement)SourceTreeToPsiMap.treeElementToPsi(element);
final PsiClass refClass = element.getCopyableUserData(REFERENCED_CLASS_KEY);
if (refClass != null) {
element.putCopyableUserData(REFERENCED_CLASS_KEY, null);
PsiManager manager = refClass.getManager();
JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(refClass.getProject());
PsiElement refElement1 = ref.resolve();
try {
if (refClass != refElement1 && !manager.areElementsEquivalent(refClass, refElement1)) {
if (((CompositeElement)element).findChildByRole(ChildRole.QUALIFIER) == null) {
// can restore only if short (otherwise qualifier should be already restored)
ref = (PsiJavaCodeReferenceElement)ref.bindToElement(refClass);
}
}
else {
// shorten references to the same package and to inner classes that can be accessed by short name
ref = (PsiJavaCodeReferenceElement)codeStyleManager.shortenClassReferences(ref, JavaCodeStyleManager.DO_NOT_ADD_IMPORTS);
}
return (TreeElement)SourceTreeToPsiMap.psiElementToTree(ref);
}
catch (IncorrectOperationException e) {
((PsiImportHolder) ref.getContainingFile()).importClass(refClass);
}
}
else {
final PsiMember refMember = element.getCopyableUserData(REFERENCED_MEMBER_KEY);
if (refMember != null) {
LOG.assertTrue(ref instanceof PsiReferenceExpression);
element.putCopyableUserData(REFERENCED_MEMBER_KEY, null);
PsiElement refElement1 = ref.resolve();
if (refMember != refElement1 && !refMember.getManager().areElementsEquivalent(refMember, refElement1)) {
try {
ref = (PsiJavaCodeReferenceElement) ((PsiReferenceExpression)ref).bindToElementViaStaticImport(refMember.getContainingClass());
}
catch (IncorrectOperationException e) {
// TODO[yole] ignore?
}
return (TreeElement)SourceTreeToPsiMap.psiElementToTree(ref);
}
}
}
}
else if (element.getElementType() == JavaElementType.MODIFIER_LIST) {
if (element.getUserData(INTERFACE_MODIFIERS_FLAG_KEY) != null) {
element.putUserData(INTERFACE_MODIFIERS_FLAG_KEY, null);
try {
PsiModifierList modifierList = (PsiModifierList)SourceTreeToPsiMap.treeElementToPsi(element);
if (element.getTreeParent().getElementType() == JavaElementType.FIELD) {
modifierList.setModifierProperty(PsiModifier.PUBLIC, true);
modifierList.setModifierProperty(PsiModifier.STATIC, true);
modifierList.setModifierProperty(PsiModifier.FINAL, true);
}
else if (element.getTreeParent().getElementType() == JavaElementType.METHOD ||
element.getTreeParent().getElementType() == JavaElementType.ANNOTATION_METHOD) {
modifierList.setModifierProperty(PsiModifier.PUBLIC, true);
modifierList.setModifierProperty(PsiModifier.ABSTRACT, true);
}
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
}
}
else if (shallDecodeEscapedTexts && element instanceof LeafElement && !(element instanceof OuterLanguageElement)) {
if (!isInCData(element)) {
final String original = element.getText();
final 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);
return copy;
}
}
}
return null;
}
private static final Key<Boolean> ALREADY_ESCAPED = new Key<Boolean>("ALREADY_ESCAPED");
private static final Key<Boolean> ESCAPEMENT_ENGAGED = new Key<Boolean>("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();
return baseLanguage == StdLanguages.JSPX && file.getLanguage() != baseLanguage;
}
public void encodeInformation(final TreeElement element, final ASTNode original, final Map<Object, Object> encodingState) {
boolean shallEncodeEscapedTexts = shallEncodeEscapedTexts(original, encodingState);
if (original instanceof CompositeElement) {
if (original.getElementType() == JavaElementType.JAVA_CODE_REFERENCE || original.getElementType() == 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 (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);
}
}
}
}
private static Boolean shallEncodeEscapedTexts(final ASTNode original, final Map<Object, Object> encodingState) {
Boolean shallEncodeEscapedTexts = (Boolean)encodingState.get(ESCAPEMENT_ENGAGED);
if (shallEncodeEscapedTexts == null) {
shallEncodeEscapedTexts = conversionMayApply(original);
encodingState.put(ESCAPEMENT_ENGAGED, shallEncodeEscapedTexts);
}
return shallEncodeEscapedTexts;
}
private static boolean isInCData(ASTNode element) {
ASTNode leaf = element;
while (leaf != null) {
if (leaf instanceof OuterLanguageElement) {
return leaf.getText().indexOf("<![CDATA[") >= 0;
}
leaf = TreeUtil.prevLeaf(leaf);
}
return false;
}
private static void encodeInformationInRef(TreeElement ref, ASTNode original) {
if (original.getElementType() == JavaElementType.REFERENCE_EXPRESSION) {
final PsiJavaCodeReferenceElement javaRefElement = (PsiJavaCodeReferenceElement)SourceTreeToPsiMap.treeElementToPsi(original);
assert javaRefElement != null;
final JavaResolveResult resolveResult = javaRefElement.advancedResolve(false);
final PsiElement target = resolveResult.getElement();
if (target instanceof PsiClass &&
original.getTreeParent().getElementType() == JavaElementType.REFERENCE_EXPRESSION) {
ref.putCopyableUserData(REFERENCED_CLASS_KEY, (PsiClass)target);
}
else if ((target instanceof PsiMethod || target instanceof PsiField) &&
((PsiMember) target).hasModifierProperty(PsiModifier.STATIC) &&
resolveResult.getCurrentFileResolveScope() instanceof PsiImportStaticStatement) {
ref.putCopyableUserData(REFERENCED_MEMBER_KEY, (PsiMember) target);
}
}
else if (original.getElementType() == JavaElementType.JAVA_CODE_REFERENCE) {
switch (((PsiJavaCodeReferenceElementImpl)original).getKind()) {
case PsiJavaCodeReferenceElementImpl.CLASS_NAME_KIND:
case PsiJavaCodeReferenceElementImpl.CLASS_OR_PACKAGE_NAME_KIND:
case PsiJavaCodeReferenceElementImpl.CLASS_IN_QUALIFIED_NEW_KIND:
final PsiElement target = SourceTreeToPsiMap.<PsiJavaCodeReferenceElement>treeToPsiNotNull(original).resolve();
if (target instanceof PsiClass) {
ref.putCopyableUserData(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;
default:
LOG.assertTrue(false);
}
}
else {
LOG.error("Wrong element type: " + original.getElementType());
}
}
private static void encodeInfoInTypeElement(ASTNode typeElement, PsiType type) {
if (type instanceof PsiPrimitiveType) return;
LOG.assertTrue(typeElement.getElementType() == JavaElementType.TYPE);
@@ -491,7 +288,6 @@ public class JavaChangeUtilSupport implements TreeGenerator, TreeCopyHandler {
}
}
private static final Key<PsiClass> REFERENCED_CLASS_KEY = Key.create("REFERENCED_CLASS_KEY");
private static final Key<PsiMember> REFERENCED_MEMBER_KEY = Key.create("REFERENCED_MEMBER_KEY");
private static final Key<Boolean> INTERFACE_MODIFIERS_FLAG_KEY = Key.create("INTERFACE_MODIFIERS_FLAG_KEY");
static final Key<PsiClass> REFERENCED_CLASS_KEY = Key.create("REFERENCED_CLASS_KEY");
static final Key<PsiMember> REFERENCED_MEMBER_KEY = Key.create("REFERENCED_MEMBER_KEY");
}
@@ -19,6 +19,7 @@ package com.intellij.psi.impl.source.tree;
import com.intellij.lang.ASTFactory;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.pom.PomManager;
import com.intellij.pom.PomModel;
import com.intellij.pom.event.PomModelEvent;
@@ -47,19 +48,9 @@ import java.util.Map;
public class ChangeUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.ChangeUtil");
private static final List<TreeCopyHandler> ourCopyHandlers = ContainerUtil.createEmptyCOWList();
private static final List<TreeGenerator> ourTreeGenerators = ContainerUtil.createEmptyCOWList();
private ChangeUtil() { }
public static void registerCopyHandler(TreeCopyHandler handler) {
ourCopyHandlers.add(handler);
}
public static void registerTreeGenerator(TreeGenerator generator) {
ourTreeGenerators.add(generator);
}
public static void changeElementInPlace(final ASTNode element, final ChangeAction action){
prepareAndRunChangeAction(new ChangeAction() {
public void makeChange(TreeChangeEvent destinationTreeChange) {
@@ -68,11 +59,11 @@ public class ChangeUtil {
ASTNode node = element;
while (node != null) {
ASTNode parent = node.getTreeParent();
((TreeElement) node).clearCaches();
((TreeElement)node).clearCaches();
node = parent;
}
}
}, (TreeElement) element);
}, (TreeElement)element);
}
public static void encodeInformation(TreeElement element) {
@@ -84,7 +75,7 @@ public class ChangeUtil {
}
private static void encodeInformation(TreeElement element, ASTNode original, Map<Object, Object> state) {
for (TreeCopyHandler handler : ourCopyHandlers) {
for (TreeCopyHandler handler : Extensions.getExtensions(TreeCopyHandler.EP_NAME)) {
handler.encodeInformation(element, original, state);
}
@@ -110,7 +101,7 @@ public class ChangeUtil {
child = child.getTreeNext();
}
for (TreeCopyHandler handler : ourCopyHandlers) {
for (TreeCopyHandler handler : Extensions.getExtensions(TreeCopyHandler.EP_NAME)) {
final TreeElement handled = handler.decodeInformation(element, state);
if (handled != null) return handled;
}
@@ -169,7 +160,7 @@ public class ChangeUtil {
return copyElement((TreeElement)SourceTreeToPsiMap.psiElementToTree(original), table);
}
else {
for (TreeGenerator generator : ourTreeGenerators) {
for (TreeGenerator generator : Extensions.getExtensions(TreeGenerator.EP_NAME)) {
final TreeElement element = generator.generateTreeFor(original, table, manager);
if (element != null) return element;
}
@@ -20,10 +20,13 @@
package com.intellij.psi.impl.source.tree;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.extensions.ExtensionPointName;
import java.util.Map;
public interface TreeCopyHandler {
ExtensionPointName<TreeCopyHandler> EP_NAME = ExtensionPointName.create("com.intellij.treeCopyHandler");
void encodeInformation(TreeElement element, ASTNode original, Map<Object, Object> encodingState);
TreeElement decodeInformation(TreeElement element, Map<Object, Object> decodingState);
}
@@ -19,12 +19,15 @@
*/
package com.intellij.psi.impl.source.tree;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiManager;
import com.intellij.util.CharTable;
import org.jetbrains.annotations.Nullable;
public interface TreeGenerator {
ExtensionPointName<TreeGenerator> EP_NAME = ExtensionPointName.create("com.intellij.treeGenerator");
@Nullable
TreeElement generateTreeFor(PsiElement original, CharTable table, final PsiManager manager);
}
@@ -503,4 +503,9 @@
<extensionPoint name="project.converterProvider"
interface="com.intellij.conversion.ConverterProvider"/>
<extensionPoint name="treeCopyHandler"
interface="com.intellij.psi.impl.source.tree.TreeCopyHandler"/>
<extensionPoint name="treeGenerator"
interface="com.intellij.psi.impl.source.tree.TreeGenerator"/>
</extensionPoints>
+2 -3
View File
@@ -365,6 +365,8 @@
<postStartupActivity implementation="org.jetbrains.plugins.groovy.mvc.MvcProjectWithoutLibraryNotificator" />
<treeCopyHandler implementation="org.jetbrains.plugins.groovy.lang.GroovyChangeUtilSupport"/>
<localInspection language="Groovy" shortName="SecondUnsafeCall" bundle="org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle"
key="second.unsafe.call" groupName="Probable bugs" enabledByDefault="true" level="WARNING"
implementationClass="org.jetbrains.plugins.groovy.codeInspection.secondUnsafeCall.SecondUnsafeCallInspection"/>
@@ -1039,9 +1041,6 @@
</actions>
<application-components>
<component>
<implementation-class>org.jetbrains.plugins.groovy.GroovyLoader</implementation-class>
</component>
<component>
<implementation-class>org.jetbrains.plugins.groovy.gant.GantLoader</implementation-class>
</component>
@@ -1,33 +0,0 @@
/*
* Copyright 2000-2011 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 org.jetbrains.plugins.groovy;
import com.intellij.psi.impl.source.tree.ChangeUtil;
import org.jetbrains.plugins.groovy.lang.GroovyChangeUtilSupport;
/**
* Main application component, that loads Groovy language support
*
* @author ilyas
*/
public class GroovyLoader {
public GroovyLoader() {
ChangeUtil.registerCopyHandler(new GroovyChangeUtilSupport());
}
}
+3
View File
@@ -1119,6 +1119,9 @@
<iconLayerProvider implementation="com.intellij.compiler.CompilerIconLayerProvider"/>
<treeCopyHandler implementation="com.intellij.psi.impl.source.tree.JavaTreeCopyHandler"/>
<treeGenerator implementation="com.intellij.psi.impl.source.tree.JavaTreeGenerator"/>
<projectService serviceImplementation="com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable"/>
<projectService serviceInterface="com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemsSettings"
serviceImplementation="com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemsSettingsImpl"/>