import com.intellij.util.ReflectionCache;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Stack;
+import gnu.trove.THashMap;
import gnu.trove.THashSet;
import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
-import java.lang.reflect.Array;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
+import java.lang.reflect.*;
import java.util.*;
/**
}
}
- public static ElementPattern<PsiElement> compileElementPattern(final String text, final String supportId) {
+ public static ElementPattern<PsiElement> compileElementPattern(final String text, final String supportId) {
+ final Set<Method> staticMethods = getStaticMethods(supportId);
+ return createElementPatternNoGroovy(text, new Function<Frame, Object>() {
+ public Object fun(final Frame frame) {
+ try {
+ return invokeMethod(frame.target, frame.methodName, frame.params.toArray(), staticMethods);
+ }
+ catch (Throwable throwable) {
+ throw new IllegalArgumentException(text, throwable);
+ }
+ }
+ });
+ }
+
+ private static Set<Method> getStaticMethods(String supportId) {
final Class[] patternClasses = getPatternClasses(supportId);
- final Set<Method> staticMethods = new THashSet<Method>(ContainerUtil.concat(patternClasses, new Function<Class, Collection<? extends Method>>() {
+ return new THashSet<Method>(ContainerUtil.concat(patternClasses, new Function<Class, Collection<? extends Method>>() {
public Collection<Method> fun(final Class aClass) {
return ContainerUtil.findAll(ReflectionCache.getMethods(aClass), new Condition<Method>() {
public boolean value(final Method method) {
});
}
}));
- return createElementPatternNoGroovy(text, new Function<Frame, Object>() {
- public Object fun(final Frame frame) {
- try {
- return invokeMethod(frame.target, frame.methodName, frame.params.toArray(), staticMethods);
- }
- catch (Throwable throwable) {
- throw new IllegalArgumentException(text, throwable);
- }
- }
- });
}
private static enum State {
}, ", ")+")");
}
+
+ public static String dumpContextDeclarations(String injectorId) {
+ final Set<Method> methods = getStaticMethods(injectorId);
+ final StringBuilder sb = new StringBuilder();
+ final THashMap<Class, Collection<Class>> classes = new THashMap<Class, Collection<Class>>();
+ final THashSet<Class> missingClasses = new THashSet<Class>();
+ classes.put(Object.class, missingClasses);
+ for (Method method : methods) {
+ for (Class<?> type = method.getReturnType(); type != null && ElementPattern.class.isAssignableFrom(type); type = type.getSuperclass()) {
+ final Class<?> enclosingClass = type.getEnclosingClass();
+ if (enclosingClass != null) {
+ Collection<Class> list = classes.get(enclosingClass);
+ if (list == null) {
+ list = new THashSet<Class>();
+ classes.put(enclosingClass, list);
+ }
+ list.add(type);
+ }
+ else if (!classes.containsKey(type)) {
+ classes.put(type, null);
+ }
+ }
+ }
+ for (Class aClass : classes.keySet()) {
+ if (aClass == Object.class) continue;
+ printClass(aClass, classes, sb);
+ }
+ for (Method method : methods) {
+ printMethodDeclaration(method, sb, classes);
+ }
+ for (Class aClass : missingClasses) {
+ sb.append("class ").append(aClass.getSimpleName());
+ final Class superclass = aClass.getSuperclass();
+ if (missingClasses.contains(superclass)) {
+ sb.append(" extends ").append(superclass.getSimpleName());
+ }
+ sb.append("{}\n");
+ }
+ //System.out.println(sb);
+ return sb.toString();
+ }
+
+ private static void printClass(Class aClass, Map<Class, Collection<Class>> classes, StringBuilder sb) {
+ final boolean isInterface = aClass.isInterface();
+ sb.append(isInterface ? "interface ": "class ");
+ dumpType(aClass, aClass, sb, classes);
+ final Type superClass = aClass.getGenericSuperclass();
+ final Class rawSuperClass = (Class)(superClass instanceof ParameterizedType ? ((ParameterizedType)superClass).getRawType() : superClass);
+ if (superClass != null && classes.containsKey(rawSuperClass)) {
+ sb.append(" extends ");
+ dumpType(null, superClass, sb, classes);
+ }
+ int implementsIdx = 1;
+ for (Type superInterface : aClass.getGenericInterfaces()) {
+ final Class rawSuperInterface = (Class)(superInterface instanceof ParameterizedType ? ((ParameterizedType)superInterface).getRawType() : superClass);
+ if (classes.containsKey(rawSuperInterface)) {
+ if (implementsIdx++ == 1) sb.append(isInterface? " extends " : " implements ");
+ else sb.append(", ");
+ dumpType(null, superInterface, sb, classes);
+ }
+ }
+ sb.append(" {\n");
+ for (Method method : aClass.getDeclaredMethods()) {
+ if (Modifier.isStatic(method.getModifiers()) ||
+ !Modifier.isPublic(method.getModifiers()) ||
+ Modifier.isVolatile(method.getModifiers())) continue;
+ printMethodDeclaration(method, sb.append(" "), classes);
+ }
+ final Collection<Class> innerClasses = classes.get(aClass);
+ sb.append("}\n");
+ if (innerClasses != null) {
+ for (Class innerClass : innerClasses) {
+ printClass(innerClass, classes, sb);
+ }
+ }
+ }
+
+ private static void dumpType(GenericDeclaration owner, Type type, StringBuilder sb, Map<Class, Collection<Class>> classes) {
+ if (type instanceof Class) {
+ final Class aClass = (Class)type;
+ final Class enclosingClass = aClass.getEnclosingClass();
+ if (enclosingClass != null) {
+ sb.append(enclosingClass.getSimpleName()).append("_");
+ }
+ else if (!aClass.isArray() && !aClass.isPrimitive() && !aClass.getName().startsWith("java.") && !classes.containsKey(aClass)) {
+ classes.get(Object.class).add(aClass);
+ }
+ sb.append(aClass.getSimpleName());
+ if (owner == aClass) {
+ dumpTypeParametersArray(owner, aClass.getTypeParameters(), sb, "<", ">", classes);
+ }
+ }
+ else if (type instanceof TypeVariable) {
+ TypeVariable typeVariable = (TypeVariable)type;
+ sb.append(typeVariable.getName());
+ if (typeVariable.getGenericDeclaration() == owner) {
+ dumpTypeParametersArray(null, typeVariable.getBounds(), sb, " extends ", "", classes);
+ }
+ }
+ else if (type instanceof WildcardType) {
+ final WildcardType wildcardType = (WildcardType)type;
+ sb.append("?");
+ dumpTypeParametersArray(owner, wildcardType.getUpperBounds(), sb, " extends ", "", classes);
+ dumpTypeParametersArray(owner, wildcardType.getLowerBounds(), sb, " super ", "", classes);
+ }
+ else if (type instanceof ParameterizedType) {
+ final ParameterizedType parameterizedType = (ParameterizedType)type;
+ final Type raw = parameterizedType.getRawType();
+ dumpType(null, raw, sb, classes);
+ dumpTypeParametersArray(owner, parameterizedType.getActualTypeArguments(), sb, "<", ">", classes);
+ }
+ else if (type instanceof GenericArrayType) {
+ dumpType(owner, ((GenericArrayType)type).getGenericComponentType(), sb, classes);
+ sb.append("[]");
+ }
+ }
+
+ private static void dumpTypeParametersArray(GenericDeclaration owner, final Type[] typeVariables,
+ final StringBuilder sb,
+ final String prefix, final String suffix, Map<Class, Collection<Class>> classes) {
+ int typeVarIdx = 1;
+ for (Type typeVariable : typeVariables) {
+ if (typeVariable == Object.class) continue;
+ if (typeVarIdx++ == 1) sb.append(prefix);
+ else sb.append(", ");
+ dumpType(owner, typeVariable, sb, classes);
+ }
+ if (typeVarIdx > 1) sb.append(suffix);
+ }
+
+ private static void printMethodDeclaration(Method method, StringBuilder sb, Map<Class, Collection<Class>> classes) {
+ if (Modifier.isStatic(method.getModifiers())) {
+ sb.append("static ");
+ }
+ dumpTypeParametersArray(method, method.getTypeParameters(), sb, "<", "> ", classes);
+ dumpType(null, method.getGenericReturnType(), sb, classes);
+ sb.append(" ").append(method.getName()).append("(");
+ int paramIdx = 1;
+ for (Type parameter : method.getGenericParameterTypes()) {
+ if (paramIdx != 1) sb.append(", ");
+ dumpType(null, parameter, sb, classes);
+ sb.append(" ").append("p").append(paramIdx++);
+ }
+ sb.append(")");
+ if (!method.getDeclaringClass().isInterface()) sb.append("{}");
+ sb.append("\n");
+ }
+
}
*/
package org.intellij.plugins.intelliLang.inject.config.ui;
-import com.intellij.openapi.editor.colors.EditorColorsManager;
-import com.intellij.openapi.editor.colors.EditorFontType;
+import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.fileTypes.UnknownFileType;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiFileFactory;
import com.intellij.ui.EditorTextField;
-import com.intellij.ui.ScrollPaneFactory;
import org.intellij.plugins.intelliLang.PatternBasedInjectionHelper;
import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
import org.intellij.plugins.intelliLang.inject.config.InjectionPlace;
AdvancedPanel myAdvancedPanel;
private JPanel myRoot;
+ private JTextField myNameTextField;
public BaseInjectionPanel(BaseInjection injection, Project project) {
super(injection, project);
$$$setupUI$$$(); // see IDEA-9987
final FileType groovy = FileTypeManager.getInstance().getFileTypeByExtension("groovy");
- myTextArea = new EditorTextField("", project, groovy == UnknownFileType.INSTANCE? FileTypes.PLAIN_TEXT : groovy) {
+ final FileType realFileType = groovy == UnknownFileType.INSTANCE ? FileTypes.PLAIN_TEXT : groovy;
+ final PsiFile psiFile = PsiFileFactory.getInstance(project).createFileFromText("injection." + realFileType.getDefaultExtension(), realFileType, "", 0, true);
+ final Document document = PsiDocumentManager.getInstance(project).getDocument(psiFile);
+ psiFile.putUserData(BaseInjection.INJECTION_KEY, injection);
+ myTextArea = new EditorTextField(document, project, realFileType) {
@Override
protected EditorEx createEditor() {
final EditorEx ex = super.createEditor();
ex.setOneLineMode(false);
+ ex.setVerticalScrollbarVisible(true);
+ ex.setHorizontalScrollbarVisible(true);
return ex;
}
};
- myCenterPanel.add(ScrollPaneFactory.createScrollPane(myTextArea), BorderLayout.CENTER);
+ myCenterPanel.add(myTextArea, BorderLayout.CENTER);
myTextArea.setFontInheritedFromLAF(false);
//myTextArea.setFont(EditorColorsManager.getInstance().getGlobalScheme().getFont(EditorFontType.PLAIN));
init(injection.copy());
}
protected void apply(BaseInjection other) {
+ final String displayName = myNameTextField.getText();
+ if (StringUtil.isEmpty(displayName)) {
+ throw new IllegalArgumentException("Display name should not be empty");
+ }
+ other.setDisplayName(displayName);
boolean enabled = true;
final StringBuilder sb = new StringBuilder();
final ArrayList<InjectionPlace> places = new ArrayList<InjectionPlace>();
sb.append(place.isEnabled()?"+ ":"- ").append(place.getText()).append("\n");
}
myTextArea.setText(sb.toString());
+ myNameTextField.setText(myOrigInjection.getDisplayName());
}
public JPanel getComponent() {
--- /dev/null
+/*
+ * 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 org.intellij.plugins.intelliLang.inject.groovy;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.AtomicNotNullLazyValue;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.UserDataHolderEx;
+import com.intellij.psi.*;
+import com.intellij.psi.scope.PsiScopeProcessor;
+import org.intellij.plugins.intelliLang.PatternBasedInjectionHelper;
+import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.GroovyFileType;
+import org.jetbrains.plugins.groovy.lang.resolve.NonCodeMembersProcessor;
+
+/**
+ * @author Gregory.Shrago
+ */
+public class PatternEditorContextMembersProvider implements NonCodeMembersProcessor {
+
+ public static final Key<AtomicNotNullLazyValue<PsiFile>> INJECTION_PARSED_CONTEXT = Key.create("INJECTION_PARSED_CONTEXT");
+
+ public boolean processNonCodeMembers(PsiType type, PsiScopeProcessor processor, PsiElement place, boolean forCompletion) {
+ final PsiFile file = place.getContainingFile().getOriginalFile();
+ final BaseInjection injection = file.getUserData(BaseInjection.INJECTION_KEY);
+ if (injection == null) return true;
+ return ((UserDataHolderEx)file).putUserDataIfAbsent(INJECTION_PARSED_CONTEXT, new AtomicNotNullLazyValue<PsiFile>() {
+ @NotNull
+ @Override
+ protected PsiFile compute() {
+ return parseInjectionContext(injection, file.getProject());
+ }
+ }).getValue().processDeclarations(processor, ResolveState.initial(), null, place);
+ }
+
+ private static PsiFile parseInjectionContext(@NotNull BaseInjection injection, Project project) {
+ final String text = PatternBasedInjectionHelper.dumpContextDeclarations(injection.getSupportId());
+ return PsiFileFactory.getInstance(project).createFileFromText("context.groovy", GroovyFileType.GROOVY_FILE_TYPE, text);
+ }
+}