debugging anonymous and inner classes in script

This commit is contained in:
Maxim.Medvedev
2011-11-23 10:57:54 +04:00
parent 8f8e4c4abe
commit 8f64d212c0
7 changed files with 108 additions and 17 deletions
@@ -426,14 +426,4 @@ public class JVMNameUtil {
}
return "";
}
public static PsiClass getTopLevelParentClass(PsiClass psiClass) {
PsiClass enclosing = PsiTreeUtil.getParentOfType(psiClass, PsiClass.class, true);
while (enclosing != null) {
psiClass = enclosing;
enclosing = PsiTreeUtil.getParentOfType(enclosing, PsiClass.class, true);
}
return psiClass;
}
}
@@ -85,7 +85,7 @@ public class PositionManagerImpl implements PositionManager {
}
if (PsiUtil.isLocalOrAnonymousClass(psiClass)) {
PsiClass parent = JVMNameUtil.getTopLevelParentClass(psiClass);
PsiClass parent = TopLevelParentClassProvider.getTopLevelParentClass(psiClass);
if (parent == null) {
return;
@@ -244,7 +244,7 @@ public class PositionManagerImpl implements PositionManager {
}
if(PsiUtil.isLocalOrAnonymousClass(psiClass)) {
final PsiClass parentNonLocal = JVMNameUtil.getTopLevelParentClass(psiClass);
final PsiClass parentNonLocal = TopLevelParentClassProvider.getTopLevelParentClass(psiClass);
if(parentNonLocal == null) {
LOG.error("Local or anonymous class has no non-local parent");
return null;
@@ -0,0 +1,47 @@
/*
* 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.debugger.engine;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.psi.PsiClass;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.Nullable;
/**
* @author Max Medvedev
*/
public abstract class TopLevelParentClassProvider {
private static final ExtensionPointName<TopLevelParentClassProvider> EP_NAME =
ExtensionPointName.create("com.intellij.topLevelClassProvider");
public static PsiClass getTopLevelParentClass(PsiClass psiClass) {
for (TopLevelParentClassProvider provider : EP_NAME.getExtensions()) {
final PsiClass custom = provider.getCustomTopLevelParentClass(psiClass);
if (custom != null) return custom;
}
PsiClass enclosing = PsiTreeUtil.getParentOfType(psiClass, PsiClass.class, true);
while (enclosing != null) {
psiClass = enclosing;
enclosing = PsiTreeUtil.getParentOfType(enclosing, PsiClass.class, true);
}
return psiClass;
}
@Nullable
protected abstract PsiClass getCustomTopLevelParentClass(PsiClass psiClass);
}
+2
View File
@@ -252,6 +252,8 @@
<weigher key="proximity" implementationClass="org.jetbrains.plugins.groovy.lang.completion.weighers.GrReferenceListWeigher"
id="groovyReferenceListWeigher" order="before openedInEditor" />
<topLevelClassProvider implementation="org.jetbrains.plugins.groovy.debugger.GroovyTopLevelParentClassProvider"/>
<debuggerClassFilterProvider implementation="org.jetbrains.plugins.groovy.debugger.filters.GroovyDebuggerClassFilterProvider"/>
<useScopeEnlarger implementation="org.jetbrains.plugins.groovy.lang.psi.impl.search.GrPrivateFieldScopeEnlarger"/>
@@ -94,8 +94,8 @@ public class GroovyCodeFragmentFactory implements CodeFragmentFactory {
javaText.append("groovy.lang.MetaClass |mc;\n");
javaText.append("java.lang.Class |clazz;\n");
if (!isStatic) {
javaText.append("|clazz = ((java.lang.Object)this).getClass();\n");
javaText.append("|mc = ((groovy.lang.GroovyObject)this).getMetaClass();\n");
javaText.append("|clazz = this.getClass();\n");
javaText.append("|mc = this.getMetaClass();\n");
} else {
assert contextClass != null;
javaText.append("|clazz = java.lang.Class.forName(\"").append(contextClass.getQualifiedName()).append("\");\n");
@@ -118,16 +118,16 @@ public class GroovyCodeFragmentFactory implements CodeFragmentFactory {
javaText.append("groovy.lang.ExpandoMetaClass |emc = new groovy.lang.ExpandoMetaClass(|clazz);\n");
if (!isStatic) {
javaText.append("|emc.setProperty(\"").append(EVAL_NAME).append("\", |closure);\n");
javaText.append("((groovy.lang.GroovyObject)this).setMetaClass(|emc);\n");
javaText.append("this.setMetaClass(|emc);\n");
} else {
javaText.append("((groovy.lang.GroovyObject)|emc.getProperty(\"static\")).setProperty(\"").append(EVAL_NAME).append("\", |closure);\n");
javaText.append("|emc.getProperty(\"static\").setProperty(\"").append(EVAL_NAME).append("\", |closure);\n");
javaText.append("groovy.lang.GroovySystem.getMetaClassRegistry().setMetaClass(|clazz, |emc);\n");
}
javaText.append("|emc.initialize();\n");
javaText.append(unwrapVals(values));
if (!isStatic) {
javaText.append("java.lang.Object |res = ((groovy.lang.MetaClassImpl)|emc).invokeMethod(this, \"").append(EVAL_NAME).append("\", |resVals);\n");
javaText.append("((groovy.lang.GroovyObject)this).setMetaClass(|mc);"); //try/finally is not supported
javaText.append("this.setMetaClass(|mc);"); //try/finally is not supported
} else {
javaText.append("java.lang.Object |res = ((groovy.lang.MetaClassImpl)|emc).invokeStaticMethod(|clazz, \"").append(EVAL_NAME).append("\", |resVals);\n");
javaText.append("groovy.lang.GroovySystem.getMetaClassRegistry().setMetaClass(|clazz, |mc);\n");
@@ -0,0 +1,51 @@
/*
* 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.debugger;
import com.intellij.debugger.engine.TopLevelParentClassProvider;
import com.intellij.psi.PsiAnonymousClass;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
/**
* @author Max Medvedev
*/
public class GroovyTopLevelParentClassProvider extends TopLevelParentClassProvider {
@Nullable
@Override
protected PsiClass getCustomTopLevelParentClass(PsiClass psiClass) {
if (!(psiClass instanceof GrTypeDefinition)) return null;
PsiClass enclosing = PsiTreeUtil.getParentOfType(psiClass, PsiClass.class, true);
while (enclosing != null) {
psiClass = enclosing;
enclosing = PsiTreeUtil.getParentOfType(enclosing, PsiClass.class, true);
}
if (psiClass instanceof PsiAnonymousClass) {
final PsiFile file = psiClass.getContainingFile();
if (file instanceof GroovyFile) {
return ((GroovyFile)file).getScriptClass();
}
}
return psiClass;
}
}
+1
View File
@@ -121,6 +121,7 @@
<extensionPoint name="javaMainMethodProvider" interface="com.intellij.codeInsight.runner.JavaMainMethodProvider"/>
<extensionPoint name="debuggerClassFilterProvider" interface="com.intellij.ui.classFilter.DebuggerClassFilterProvider"/>
<extensionPoint name="topLevelClassProvider" interface="com.intellij.debugger.engine.TopLevelParentClassProvider"/>
<extensionPoint name="debuggerEditorTextProvider" beanClass="com.intellij.lang.LanguageExtensionPoint" />