mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
groovy dsl for categories and gdk methods
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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 standardDsls
|
||||
|
||||
import com.intellij.util.Function
|
||||
import org.jetbrains.plugins.groovy.gpp.GppGdkMethod
|
||||
|
||||
/**
|
||||
* @author Maxim.Medvedev
|
||||
*/
|
||||
|
||||
def gppCategory(def className, def isStatic = false) {
|
||||
def staticConverter = new Function() {def fun(def m) {new GppGdkMethod(m, true)}};
|
||||
def nonStaticConverter = new Function() {def fun(def m) {new GppGdkMethod(m, false)}};
|
||||
category className, isStatic ? staticConverter : nonStaticConverter
|
||||
}
|
||||
|
||||
gppCategory "groovy.util.Conversions"
|
||||
gppCategory "groovy.util.Files"
|
||||
gppCategory "groovy.util.Filters"
|
||||
gppCategory "groovy.util.Iterations"
|
||||
gppCategory "groovy.util.Mappers"
|
||||
gppCategory "groovy.util.Sort"
|
||||
gppCategory "groovy.util.Strings"
|
||||
gppCategory "groovy.util.With"
|
||||
gppCategory "groovy.util.concurrent.Atomics"
|
||||
gppCategory "org.mbte.groovypp.runtime.ArraysMethods"
|
||||
gppCategory "org.mbte.groovypp.runtime.DefaultGroovyPPMethods"
|
||||
|
||||
gppCategory "org.mbte.groovypp.runtime.DefaultGroovyPPStaticMethods", true
|
||||
@@ -17,44 +17,16 @@
|
||||
|
||||
package standardDsls
|
||||
|
||||
import com.intellij.psi.PsiParameter
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.psi.util.TypeConversionUtil
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrGdkMethodImpl
|
||||
|
||||
/**
|
||||
* @author Maxim.Medvedev
|
||||
*//*
|
||||
*/
|
||||
*/
|
||||
|
||||
def extension(def className, boolean isStatic = false) {
|
||||
contributor(context()) {
|
||||
|
||||
if (!classType) return;
|
||||
|
||||
def categoryClass = findClass(className)
|
||||
if (!categoryClass) return;
|
||||
def myPlace = PsiTreeUtil.getParentOfType(place, GroovyPsiElement, false)
|
||||
if (myPlace == null) return;
|
||||
categoryClass.methods.each {m ->
|
||||
def params = m.parameterList.parameters as List<PsiParameter>
|
||||
if (!params) return;
|
||||
def targetType = params[0].type
|
||||
if (!TypesUtil.isAssignableByMethodCallConversion(TypeConversionUtil.erasure(targetType), classType, myPlace)) return;
|
||||
|
||||
add new GrGdkMethodImpl(m, isStatic)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension "org.codehaus.groovy.runtime.DefaultGroovyMethods"
|
||||
extension "org.codehaus.groovy.runtime.DefaultGroovyStaticMethods", true
|
||||
extension "org.codehaus.groovy.runtime.DateGroovyMethods"
|
||||
extension "org.codehaus.groovy.runtime.EncodingGroovyMethods"
|
||||
extension "org.codehaus.groovy.runtime.SqlGroovyMethods"
|
||||
extension "org.codehaus.groovy.runtime.SwingGroovyMethods"
|
||||
extension "org.codehaus.groovy.runtime.XmlGroovyMethods"
|
||||
category "org.codehaus.groovy.runtime.DefaultGroovyMethods"
|
||||
category "org.codehaus.groovy.runtime.DefaultGroovyStaticMethods", true
|
||||
category "org.codehaus.groovy.runtime.DateGroovyMethods"
|
||||
category "org.codehaus.groovy.runtime.EncodingGroovyMethods"
|
||||
category "org.codehaus.groovy.runtime.SqlGroovyMethods"
|
||||
category "org.codehaus.groovy.runtime.SwingGroovyMethods"
|
||||
category "org.codehaus.groovy.runtime.XmlGroovyMethods"
|
||||
|
||||
|
||||
|
||||
@@ -22,6 +22,9 @@ contributor([gdslScriptContext]) {
|
||||
method name: "contributor", params: [contexts: "java.util.Map", body: {}], type: void
|
||||
method name: "contributor", params: [contexts: "java.lang.Object", body: {}], type: void
|
||||
|
||||
method name: "category", params: [categoryClass: "java.lang.String", isStatic:"java.lang.Boolean", body: {}], type: void
|
||||
method name: "category", params: [categoryClass: "java.lang.String", body: {}], type: void
|
||||
|
||||
method name: "supportsVersion", params: [version: "java.lang.String"], type: boolean
|
||||
|
||||
// scopes
|
||||
@@ -54,8 +57,9 @@ contributor([contributorBody]) {
|
||||
method name: "enclosingClass", type: "com.intellij.psi.PsiClass"
|
||||
|
||||
property name: "place", type: "com.intellij.psi.PsiElement"
|
||||
property name: "classType", type: "com.intellij.psi.PsiType"
|
||||
property name: "classType", type: "com.intellij.psi.PsiClass"
|
||||
property name: "psiClass", type: "com.intellij.psi.PsiClass"
|
||||
property name: "psiType", type: "com.intellij.psi.PsiType"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,6 @@
|
||||
<expectedTypesContributor implementation="org.jetbrains.plugins.groovy.gpp.GppExpectedTypesContributor"/>
|
||||
<variableEnhancer implementation="org.jetbrains.plugins.groovy.gpp.GppClosureParameterTypeProvider"/>
|
||||
<classSubstitutor implementation="org.jetbrains.plugins.groovy.gpp.GppClassSubstitutor"/>
|
||||
<membersContributor implementation="org.jetbrains.plugins.groovy.gpp.GppStdLibSupport"/>
|
||||
<positionManagerDelegate implementation="org.jetbrains.plugins.groovy.gpp.GppPositionManager"/>
|
||||
|
||||
</extensions>
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ public class DynamicMembersContributor extends NonCodeMembersContributor {
|
||||
PsiElement place,
|
||||
ResolveState state) {
|
||||
final DynamicManager manager = DynamicManager.getInstance(place.getProject());
|
||||
for (String qName : ResolveUtil.getAllSuperTypes(qualifierType, place).keySet()) {
|
||||
for (String qName : ResolveUtil.getAllSuperTypes(qualifierType, place.getProject()).keySet()) {
|
||||
for (PsiMethod method : manager.getMethods(qName)) {
|
||||
if (!ResolveUtil.processElement(processor, method, state)) return;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.jetbrains.plugins.groovy.dsl;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import groovy.lang.Closure;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.dsl.holders.CompoundMembersHolder;
|
||||
@@ -21,7 +20,6 @@ import java.util.Set;
|
||||
public class CustomMembersGenerator implements GdslMembersHolderConsumer {
|
||||
private final Set<Map> myMethods = new HashSet<Map>();
|
||||
private final Project myProject;
|
||||
private final String myTypeText;
|
||||
private final CompoundMembersHolder myDepot = new CompoundMembersHolder();
|
||||
private final GroovyClassDescriptor myDescriptor;
|
||||
private final String myQualifiedName;
|
||||
@@ -29,7 +27,6 @@ public class CustomMembersGenerator implements GdslMembersHolderConsumer {
|
||||
public CustomMembersGenerator(GroovyClassDescriptor descriptor) {
|
||||
myDescriptor = descriptor;
|
||||
myProject = descriptor.getProject();
|
||||
myTypeText = descriptor.getTypeText();
|
||||
final PsiType type = descriptor.getPsiType();
|
||||
if (type instanceof PsiClassType) {
|
||||
final PsiClass psiClass = ((PsiClassType)type).resolve();
|
||||
@@ -48,16 +45,12 @@ public class CustomMembersGenerator implements GdslMembersHolderConsumer {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiType getClassType() {
|
||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(myProject);
|
||||
try {
|
||||
return factory.createTypeFromText(myTypeText, getPlace());
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
final PsiClass psiClass = getPsiClass();
|
||||
if (psiClass != null) return factory.createType(psiClass);
|
||||
}
|
||||
return null;
|
||||
public PsiClass getClassType() {
|
||||
return getPsiClass();
|
||||
}
|
||||
|
||||
public PsiType getPsiType() {
|
||||
return myDescriptor.getPsiType();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -30,7 +30,8 @@ public interface GdslMembersHolderConsumer {
|
||||
void addMemberHolder(CustomMembersHolder holder);
|
||||
Project getProject();
|
||||
PsiElement getPlace();
|
||||
PsiType getClassType();
|
||||
PsiClass getClassType();
|
||||
PsiType getPsiType();
|
||||
@Nullable
|
||||
PsiClass getPsiClass();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import com.intellij.openapi.project.Project
|
||||
public class GroovyDslExecutor {
|
||||
static final def cats = PsiEnhancerCategory.EP_NAME.extensions.collect { it.class }
|
||||
final List<Pair<ContextFilter, Closure>> enhancers = []
|
||||
final List<Pair<Closure>> categoryEnhancers = []
|
||||
|
||||
private final String myFileName;
|
||||
static final String ideaVersion
|
||||
@@ -59,10 +58,6 @@ public class GroovyDslExecutor {
|
||||
enhancers << Pair.create(CompositeContextFilter.compose(cts, false), toDo)
|
||||
}
|
||||
|
||||
def addCategoryEnhancer(Closure toDo) {
|
||||
categoryEnhancers << toDo
|
||||
}
|
||||
|
||||
def processVariants(GroovyClassDescriptor descriptor, consumer, ProcessingContext ctx) {
|
||||
for (pair in enhancers) {
|
||||
if (pair.first.isApplicable(descriptor, ctx)) {
|
||||
@@ -77,18 +72,6 @@ public class GroovyDslExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
def processCategoryVariants(Project project, consumer) {
|
||||
for (enhancer in categoryEnhancers) {
|
||||
Closure f = enhancer.clone()
|
||||
f.delegate = consumer
|
||||
f.resolveStrategy = Closure.DELEGATE_FIRST
|
||||
|
||||
use(cats) {
|
||||
f.call()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def String toString() {
|
||||
return "${super.toString()}; file = $myFileName";
|
||||
}
|
||||
|
||||
@@ -126,8 +126,8 @@ public class GroovyDslScript {
|
||||
}
|
||||
|
||||
private boolean handleDslError(Throwable e) {
|
||||
LOG.error(e);
|
||||
if (project.isDisposed() || ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
LOG.error(e);
|
||||
return true;
|
||||
}
|
||||
GroovyDslFileIndex.invokeDslErrorPopup(e, project, file);
|
||||
|
||||
+64
-2
@@ -7,6 +7,19 @@ import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.AnnotatedScope
|
||||
import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.ClassScope
|
||||
import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.ClosureScope
|
||||
import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.ScriptScope
|
||||
import com.intellij.psi.util.TypeConversionUtil
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import com.intellij.openapi.util.Key
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod
|
||||
import com.intellij.psi.util.CachedValue
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.CachedValueProvider.Result
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrGdkMethodImpl
|
||||
import com.intellij.psi.util.PsiModificationTracker
|
||||
import com.intellij.openapi.roots.ProjectRootManager
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.util.Function
|
||||
|
||||
/**
|
||||
* @author ilyas
|
||||
@@ -42,8 +55,57 @@ class GdslMetaClassProperties {
|
||||
}
|
||||
}
|
||||
|
||||
Closure staticContributor = { Closure toDo ->
|
||||
myExecutor.addCategoryEnhancer toDo
|
||||
Closure category = {Object[] params ->
|
||||
if (params.length == 1) {
|
||||
processCategoryMethods(params[0], new Function() {def fun(def param) {new GrGdkMethodImpl(param, false)}})
|
||||
}
|
||||
else if (params.length == 2) {
|
||||
if (params[1] instanceof Boolean) {
|
||||
processCategoryMethods(params[0], new Function() {def fun(def param) {new GrGdkMethodImpl(param, params[1])}})
|
||||
}
|
||||
else {
|
||||
processCategoryMethods(params[0], params[1])
|
||||
}
|
||||
}
|
||||
else throw new IllegalArgumentException("Incorrect aruments in method 'category': $params")
|
||||
}
|
||||
|
||||
private def processCategoryMethods (def className, Function<PsiMethod, PsiMethod> converter) {
|
||||
contributor(context()) {
|
||||
if (!psiType) return;
|
||||
|
||||
def categoryClass = findClass(className)
|
||||
if (!categoryClass) return;
|
||||
categoryClass.methods.each {m ->
|
||||
def params = m.parameterList.parameters
|
||||
if (!params) return;
|
||||
def targetType = TypeConversionUtil.erasure(params[0].type)
|
||||
if (!ResolveUtil.isInheritor(psiType, targetType.getCanonicalText(), project)) return;
|
||||
|
||||
add CachedValuesManager.getManager(project).
|
||||
getCachedValue(m, CategoryMethodProvider.CATEGORY_METHOD, new CategoryMethodProvider(m, converter), false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class CategoryMethodProvider implements CachedValueProvider<GrGdkMethod> {
|
||||
static final Key<CachedValue<GrGdkMethod>> CATEGORY_METHOD = Key.create("category method");
|
||||
|
||||
def method
|
||||
def converter
|
||||
|
||||
def CategoryMethodProvider(def method, def converter) {
|
||||
this.method = method;
|
||||
this.converter = converter
|
||||
}
|
||||
|
||||
Result<GrGdkMethod> compute() {
|
||||
return Result.create(
|
||||
converter.fun(method),
|
||||
PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT,
|
||||
ProjectRootManager.getInstance(method.project));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,7 +38,7 @@ public class GantMemberContributor extends NonCodeMembersContributor {
|
||||
PsiScopeProcessor processor,
|
||||
PsiElement place,
|
||||
ResolveState state) {
|
||||
if (ResolveUtil.isInheritor(qualifierType, "groovy.util.AntBuilder", place)) {
|
||||
if (ResolveUtil.isInheritor(qualifierType, "groovy.util.AntBuilder", place.getProject())) {
|
||||
processAntTasks(processor, place, state);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.jetbrains.plugins.groovy.gpp;
|
||||
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiParameter;
|
||||
import com.intellij.psi.PsiSubstitutor;
|
||||
import com.intellij.psi.PsiType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrGdkMethodImpl;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.DominanceAwareMethod;
|
||||
|
||||
/**
|
||||
* @author Maxim.Medvedev
|
||||
*/
|
||||
public class GppGdkMethod extends GrGdkMethodImpl implements DominanceAwareMethod {
|
||||
public GppGdkMethod(PsiMethod method, final boolean isStatic) {
|
||||
super(method, isStatic);
|
||||
}
|
||||
|
||||
public boolean isMoreConcreteThan(@NotNull final PsiSubstitutor substitutor,
|
||||
@NotNull PsiMethod another,
|
||||
@NotNull PsiSubstitutor anotherSubstitutor,
|
||||
@NotNull GroovyPsiElement context) {
|
||||
if (another instanceof GrGdkMethodImpl && another.getName().equals(getName())) {
|
||||
final PsiParameter[] plusParameters = getParameterList().getParameters();
|
||||
final PsiParameter[] defParameters = another.getParameterList().getParameters();
|
||||
|
||||
final PsiType[] paramTypes = new PsiType[plusParameters.length];
|
||||
for (int i = 0; i < paramTypes.length; i++) {
|
||||
paramTypes[i] = eliminateOneMethodInterfaces(plusParameters[i], defParameters, i);
|
||||
|
||||
}
|
||||
|
||||
final GrClosureSignature gdkSignature = GrClosureSignatureUtil.createSignature(another, anotherSubstitutor);
|
||||
if (GrClosureSignatureUtil.isSignatureApplicable(gdkSignature, paramTypes, context)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static PsiType eliminateOneMethodInterfaces(PsiParameter plusParameter, PsiParameter[] gdkParameters, int i) {
|
||||
PsiType type = plusParameter.getType();
|
||||
if (i < gdkParameters.length &&
|
||||
gdkParameters[i].getType().equalsToText(GrClosableBlock.GROOVY_LANG_CLOSURE) &&
|
||||
GppClosureParameterTypeProvider.findSingleAbstractMethodSignature(type) != null) {
|
||||
return gdkParameters[i].getType();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
package org.jetbrains.plugins.groovy.gpp;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.util.NotNullFunction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrGdkMethodImpl;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.DominanceAwareMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.NonCodeMembersContributor;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class GppStdLibSupport extends NonCodeMembersContributor {
|
||||
private static final Key<CachedValue<Map<String, List<PsiMethod>>>> CACHED_STDLIB = Key.create("GppStdLib");
|
||||
private static final String[] STDLIB_CLASSES = {
|
||||
"groovy.util.Conversions",
|
||||
"groovy.util.Files", "groovy.util.Filters",
|
||||
"groovy.util.Iterations", "groovy.util.Mappers",
|
||||
"groovy.util.Sort", "groovy.util.Strings",
|
||||
"groovy.util.With",
|
||||
"groovy.util.concurrent.Atomics",
|
||||
"org.mbte.groovypp.runtime.ArraysMethods",
|
||||
"org.mbte.groovypp.runtime.DefaultGroovyPPMethods"};
|
||||
|
||||
@Override
|
||||
public void processDynamicElements(@NotNull PsiType type, PsiScopeProcessor processor, PsiElement place, ResolveState state) {
|
||||
if (!(type instanceof PsiClassType) && !(type instanceof PsiArrayType)) {
|
||||
return;
|
||||
}
|
||||
if (!GppTypeConverter.hasTypedContext(place)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Project project = place.getProject();
|
||||
final Map<String, List<PsiMethod>> map = CachedValuesManager.getManager(project).getCachedValue(project, CACHED_STDLIB, new CachedValueProvider<Map<String, List<PsiMethod>>>() {
|
||||
public Result<Map<String, List<PsiMethod>>> compute() {
|
||||
final GroovyPsiManager manager = GroovyPsiManager.getInstance(project);
|
||||
final Map<String, List<PsiMethod>> result = new HashMap<String, List<PsiMethod>>();
|
||||
final NotNullFunction<PsiMethod, PsiMethod> nonStaticConverter = new NotNullFunction<PsiMethod, PsiMethod>() {
|
||||
@NotNull
|
||||
public PsiMethod fun(PsiMethod method) {
|
||||
return new GppGdkMethod(method, false);
|
||||
}
|
||||
};
|
||||
|
||||
for (String qname : STDLIB_CLASSES) {
|
||||
manager.addCategoryMethods(qname, result, nonStaticConverter);
|
||||
}
|
||||
|
||||
manager.addCategoryMethods("org.mbte.groovypp.runtime.DefaultGroovyPPStaticMethods", result, new NotNullFunction<PsiMethod, PsiMethod>() {
|
||||
@NotNull
|
||||
public PsiMethod fun(PsiMethod method) {
|
||||
return new GppGdkMethod(method, true);
|
||||
}
|
||||
});
|
||||
|
||||
return Result.create(result, ProjectRootManager.getInstance(project));
|
||||
}
|
||||
}, false);
|
||||
|
||||
for (String className : ResolveUtil.getAllSuperTypes(type, place).keySet()) {
|
||||
final List<PsiMethod> methods = map.get(className);
|
||||
if (methods != null) {
|
||||
for (PsiMethod method : methods) {
|
||||
if (!ResolveUtil.processElement(processor, method, state)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class GppGdkMethod extends GrGdkMethodImpl implements DominanceAwareMethod {
|
||||
public GppGdkMethod(PsiMethod method, final boolean isStatic) {
|
||||
super(method, isStatic);
|
||||
}
|
||||
|
||||
public boolean isMoreConcreteThan(@NotNull final PsiSubstitutor substitutor,
|
||||
@NotNull PsiMethod another,
|
||||
@NotNull PsiSubstitutor anotherSubstitutor,
|
||||
@NotNull GroovyPsiElement context) {
|
||||
if (another instanceof GrGdkMethodImpl && another.getName().equals(getName())) {
|
||||
final PsiParameter[] plusParameters = getParameterList().getParameters();
|
||||
final PsiParameter[] defParameters = another.getParameterList().getParameters();
|
||||
|
||||
final PsiType[] paramTypes = new PsiType[plusParameters.length];
|
||||
for (int i = 0; i < paramTypes.length; i++) {
|
||||
paramTypes[i] = eliminateOneMethodInterfaces(plusParameters[i], defParameters, i);
|
||||
|
||||
}
|
||||
|
||||
final GrClosureSignature gdkSignature = GrClosureSignatureUtil.createSignature(another, anotherSubstitutor);
|
||||
if (GrClosureSignatureUtil.isSignatureApplicable(gdkSignature, paramTypes, context)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static PsiType eliminateOneMethodInterfaces(PsiParameter plusParameter, PsiParameter[] gdkParameters, int i) {
|
||||
PsiType type = plusParameter.getType();
|
||||
if (i < gdkParameters.length &&
|
||||
gdkParameters[i].getType().equalsToText(GrClosableBlock.GROOVY_LANG_CLOSURE) &&
|
||||
GppClosureParameterTypeProvider.findSingleAbstractMethodSignature(type) != null) {
|
||||
return gdkParameters[i].getType();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,25 +25,16 @@ import com.intellij.openapi.roots.ModuleRootListener;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiManagerEx;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.PsiShortNamesCache;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.ConcurrencyUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.NotNullFunction;
|
||||
import com.intellij.util.containers.ConcurrentWeakHashMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.dsl.GroovyDslExecutor;
|
||||
import org.jetbrains.plugins.groovy.dsl.GroovyDslFileIndex;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrGdkMethodImpl;
|
||||
import org.jetbrains.plugins.groovy.lang.stubs.GroovyShortNamesCache;
|
||||
|
||||
import java.util.*;
|
||||
@@ -54,12 +45,10 @@ import java.util.*;
|
||||
public class GroovyPsiManager {
|
||||
private static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager");
|
||||
private final Project myProject;
|
||||
private Map<String, List<PsiMethod>> myDefaultMethods;
|
||||
|
||||
private GrTypeDefinition myArrayClass;
|
||||
|
||||
private final ConcurrentWeakHashMap<GroovyPsiElement, PsiType> myCalculatedTypes = new ConcurrentWeakHashMap<GroovyPsiElement, PsiType>();
|
||||
private volatile boolean myRebuildGdkPending = true;
|
||||
private final GroovyShortNamesCache myCache;
|
||||
|
||||
private final TypeInferenceHelper myTypeInferenceHelper;
|
||||
@@ -84,7 +73,6 @@ public class GroovyPsiManager {
|
||||
|
||||
public void rootsChanged(ModuleRootEvent event) {
|
||||
dropTypesCache();
|
||||
myRebuildGdkPending = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -98,65 +86,6 @@ public class GroovyPsiManager {
|
||||
}
|
||||
|
||||
|
||||
public List<PsiMethod> getDefaultMethods(String qName) {
|
||||
if (myRebuildGdkPending) {
|
||||
final Map<String, List<PsiMethod>> gdk = buildGDK();
|
||||
if (myRebuildGdkPending) {
|
||||
myDefaultMethods = gdk;
|
||||
myRebuildGdkPending = false;
|
||||
}
|
||||
}
|
||||
|
||||
List<PsiMethod> methods = myDefaultMethods.get(qName);
|
||||
if (methods == null) return Collections.emptyList();
|
||||
return methods;
|
||||
}
|
||||
|
||||
private Map<String, List<PsiMethod>> buildGDK() {
|
||||
return null; //To change body of created methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
public List<PsiMethod> getDefaultMethods(PsiClass psiClass) {
|
||||
List<PsiMethod> list = new ArrayList<PsiMethod>();
|
||||
getDefaultMethodsInner(psiClass, new HashSet<PsiClass>(), list);
|
||||
return list;
|
||||
}
|
||||
|
||||
public void getDefaultMethodsInner(PsiClass psiClass, Set<PsiClass> watched, List<PsiMethod> methods) {
|
||||
if (watched.contains(psiClass)) return;
|
||||
watched.add(psiClass);
|
||||
methods.addAll(getDefaultMethods(psiClass.getQualifiedName()));
|
||||
for (PsiClass aClass : psiClass.getSupers()) {
|
||||
getDefaultMethodsInner(aClass, watched, methods);
|
||||
}
|
||||
}
|
||||
|
||||
public void addCategoryMethods(String fromClass, Map<String, List<PsiMethod>> toMap, NotNullFunction<PsiMethod, PsiMethod> converter) {
|
||||
PsiClass categoryClass = JavaPsiFacade.getInstance(myProject).findClass(fromClass, GlobalSearchScope.allScope(myProject));
|
||||
if (categoryClass != null) {
|
||||
for (PsiMethod method : categoryClass.getMethods()) {
|
||||
if (method.isConstructor()) continue;
|
||||
if (!method.hasModifierProperty(PsiModifier.STATIC) || !method.hasModifierProperty(PsiModifier.PUBLIC)) continue;
|
||||
addDefaultMethod(method, toMap, converter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void addDefaultMethod(PsiMethod method, Map<String, List<PsiMethod>> map, NotNullFunction<PsiMethod, PsiMethod> converter) {
|
||||
if (!method.hasModifierProperty(PsiModifier.PUBLIC)) return;
|
||||
|
||||
PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
LOG.assertTrue(parameters.length > 0, method.getName());
|
||||
PsiType thisType = TypeConversionUtil.erasure(parameters[0].getType());
|
||||
String thisCanonicalText = thisType.getCanonicalText();
|
||||
LOG.assertTrue(thisCanonicalText != null);
|
||||
List<PsiMethod> hisMethods = map.get(thisCanonicalText);
|
||||
if (hisMethods == null) {
|
||||
hisMethods = new ArrayList<PsiMethod>();
|
||||
map.put(thisCanonicalText, hisMethods);
|
||||
}
|
||||
hisMethods.add(converter.fun(method));
|
||||
}
|
||||
|
||||
public static GroovyPsiManager getInstance(Project project) {
|
||||
return ServiceManager.getService(project, GroovyPsiManager.class);
|
||||
|
||||
@@ -161,8 +161,7 @@ public class ResolveUtil {
|
||||
|
||||
}
|
||||
|
||||
public static Map<String, PsiType> getAllSuperTypes(PsiType base, final PsiElement place) {
|
||||
final Project project = place.getProject();
|
||||
public static Map<String, PsiType> getAllSuperTypes(PsiType base, final Project project) {
|
||||
final Map<String, Map<String, PsiType>> cache =
|
||||
CachedValuesManager.getManager(project).getCachedValue(project, new CachedValueProvider<Map<String, Map<String, PsiType>>>() {
|
||||
@Override
|
||||
@@ -184,8 +183,8 @@ public class ResolveUtil {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean isInheritor(PsiType type, @NotNull String baseClass, PsiElement place) {
|
||||
return getAllSuperTypes(type, place).keySet().contains(baseClass);
|
||||
public static boolean isInheritor(PsiType type, @NotNull String baseClass, Project project) {
|
||||
return getAllSuperTypes(type, project).keySet().contains(baseClass);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user