mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -17,7 +17,7 @@ package com.intellij.ide.macro;
|
||||
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.DataKeys;
|
||||
import com.intellij.openapi.actionSystem.LangDataKeys;
|
||||
import com.intellij.psi.JavaDirectoryService;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiFile;
|
||||
@@ -41,7 +41,7 @@ public final class FilePackageMacro extends Macro {
|
||||
|
||||
@Nullable
|
||||
static PsiPackage getFilePackage(DataContext dataContext) {
|
||||
PsiFile psiFile = DataKeys.PSI_FILE.getData(dataContext);
|
||||
PsiFile psiFile = LangDataKeys.PSI_FILE.getData(dataContext);
|
||||
if (psiFile == null) return null;
|
||||
PsiDirectory containingDirectory = psiFile.getContainingDirectory();
|
||||
if (containingDirectory == null || !containingDirectory.isValid()) return null;
|
||||
|
||||
@@ -33,6 +33,7 @@ public class LineRange {
|
||||
public LineRange(final int startLine, final int endLine) {
|
||||
this.startLine = startLine;
|
||||
this.endLine = endLine;
|
||||
LOG.assertTrue(startLine > 0, "Negative start line");
|
||||
if (startLine > endLine) {
|
||||
LOG.error("start > end: start=" + startLine+"; end="+endLine);
|
||||
}
|
||||
|
||||
@@ -18,8 +18,6 @@ package com.intellij.ide.macro;
|
||||
|
||||
import com.intellij.application.options.PathMacrosImpl;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.IdeEventQueue;
|
||||
import com.intellij.ide.impl.DataManagerImpl;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
@@ -147,11 +145,11 @@ public final class MacroManager {
|
||||
String name = "$" + macro.getName() + "$";
|
||||
if (str.indexOf(name) >= 0) {
|
||||
String expanded = macro.expand(dataContext);
|
||||
if (dataContext instanceof DataManagerImpl.MyDataContext) {
|
||||
// hack: macro.expand() can cause UI events such as showing dialogs ('Prompt' macro) which may 'invalidate' the datacontext
|
||||
// since we know exactly that context is valid, we need to update its event count
|
||||
((DataManagerImpl.MyDataContext)dataContext).setEventCount(IdeEventQueue.getInstance().getEventCount());
|
||||
}
|
||||
//if (dataContext instanceof DataManagerImpl.MyDataContext) {
|
||||
// // hack: macro.expand() can cause UI events such as showing dialogs ('Prompt' macro) which may 'invalidate' the datacontext
|
||||
// // since we know exactly that context is valid, we need to update its event count
|
||||
// ((DataManagerImpl.MyDataContext)dataContext).setEventCount(IdeEventQueue.getInstance().getEventCount());
|
||||
//}
|
||||
if (expanded == null) {
|
||||
expanded = "";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.tools;
|
||||
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.DataKey;
|
||||
import com.intellij.openapi.actionSystem.LangDataKeys;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
class HackyDataContext implements DataContext {
|
||||
private static DataKey[] keys = {
|
||||
PlatformDataKeys.PROJECT,
|
||||
PlatformDataKeys.PROJECT_FILE_DIRECTORY,
|
||||
PlatformDataKeys.EDITOR,
|
||||
PlatformDataKeys.VIRTUAL_FILE,
|
||||
LangDataKeys.MODULE,
|
||||
LangDataKeys.PSI_FILE
|
||||
};
|
||||
|
||||
|
||||
private final Map<String, Object> values = new HashMap<String, Object>();
|
||||
|
||||
public HackyDataContext(DataContext context) {
|
||||
for (DataKey key : keys) {
|
||||
values.put(key.getName(), key.getData(context));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getData(@NonNls String dataId) {
|
||||
if (values.keySet().contains(dataId)) {
|
||||
return values.get(dataId);
|
||||
}
|
||||
//noinspection UseOfSystemOutOrSystemErr
|
||||
System.out.println("Please add " + dataId + " key in " + getClass().getName());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -35,10 +35,11 @@ public class ToolAction extends AnAction implements DumbAware {
|
||||
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
MacroManager.getInstance().cacheMacrosPreview(e.getDataContext());
|
||||
final HackyDataContext dataContext = new HackyDataContext(e.getDataContext());
|
||||
Tool[] tools = ToolManager.getInstance().getTools();
|
||||
for (Tool tool : tools) {
|
||||
if (myActionId.equals(tool.getActionId())) {
|
||||
tool.execute(e.getDataContext());
|
||||
tool.execute(dataContext);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,8 +28,6 @@ import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.execution.process.ProcessTerminatedListener;
|
||||
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
import com.intellij.execution.runners.ProgramRunner;
|
||||
import com.intellij.ide.IdeEventQueue;
|
||||
import com.intellij.ide.impl.DataManagerImpl;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -48,11 +46,11 @@ public class ToolRunProfile implements ModuleRunProfile{
|
||||
public ToolRunProfile(final Tool tool, final DataContext context) {
|
||||
myTool = tool;
|
||||
myCommandLine = myTool.createCommandLine(context);
|
||||
if (context instanceof DataManagerImpl.MyDataContext) {
|
||||
// hack: macro.expand() can cause UI events such as showing dialogs ('Prompt' macro) which may 'invalidate' the datacontext
|
||||
// since we know exactly that context is valid, we need to update its event count
|
||||
((DataManagerImpl.MyDataContext)context).setEventCount(IdeEventQueue.getInstance().getEventCount());
|
||||
}
|
||||
//if (context instanceof DataManagerImpl.MyDataContext) {
|
||||
// // hack: macro.expand() can cause UI events such as showing dialogs ('Prompt' macro) which may 'invalidate' the datacontext
|
||||
// // since we know exactly that context is valid, we need to update its event count
|
||||
// ((DataManagerImpl.MyDataContext)context).setEventCount(IdeEventQueue.getInstance().getEventCount());
|
||||
//}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
||||
@@ -308,7 +308,7 @@ public class DataManagerImpl extends DataManager implements ApplicationComponent
|
||||
PlatformDataKeys.MODALITY_STATE.getName()
|
||||
));
|
||||
|
||||
public class MyDataContext implements DataContext, UserDataHolder {
|
||||
public static class MyDataContext implements DataContext, UserDataHolder {
|
||||
private int myEventCount;
|
||||
// To prevent memory leak we have to wrap passed component into
|
||||
// the weak reference. For example, Swing often remembers menu items
|
||||
@@ -322,7 +322,9 @@ public class DataManagerImpl extends DataManager implements ApplicationComponent
|
||||
myRef = new WeakReference<Component>(component);
|
||||
}
|
||||
|
||||
public void setEventCount(int eventCount) {
|
||||
|
||||
public void setEventCount(int eventCount, Object caller) {
|
||||
assert caller instanceof IdeKeyEventDispatcher : "This method might be accessible from " + IdeKeyEventDispatcher.class.getName() + " only";
|
||||
myCachedData.clear();
|
||||
myEventCount = eventCount;
|
||||
}
|
||||
@@ -366,11 +368,11 @@ public class DataManagerImpl extends DataManager implements ApplicationComponent
|
||||
return _component != null ? ModalityState.stateForComponent(_component) : ModalityState.NON_MODAL;
|
||||
}
|
||||
else if (PlatformDataKeys.EDITOR.is(dataId)) {
|
||||
Editor editor = (Editor)DataManagerImpl.this.getData(dataId, _component);
|
||||
Editor editor = (Editor)(((DataManagerImpl)DataManager.getInstance()).getData(dataId, _component));
|
||||
return validateEditor(editor);
|
||||
}
|
||||
else {
|
||||
return DataManagerImpl.this.getData(dataId, _component);
|
||||
return (((DataManagerImpl)DataManager.getInstance()).getData(dataId, _component));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -580,7 +580,7 @@ public final class IdeKeyEventDispatcher implements Disposable {
|
||||
|
||||
processor.onUpdatePassed(e, action, actionEvent);
|
||||
|
||||
((DataManagerImpl.MyDataContext)myContext.getDataContext()).setEventCount(IdeEventQueue.getInstance().getEventCount());
|
||||
((DataManagerImpl.MyDataContext)myContext.getDataContext()).setEventCount(IdeEventQueue.getInstance().getEventCount(), this);
|
||||
actionManager.fireBeforeActionPerformed(action, actionEvent.getDataContext(), actionEvent);
|
||||
Component component = PlatformDataKeys.CONTEXT_COMPONENT.getData(actionEvent.getDataContext());
|
||||
if (component != null && !component.isShowing()) {
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.intellij.lang.ant.config.actions;
|
||||
|
||||
import com.intellij.ide.IdeEventQueue;
|
||||
import com.intellij.ide.impl.DataManagerImpl;
|
||||
import com.intellij.lang.ant.config.AntBuildFile;
|
||||
import com.intellij.lang.ant.config.AntConfiguration;
|
||||
import com.intellij.lang.ant.config.AntConfigurationListener;
|
||||
@@ -25,7 +23,6 @@ import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
|
||||
@@ -83,12 +80,12 @@ public class TargetActionStub extends AnAction implements Disposable {
|
||||
return;
|
||||
}
|
||||
if (!myActionInvoked.getAndSet(true)) {
|
||||
final DataContext context = e.getDataContext();
|
||||
if (context instanceof DataManagerImpl.MyDataContext) {
|
||||
// hack: macro.expand() can cause UI events such as showing dialogs ('Prompt' macro) which may 'invalidate' the datacontext
|
||||
// since we know exactly that context is valid, we need to update its event count
|
||||
((DataManagerImpl.MyDataContext)context).setEventCount(IdeEventQueue.getInstance().getEventCount());
|
||||
}
|
||||
//final DataContext context = e.getDataContext();
|
||||
//if (context instanceof DataManagerImpl.MyDataContext) {
|
||||
// // hack: macro.expand() can cause UI events such as showing dialogs ('Prompt' macro) which may 'invalidate' the datacontext
|
||||
// // since we know exactly that context is valid, we need to update its event count
|
||||
// ((DataManagerImpl.MyDataContext)context).setEventCount(IdeEventQueue.getInstance().getEventCount());
|
||||
//}
|
||||
action.actionPerformed(e);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -61,7 +61,8 @@ public class GDKSuperMethodSearcher implements QueryExecutor<MethodSignatureBack
|
||||
|
||||
final String name = method.getName();
|
||||
final MethodResolverProcessor processor = new MethodResolverProcessor(name, ((GrMethod)method), false, null, null, PsiType.EMPTY_ARRAY);
|
||||
ResolveUtil.processNonCodeMembers(JavaPsiFacade.getElementFactory(project).createType(psiClass), processor, (GrMethod)method);
|
||||
ResolveUtil.processNonCodeMembers(JavaPsiFacade.getElementFactory(project).createType(psiClass), processor, (GrMethod)method,
|
||||
ResolveState.initial());
|
||||
|
||||
final GroovyResolveResult[] candidates = processor.getCandidates();
|
||||
|
||||
|
||||
+1
-1
@@ -144,7 +144,7 @@ public class LiteralConstructorReference extends PsiReferenceBase.Poly<GrListOrM
|
||||
final GroovyResolveResult[] constructorCandidates =
|
||||
PsiUtil.getConstructorCandidates(myExpectedType, getCallArgumentTypes(), getElement());
|
||||
|
||||
if (constructorCandidates.length == 0) {
|
||||
if (constructorCandidates.length == 0 && classResolveResult.getElement() != null) {
|
||||
return new GroovyResolveResult[]{new GroovyResolveResultImpl(classResolveResult)};
|
||||
}
|
||||
return constructorCandidates;
|
||||
|
||||
+12
-1
@@ -15,9 +15,10 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.lang.psi.api;
|
||||
|
||||
import com.intellij.psi.ResolveResult;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiSubstitutor;
|
||||
import com.intellij.psi.ResolveResult;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
|
||||
@@ -34,10 +35,14 @@ public interface GroovyResolveResult extends ResolveResult {
|
||||
@Nullable
|
||||
GroovyPsiElement getCurrentFileResolveContext();
|
||||
|
||||
@NotNull
|
||||
PsiSubstitutor getSubstitutor();
|
||||
|
||||
boolean isInvokedOnProperty();
|
||||
|
||||
@Nullable
|
||||
SpreadState getSpreadState();
|
||||
|
||||
GroovyResolveResult EMPTY_RESULT = new GroovyResolveResult() {
|
||||
public boolean isAccessible() {
|
||||
return false;
|
||||
@@ -51,6 +56,7 @@ public interface GroovyResolveResult extends ResolveResult {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiSubstitutor getSubstitutor() {
|
||||
return PsiSubstitutor.EMPTY;
|
||||
}
|
||||
@@ -68,5 +74,10 @@ public interface GroovyResolveResult extends ResolveResult {
|
||||
public boolean isInvokedOnProperty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpreadState getSpreadState() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.lang.psi.api;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.PsiType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public final class SpreadState {
|
||||
public static final Key<SpreadState> SPREAD_STATE = Key.create("Spread state");
|
||||
|
||||
private final PsiType containerType;
|
||||
@Nullable private final SpreadState innerState;
|
||||
|
||||
public SpreadState(PsiType type, @Nullable SpreadState state) {
|
||||
containerType = type;
|
||||
innerState = state;
|
||||
}
|
||||
|
||||
public PsiType getContainerType() {
|
||||
return containerType;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public SpreadState getInnerState() {
|
||||
return innerState;
|
||||
}
|
||||
|
||||
public static SpreadState create(PsiType type, @Nullable SpreadState state) {
|
||||
return new SpreadState(type, state);
|
||||
}
|
||||
|
||||
public static PsiType apply(PsiType item, @Nullable SpreadState state, Project project) {
|
||||
if (state == null) return item;
|
||||
return apply(TypesUtil.createSimilarCollection(state.getContainerType(), project, item), state.getInnerState(), project);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.lang.psi.impl;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.PsiClassType;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public class GrSpreadType extends GrLiteralClassType {
|
||||
|
||||
private PsiType myType;
|
||||
|
||||
public GrSpreadType(PsiType original, PsiType containerType, GlobalSearchScope scope) {
|
||||
this(original, containerType, LanguageLevel.JDK_1_5, scope, JavaPsiFacade.getInstance(scope.getProject()));
|
||||
}
|
||||
|
||||
public GrSpreadType(PsiType original, PsiType containerType, LanguageLevel languageLevel, GlobalSearchScope scope, JavaPsiFacade facade) {
|
||||
super(languageLevel, scope, facade);
|
||||
|
||||
final Project project = facade.getProject();
|
||||
myType = TypesUtil.createSimilarCollection(containerType, project, original);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getJavaClassName() {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getClassName() {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiType[] getParameters() {
|
||||
return new PsiType[0]; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClassType setLanguageLevel(@NotNull LanguageLevel languageLevel) {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInternalCanonicalText() {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return false; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
+24
-12
@@ -16,10 +16,12 @@
|
||||
package org.jetbrains.plugins.groovy.lang.psi.impl;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrClassSubstitutor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.SpreadState;
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
@@ -31,28 +33,30 @@ public class GroovyResolveResultImpl implements GroovyResolveResult {
|
||||
private final PsiSubstitutor mySubstitutor;
|
||||
private final boolean myIsInvokedOnProperty;
|
||||
|
||||
private GroovyPsiElement myCurrentFileResolveContext;
|
||||
private final GroovyPsiElement myCurrentFileResolveContext;
|
||||
private final SpreadState mySpreadState;
|
||||
|
||||
public GroovyResolveResultImpl(PsiElement element, boolean isAccessible) {
|
||||
this(element, null, PsiSubstitutor.EMPTY, isAccessible, true);
|
||||
public GroovyResolveResultImpl(@NotNull PsiElement element, boolean isAccessible) {
|
||||
this(element, null, null, PsiSubstitutor.EMPTY, isAccessible, true, false);
|
||||
}
|
||||
|
||||
public GroovyResolveResultImpl(PsiElement element,
|
||||
@Nullable GroovyPsiElement context,
|
||||
PsiSubstitutor substitutor,
|
||||
public GroovyResolveResultImpl(@NotNull PsiElement element,
|
||||
@Nullable GroovyPsiElement resolveContext,
|
||||
@Nullable SpreadState spreadState,
|
||||
@NotNull PsiSubstitutor substitutor,
|
||||
boolean isAccessible,
|
||||
boolean staticsOK) {
|
||||
this(element, context, substitutor, isAccessible, staticsOK, false);
|
||||
this(element, resolveContext, spreadState, substitutor, isAccessible, staticsOK, false);
|
||||
}
|
||||
|
||||
public GroovyResolveResultImpl(PsiClassType.ClassResolveResult classResolveResult) {
|
||||
this(classResolveResult.getElement(), null, classResolveResult.getSubstitutor(), classResolveResult.isAccessible(),
|
||||
classResolveResult.isStaticsScopeCorrect());
|
||||
this(classResolveResult.getElement(), null, null, classResolveResult.getSubstitutor(), classResolveResult.isAccessible(), classResolveResult.isStaticsScopeCorrect(), false);
|
||||
}
|
||||
|
||||
public GroovyResolveResultImpl(PsiElement element,
|
||||
GroovyPsiElement resolveContext,
|
||||
PsiSubstitutor substitutor,
|
||||
public GroovyResolveResultImpl(@NotNull PsiElement element,
|
||||
@Nullable GroovyPsiElement resolveContext,
|
||||
@Nullable SpreadState spreadState,
|
||||
@NotNull PsiSubstitutor substitutor,
|
||||
boolean isAccessible,
|
||||
boolean staticsOK,
|
||||
boolean isInvokedOnProperty) {
|
||||
@@ -62,8 +66,10 @@ public class GroovyResolveResultImpl implements GroovyResolveResult {
|
||||
mySubstitutor = substitutor;
|
||||
myIsStaticsOK = staticsOK;
|
||||
myIsInvokedOnProperty = isInvokedOnProperty;
|
||||
mySpreadState = spreadState;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiSubstitutor getSubstitutor() {
|
||||
return mySubstitutor;
|
||||
}
|
||||
@@ -108,6 +114,7 @@ public class GroovyResolveResultImpl implements GroovyResolveResult {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GroovyPsiElement getCurrentFileResolveContext() {
|
||||
return myCurrentFileResolveContext;
|
||||
}
|
||||
@@ -116,6 +123,11 @@ public class GroovyResolveResultImpl implements GroovyResolveResult {
|
||||
return myIsInvokedOnProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpreadState getSpreadState() {
|
||||
return mySpreadState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GroovyResolveResultImpl{" +
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ public class GrConstructorInvocationImpl extends GrCallImpl implements GrConstru
|
||||
}
|
||||
|
||||
public GroovyResolveResult[] multiResolveClass() {
|
||||
return new GroovyResolveResult[]{new GroovyResolveResultImpl(getDelegatedClass(), this, PsiSubstitutor.EMPTY, true, true)};
|
||||
return new GroovyResolveResult[]{new GroovyResolveResultImpl(getDelegatedClass(), this, null, PsiSubstitutor.EMPTY, true, true)};
|
||||
}
|
||||
|
||||
public PsiMethod resolveMethod() {
|
||||
|
||||
+7
-5
@@ -35,6 +35,7 @@ import org.jetbrains.plugins.groovy.lang.completion.GroovyCompletionUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.SpreadState;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
|
||||
@@ -117,7 +118,7 @@ public class CompleteReferenceExpression {
|
||||
getVariantsFromQualifierForSpreadOperator(refExpr, processor, qualifier);
|
||||
}
|
||||
}
|
||||
ResolveUtil.processCategoryMembers(refExpr, processor);
|
||||
ResolveUtil.processCategoryMembers(refExpr, processor, ResolveState.initial());
|
||||
}
|
||||
|
||||
private static void getVariantsFromQualifierForSpreadOperator(GrReferenceExpression refExpr,
|
||||
@@ -206,8 +207,8 @@ public class CompleteReferenceExpression {
|
||||
|
||||
final GrPropertyForCompletion field = new GrPropertyForCompletion(method, name, type);
|
||||
if (resolveResult != null) {
|
||||
return new GroovyResolveResultImpl(field, resolveResult.getCurrentFileResolveContext(), resolveResult.getSubstitutor(),
|
||||
resolveResult.isAccessible(), resolveResult.isStaticsOK());
|
||||
return new GroovyResolveResultImpl(field, resolveResult.getCurrentFileResolveContext(), resolveResult.getSpreadState(),
|
||||
resolveResult.getSubstitutor(), resolveResult.isAccessible(), resolveResult.isStaticsOK(), false);
|
||||
}
|
||||
else {
|
||||
return new GroovyResolveResultImpl(field, true);
|
||||
@@ -377,12 +378,13 @@ public class CompleteReferenceExpression {
|
||||
|
||||
boolean isAccessible = isAccessible(namedElement);
|
||||
final GroovyPsiElement resolveContext = state.get(RESOLVE_CONTEXT);
|
||||
final SpreadState spreadState = state.get(SpreadState.SPREAD_STATE);
|
||||
boolean isStaticsOK = isStaticsOK(namedElement, resolveContext, myParameters.getInvocationCount() <= 1);
|
||||
|
||||
PsiSubstitutor substitutor = state.get(PsiSubstitutor.KEY);
|
||||
if (substitutor == null) substitutor = PsiSubstitutor.EMPTY;
|
||||
|
||||
consume(new GroovyResolveResultImpl(namedElement, resolveContext, substitutor, isAccessible, isStaticsOK));
|
||||
consume(new GroovyResolveResultImpl(namedElement, resolveContext, spreadState, substitutor, isAccessible, isStaticsOK));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -407,7 +409,7 @@ public class CompleteReferenceExpression {
|
||||
element = ((GrReflectedMethod)element).getBaseMethod();
|
||||
if (!myProcessedMethodWithOptionalParams.add((GrMethod)element)) return;
|
||||
|
||||
result = new GroovyResolveResultImpl(element, result.getCurrentFileResolveContext(),
|
||||
result = new GroovyResolveResultImpl(element, result.getCurrentFileResolveContext(), result.getSpreadState(),
|
||||
result.getSubstitutor(), result.isAccessible(), result.isStaticsOK(),
|
||||
result.isInvokedOnProperty());
|
||||
}
|
||||
|
||||
+107
-84
@@ -42,6 +42,7 @@ import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.SpreadState;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
|
||||
@@ -64,7 +65,8 @@ import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.*;
|
||||
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mAT;
|
||||
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mMEMBER_POINTER;
|
||||
|
||||
/**
|
||||
* @author ilyas
|
||||
@@ -121,7 +123,8 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
if (!InheritanceUtil.isInheritor(containingClass, CommonClassNames.JAVA_UTIL_MAP)) continue;
|
||||
final String name = containingClass.getQualifiedName();
|
||||
if (name != null && name.startsWith("java.")) continue;
|
||||
if (containingClass.getLanguage() != GroovyFileType.GROOVY_LANGUAGE && !InheritanceUtil.isInheritor(containingClass, GroovyCommonClassNames.DEFAULT_BASE_CLASS_NAME)) {
|
||||
if (containingClass.getLanguage() != GroovyFileType.GROOVY_LANGUAGE &&
|
||||
!InheritanceUtil.isInheritor(containingClass, GroovyCommonClassNames.DEFAULT_BASE_CLASS_NAME)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -174,7 +177,8 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
String[] accessorNames = isLValue ? GroovyPropertyUtils.suggestSettersName(name) : GroovyPropertyUtils.suggestGettersName(name);
|
||||
List<GroovyResolveResult> accessorResults = new ArrayList<GroovyResolveResult>();
|
||||
for (String accessorName : accessorNames) {
|
||||
AccessorResolverProcessor accessorResolver = new AccessorResolverProcessor(accessorName, name, this, !isLValue, false, getThisType(), getTypeArguments());
|
||||
AccessorResolverProcessor accessorResolver =
|
||||
new AccessorResolverProcessor(accessorName, name, this, !isLValue, false, getThisType(), getTypeArguments());
|
||||
GrReferenceResolveUtil.resolveImpl(accessorResolver, this);
|
||||
final GroovyResolveResult[] candidates = accessorResolver.getCandidates();
|
||||
|
||||
@@ -198,7 +202,6 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
}
|
||||
|
||||
|
||||
|
||||
public GroovyResolveResult[] getCallVariants(GrExpression upToArgument) {
|
||||
return resolveMethodOrProperty(true, upToArgument, true);
|
||||
}
|
||||
@@ -221,13 +224,12 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* priority: inside class C: local variable, c.method, c.property, c.getter
|
||||
* in other places: local variable, c.method, c.getter, c.property
|
||||
* in other places: local variable, c.method, c.getter, c.property
|
||||
*/
|
||||
private GroovyResolveResult[] resolveMethodOrProperty(boolean allVariants, @Nullable GrExpression upToArgument, boolean genericsMatter) {
|
||||
final String name = getReferenceName();
|
||||
@@ -260,7 +262,8 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
for (GroovyResolveResult result : shapeResults.second) {
|
||||
final ResolveState state = ResolveState.initial().
|
||||
put(PsiSubstitutor.KEY, result.getSubstitutor()).
|
||||
put(ResolverProcessor.RESOLVE_CONTEXT, result.getCurrentFileResolveContext());
|
||||
put(ResolverProcessor.RESOLVE_CONTEXT, result.getCurrentFileResolveContext()).
|
||||
put(SpreadState.SPREAD_STATE, result.getSpreadState());
|
||||
methodResolver.execute(result.getElement(), state);
|
||||
}
|
||||
|
||||
@@ -286,7 +289,8 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
|
||||
//search for getters
|
||||
for (String getterName : GroovyPropertyUtils.suggestGettersName(name)) {
|
||||
AccessorResolverProcessor getterResolver = new AccessorResolverProcessor(getterName, name, this, true, genericsMatter, getThisType(), getTypeArguments());
|
||||
AccessorResolverProcessor getterResolver =
|
||||
new AccessorResolverProcessor(getterName, name, this, true, genericsMatter, getThisType(), getTypeArguments());
|
||||
GrReferenceResolveUtil.resolveImpl(getterResolver, this);
|
||||
final GroovyResolveResult[] candidates = getterResolver.getCandidates(); //can be only one candidate
|
||||
if (!allVariants && candidates.length == 1) {
|
||||
@@ -308,12 +312,13 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
|
||||
assert upToArgument == null;
|
||||
|
||||
return CachedValuesManager.getManager(getProject()).getCachedValue(this, new CachedValueProvider<Pair<Boolean, GroovyResolveResult[]>>() {
|
||||
@Override
|
||||
public Result<Pair<Boolean, GroovyResolveResult[]>> compute() {
|
||||
return Result.create(doResolveByShape(false, null), PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
});
|
||||
return CachedValuesManager.getManager(getProject())
|
||||
.getCachedValue(this, new CachedValueProvider<Pair<Boolean, GroovyResolveResult[]>>() {
|
||||
@Override
|
||||
public Result<Pair<Boolean, GroovyResolveResult[]>> compute() {
|
||||
return Result.create(doResolveByShape(false, null), PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Pair<Boolean, GroovyResolveResult[]> doResolveByShape(boolean allVariants, @Nullable GrExpression upToArgument) {
|
||||
@@ -329,7 +334,10 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
return Pair.create(shapeProcessor.hasApplicableCandidates(), candidates);
|
||||
}
|
||||
|
||||
private MethodResolverProcessor createMethodProcessor(boolean allVariants, String name, final boolean byShape, @Nullable GrExpression upToArgument) {
|
||||
private MethodResolverProcessor createMethodProcessor(boolean allVariants,
|
||||
String name,
|
||||
final boolean byShape,
|
||||
@Nullable GrExpression upToArgument) {
|
||||
final PsiType[] argTypes = PsiUtil.getArgumentTypes(this, false, upToArgument);
|
||||
if (byShape && argTypes != null) {
|
||||
for (int i = 0; i < argTypes.length; i++) {
|
||||
@@ -436,12 +444,13 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
return CachedValuesManager.getManager(getProject()).getCachedValue(this, new CachedValueProvider<GroovyResolveResult[]>() {
|
||||
@Override
|
||||
public Result<GroovyResolveResult[]> compute() {
|
||||
GroovyResolveResult[] value = RecursionManager.doPreventingRecursion(GrReferenceExpressionImpl.this, true, new Computable<GroovyResolveResult[]>() {
|
||||
@Override
|
||||
public GroovyResolveResult[] compute() {
|
||||
return doPolyResolve(false, false);
|
||||
}
|
||||
});
|
||||
GroovyResolveResult[] value =
|
||||
RecursionManager.doPreventingRecursion(GrReferenceExpressionImpl.this, true, new Computable<GroovyResolveResult[]>() {
|
||||
@Override
|
||||
public GroovyResolveResult[] compute() {
|
||||
return doPolyResolve(false, false);
|
||||
}
|
||||
});
|
||||
if (value == null) {
|
||||
value = GroovyResolveResult.EMPTY_ARRAY;
|
||||
}
|
||||
@@ -459,8 +468,6 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
private static final OurTypesCalculator TYPES_CALCULATOR = new OurTypesCalculator();
|
||||
|
||||
public PsiType getNominalType() {
|
||||
IElementType dotType = getDotTokenType();
|
||||
|
||||
final GroovyResolveResult resolveResult = advancedResolve();
|
||||
PsiElement resolved = resolveResult.getElement();
|
||||
|
||||
@@ -471,71 +478,93 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
}
|
||||
}
|
||||
|
||||
IElementType dotType = getDotTokenType();
|
||||
if (dotType == mMEMBER_POINTER) {
|
||||
return GrClosureType.create(multiResolve(false), this);
|
||||
}
|
||||
PsiType result = null;
|
||||
JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject());
|
||||
if (resolved == null && !"class".equals(getReferenceName())) {
|
||||
resolved = getReference().resolve();
|
||||
}
|
||||
if (resolved instanceof PsiClass) {
|
||||
if (getParent() instanceof GrReferenceExpression) {
|
||||
result = facade.getElementFactory().createType((PsiClass) resolved);
|
||||
} else {
|
||||
result = TypesUtil
|
||||
.createJavaLangClassType(facade.getElementFactory().createType((PsiClass)resolved), getProject(), getResolveScope());
|
||||
}
|
||||
} else if (resolved instanceof GrVariable) {
|
||||
result = ((GrVariable) resolved).getDeclaredType();
|
||||
} else if (resolved instanceof PsiVariable) {
|
||||
result = ((PsiVariable) resolved).getType();
|
||||
} else
|
||||
if (resolved instanceof PsiMethod) {
|
||||
PsiMethod method = (PsiMethod) resolved;
|
||||
if (PropertyUtil.isSimplePropertySetter(method) && !method.getName().equals(getReferenceName())) {
|
||||
result = method.getParameterList().getParameters()[0].getType();
|
||||
} else {
|
||||
PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass != null && CommonClassNames.JAVA_LANG_OBJECT.equals(containingClass.getQualifiedName()) &&
|
||||
"getClass".equals(method.getName())) {
|
||||
result = TypesUtil.createJavaLangClassType(getQualifierType(), getProject(), getResolveScope());
|
||||
} else {
|
||||
result = PsiUtil.getSmartReturnType(method);
|
||||
}
|
||||
|
||||
PsiType result = getNominalTypeInner(resolved);
|
||||
if (result == null) return null;
|
||||
|
||||
result = TypesUtil.substituteBoxAndNormalizeType(result, resolveResult.getSubstitutor(), resolveResult.getSpreadState(), this);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiType getNominalTypeInner(PsiElement resolved) {
|
||||
if (resolved == null && !"class".equals(getReferenceName())) {
|
||||
resolved = resolve();
|
||||
}
|
||||
|
||||
if (resolved instanceof PsiClass) {
|
||||
final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory();
|
||||
if (getParent() instanceof GrReferenceExpression) {
|
||||
return factory.createType((PsiClass)resolved);
|
||||
}
|
||||
} else if (resolved instanceof GrReferenceExpression) {
|
||||
else {
|
||||
return TypesUtil.createJavaLangClassType(factory.createType((PsiClass)resolved), getProject(), getResolveScope());
|
||||
}
|
||||
}
|
||||
|
||||
if (resolved instanceof GrVariable) {
|
||||
return ((GrVariable)resolved).getDeclaredType();
|
||||
}
|
||||
|
||||
if (resolved instanceof PsiVariable) {
|
||||
return ((PsiVariable)resolved).getType();
|
||||
}
|
||||
|
||||
if (resolved instanceof PsiMethod) {
|
||||
PsiMethod method = (PsiMethod)resolved;
|
||||
if (PropertyUtil.isSimplePropertySetter(method) && !method.getName().equals(getReferenceName())) {
|
||||
return method.getParameterList().getParameters()[0].getType();
|
||||
}
|
||||
|
||||
//'class' property with explicit generic
|
||||
PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass != null &&
|
||||
CommonClassNames.JAVA_LANG_OBJECT.equals(containingClass.getQualifiedName()) &&
|
||||
"getClass".equals(method.getName())) {
|
||||
return TypesUtil.createJavaLangClassType(getQualifierType(), getProject(), getResolveScope());
|
||||
}
|
||||
|
||||
return PsiUtil.getSmartReturnType(method);
|
||||
}
|
||||
|
||||
if (resolved instanceof GrReferenceExpression) {
|
||||
PsiElement parent = resolved.getParent();
|
||||
if (parent instanceof GrAssignmentExpression) {
|
||||
GrAssignmentExpression assignment = (GrAssignmentExpression) parent;
|
||||
GrAssignmentExpression assignment = (GrAssignmentExpression)parent;
|
||||
if (resolved.equals(assignment.getLValue())) {
|
||||
GrExpression rValue = assignment.getRValue();
|
||||
if (rValue != null) {
|
||||
PsiType rType = rValue.getType();
|
||||
if (rType != null) result = rType;
|
||||
if (rType != null) {
|
||||
return rType;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (resolved == null) {
|
||||
GrExpression qualifier = getQualifierExpression();
|
||||
|
||||
if (resolved == null) {
|
||||
if ("class".equals(getReferenceName())) {
|
||||
result = TypesUtil.createJavaLangClassType(getQualifierType(), getProject(), getResolveScope());
|
||||
return TypesUtil.createJavaLangClassType(getQualifierType(), getProject(), getResolveScope());
|
||||
}
|
||||
else {
|
||||
if (qualifier != null) {
|
||||
PsiType qType = qualifier.getType();
|
||||
if (qType instanceof PsiClassType) {
|
||||
PsiClassType.ClassResolveResult qResult = ((PsiClassType)qType).resolveGenerics();
|
||||
PsiClass clazz = qResult.getElement();
|
||||
if (clazz != null) {
|
||||
PsiClass mapClass = facade.findClass(CommonClassNames.JAVA_UTIL_MAP, getResolveScope());
|
||||
if (mapClass != null && mapClass.getTypeParameters().length == 2) {
|
||||
PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(mapClass, clazz, qResult.getSubstitutor());
|
||||
if (substitutor != null) {
|
||||
result = TypeConversionUtil.erasure(substitutor.substitute(mapClass.getTypeParameters()[1]));
|
||||
}
|
||||
|
||||
//map access
|
||||
GrExpression qualifier = getQualifierExpression();
|
||||
if (qualifier != null) {
|
||||
PsiType qType = qualifier.getType();
|
||||
if (qType instanceof PsiClassType) {
|
||||
PsiClassType.ClassResolveResult qResult = ((PsiClassType)qType).resolveGenerics();
|
||||
PsiClass clazz = qResult.getElement();
|
||||
if (clazz != null) {
|
||||
PsiClass mapClass = JavaPsiFacade.getInstance(getProject()).findClass(CommonClassNames.JAVA_UTIL_MAP, getResolveScope());
|
||||
if (mapClass != null && mapClass.getTypeParameters().length == 2) {
|
||||
PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(mapClass, clazz, qResult.getSubstitutor());
|
||||
if (substitutor != null) {
|
||||
return TypeConversionUtil.erasure(substitutor.substitute(mapClass.getTypeParameters()[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -543,14 +572,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
}
|
||||
}
|
||||
|
||||
if (result != null) {
|
||||
result = TypesUtil.substituteBoxAndNormalizeType(result, resolveResult.getSubstitutor(), this);
|
||||
}
|
||||
if (dotType != mSPREAD_DOT) {
|
||||
return result;
|
||||
} else {
|
||||
return ResolveUtil.getListTypeForSpreadOperator(this, result);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -588,7 +610,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
if (!resolved.isValid()) {
|
||||
throw new AssertionError("Invalid target of a valid reference");
|
||||
}
|
||||
return ((GrVariable) resolved).getTypeGroovy();
|
||||
return ((GrVariable)resolved).getTypeGroovy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -598,7 +620,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
if (nominal == null) return inferred;
|
||||
if (!TypeConversionUtil.isAssignable(nominal, inferred, false)) {
|
||||
final PsiElement resolved = refExpr.resolve();
|
||||
if (resolved instanceof GrVariable && ((GrVariable) resolved).getTypeElementGroovy() != null) {
|
||||
if (resolved instanceof GrVariable && ((GrVariable)resolved).getTypeElementGroovy() != null) {
|
||||
return nominal; //see GRVY-487
|
||||
}
|
||||
}
|
||||
@@ -650,7 +672,8 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
return results;
|
||||
default:
|
||||
return GroovyResolveResult.EMPTY_ARRAY;
|
||||
} }
|
||||
}
|
||||
}
|
||||
|
||||
private PsiType getThisType() {
|
||||
GrExpression qualifier = getQualifierExpression();
|
||||
@@ -755,13 +778,13 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
|
||||
public GroovyResolveResult advancedResolve() {
|
||||
ResolveResult[] results = ResolveCache.getInstance(getProject()).resolveWithCaching(this, POLY_RESOLVER, true, false);
|
||||
return results.length == 1 ? (GroovyResolveResult) results[0] : GroovyResolveResult.EMPTY_RESULT;
|
||||
return results.length == 1 ? (GroovyResolveResult)results[0] : GroovyResolveResult.EMPTY_RESULT;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public GroovyResolveResult[] multiResolve(boolean incomplete) { //incomplete means we do not take arguments into consideration
|
||||
final ResolveResult[] results = ResolveCache.getInstance(getProject()).resolveWithCaching(this, POLY_RESOLVER, true, incomplete);
|
||||
return results.length == 0 ? GroovyResolveResult.EMPTY_ARRAY : (GroovyResolveResult[])results;
|
||||
return results.length == 0 ? GroovyResolveResult.EMPTY_ARRAY : (GroovyResolveResult[])results;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+55
-51
@@ -18,9 +18,13 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.SpreadState;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrThisReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
|
||||
@@ -39,10 +43,11 @@ import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mSPREAD_D
|
||||
* @author Medvedev Max
|
||||
*/
|
||||
public class GrReferenceResolveUtil {
|
||||
|
||||
private GrReferenceResolveUtil() {
|
||||
}
|
||||
|
||||
public static boolean resolveImpl(ResolverProcessor processor, GrReferenceExpression place) {
|
||||
static boolean resolveImpl(ResolverProcessor processor, GrReferenceExpression place) {
|
||||
GrExpression qualifier = place.getQualifier();
|
||||
if (qualifier == null) {
|
||||
if (processor instanceof MethodResolverProcessor || processor instanceof CompletionProcessor) {
|
||||
@@ -62,7 +67,14 @@ public class GrReferenceResolveUtil {
|
||||
}
|
||||
else {
|
||||
if (place.getDotTokenType() == mSPREAD_DOT) {
|
||||
if (!processQualifierForSpreadDot(processor, qualifier, place)) return false;
|
||||
final PsiType qtype = qualifier.getType();
|
||||
final PsiType componentType = getComponentTypeForSpreadDot(qtype, place);
|
||||
if (componentType != null) {
|
||||
final ResolveState state = ResolveState.initial()
|
||||
.put(ResolverProcessor.RESOLVE_CONTEXT, qualifier)
|
||||
.put(SpreadState.SPREAD_STATE, SpreadState.create(qtype, null));
|
||||
if (!processQualifierType(processor, componentType, state, place)) return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!processQualifier(processor, qualifier, place)) return false;
|
||||
@@ -88,10 +100,10 @@ public class GrReferenceResolveUtil {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean processIfJavaLangClass(ResolverProcessor processor,
|
||||
private static boolean processIfJavaLangClass(ResolverProcessor processor,
|
||||
PsiType type,
|
||||
GroovyPsiElement resolveContext,
|
||||
GroovyPsiElement place) {
|
||||
GrReferenceExpression place) {
|
||||
if (!(type instanceof PsiClassType)) return true;
|
||||
|
||||
final PsiClass psiClass = ((PsiClassType)type).resolve();
|
||||
@@ -100,70 +112,60 @@ public class GrReferenceResolveUtil {
|
||||
final PsiType[] params = ((PsiClassType)type).getParameters();
|
||||
if (params.length != 1) return true;
|
||||
|
||||
if (!processClassQualifierType(processor, params[0], resolveContext, place)) return false;
|
||||
if (!processQualifierType(processor, params[0], ResolveState.initial().put(ResolverProcessor.RESOLVE_CONTEXT, resolveContext), place)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean processQualifierForSpreadDot(ResolverProcessor processor, GrExpression qualifier, GroovyPsiElement place) {
|
||||
PsiType qualifierType = qualifier.getType();
|
||||
|
||||
|
||||
@Nullable
|
||||
private static PsiType getComponentTypeForSpreadDot(@Nullable PsiType qualifierType, @NotNull GroovyPsiElement place) {
|
||||
if (qualifierType instanceof PsiArrayType) {
|
||||
if (!processClassQualifierType(processor, ((PsiArrayType)qualifierType).getComponentType(), qualifier, place)) return false;
|
||||
return true;
|
||||
return ((PsiArrayType)qualifierType).getComponentType();
|
||||
}
|
||||
|
||||
|
||||
//process for collections
|
||||
if (!(qualifierType instanceof PsiClassType)) return true;
|
||||
if (!(qualifierType instanceof PsiClassType)) return null;
|
||||
|
||||
PsiClassType.ClassResolveResult result = ((PsiClassType)qualifierType).resolveGenerics();
|
||||
PsiClass clazz = result.getElement();
|
||||
if (clazz == null) return true;
|
||||
if (clazz == null) return null;
|
||||
|
||||
PsiClass collection = GroovyPsiManager.getInstance(place.getProject())
|
||||
.findClassWithCache(CommonClassNames.JAVA_UTIL_COLLECTION, place.getResolveScope());
|
||||
if (collection == null || collection.getTypeParameters().length != 1) return true;
|
||||
PsiClass collection = GroovyPsiManager.getInstance(place.getProject()).findClassWithCache(CommonClassNames.JAVA_UTIL_COLLECTION,
|
||||
place.getResolveScope());
|
||||
if (collection == null || collection.getTypeParameters().length != 1) return null;
|
||||
|
||||
PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(collection, clazz, result.getSubstitutor());
|
||||
if (substitutor == null) return true;
|
||||
if (substitutor == null) return null;
|
||||
|
||||
PsiType componentType = substitutor.substitute(collection.getTypeParameters()[0]);
|
||||
if (componentType == null) return true;
|
||||
|
||||
if (!processClassQualifierType(processor, componentType, qualifier, place)) return false;
|
||||
return true;
|
||||
return substitutor.substitute(collection.getTypeParameters()[0]);
|
||||
}
|
||||
|
||||
public static boolean processQualifier(PsiScopeProcessor processor, GrExpression qualifier, GroovyPsiElement place) {
|
||||
public static boolean processQualifier(PsiScopeProcessor processor, GrExpression qualifier, GrReferenceExpression place) {
|
||||
PsiType qualifierType = qualifier.getType();
|
||||
ResolveState state = ResolveState.initial().put(ResolverProcessor.RESOLVE_CONTEXT, qualifier);
|
||||
if (qualifierType == null) {
|
||||
if (qualifier instanceof GrReferenceExpression) {
|
||||
PsiElement resolved = ((GrReferenceExpression)qualifier).resolve();
|
||||
if (resolved instanceof PsiPackage) {
|
||||
final ResolveState state = ResolveState.initial().put(ResolverProcessor.RESOLVE_CONTEXT, qualifier);
|
||||
if (!resolved.processDeclarations(processor, state, null, place)) return false;
|
||||
}
|
||||
else {
|
||||
qualifierType = TypesUtil.getJavaLangObject(place);
|
||||
if (!processClassQualifierType(processor, qualifierType, qualifier, place)) return false;
|
||||
if (!processQualifierType(processor, qualifierType, state, place)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (qualifierType instanceof PsiIntersectionType) {
|
||||
for (PsiType conjunct : ((PsiIntersectionType)qualifierType).getConjuncts()) {
|
||||
if (!processClassQualifierType(processor, conjunct, qualifier, place)) return false;
|
||||
if (!processQualifierType(processor, conjunct, state, place)) return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!processClassQualifierType(processor, qualifierType, qualifier, place)) return false;
|
||||
if (!processQualifierType(processor, qualifierType, state, place)) return false;
|
||||
if (qualifier instanceof GrReferenceExpression) {
|
||||
PsiElement resolved = ((GrReferenceExpression)qualifier).resolve();
|
||||
if (resolved instanceof PsiClass) { //omitted .class
|
||||
PsiClass javaLangClass = PsiUtil.getJavaLangClass(resolved, place.getResolveScope());
|
||||
if (javaLangClass != null) {
|
||||
ResolveState state = ResolveState.initial();
|
||||
PsiTypeParameter[] typeParameters = javaLangClass.getTypeParameters();
|
||||
PsiSubstitutor substitutor = state.get(PsiSubstitutor.KEY);
|
||||
if (substitutor == null) substitutor = PsiSubstitutor.EMPTY;
|
||||
@@ -172,8 +174,7 @@ public class GrReferenceResolveUtil {
|
||||
state = state.put(PsiSubstitutor.KEY, substitutor);
|
||||
}
|
||||
if (!javaLangClass.processDeclarations(processor, state, null, place)) return false;
|
||||
PsiType javaLangClassType =
|
||||
JavaPsiFacade.getInstance(place.getProject()).getElementFactory().createType(javaLangClass, substitutor);
|
||||
PsiType javaLangClassType = TypesUtil.createJavaLangClassType(qualifierType, place.getProject(), place.getResolveScope());
|
||||
if (!ResolveUtil.processNonCodeMembers(javaLangClassType, processor, place, state)) return false;
|
||||
}
|
||||
}
|
||||
@@ -183,39 +184,42 @@ public class GrReferenceResolveUtil {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean processClassQualifierType(PsiScopeProcessor processor,
|
||||
PsiType qualifierType,
|
||||
GroovyPsiElement resolveContext,
|
||||
GroovyPsiElement place) {
|
||||
final ResolveState state;
|
||||
if (qualifierType instanceof PsiDisjunctionType) {
|
||||
qualifierType = ((PsiDisjunctionType)qualifierType).getLeastUpperBound();
|
||||
private static boolean processQualifierType(final PsiScopeProcessor processor,
|
||||
final PsiType originalQualifierType,
|
||||
final ResolveState state,
|
||||
final GrReferenceExpression place) {
|
||||
PsiType qualifierType = originalQualifierType instanceof PsiDisjunctionType
|
||||
? ((PsiDisjunctionType)originalQualifierType).getLeastUpperBound()
|
||||
: originalQualifierType;
|
||||
|
||||
if (qualifierType instanceof PsiIntersectionType) {
|
||||
for (PsiType conjunct : ((PsiIntersectionType)qualifierType).getConjuncts()) {
|
||||
if (!processQualifierType(processor, conjunct, state, place)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (qualifierType instanceof PsiClassType) {
|
||||
PsiClassType.ClassResolveResult qualifierResult = ((PsiClassType)qualifierType).resolveGenerics();
|
||||
PsiClass qualifierClass = qualifierResult.getElement();
|
||||
state = ResolveState.initial().put(PsiSubstitutor.KEY, qualifierResult.getSubstitutor())
|
||||
.put(ResolverProcessor.RESOLVE_CONTEXT, resolveContext);
|
||||
if (qualifierClass != null) {
|
||||
if (!qualifierClass.processDeclarations(processor, state, null, place)) return false;
|
||||
if (!qualifierClass.processDeclarations(processor, state.put(PsiSubstitutor.KEY, qualifierResult.getSubstitutor()), null, place)) return false;
|
||||
}
|
||||
}
|
||||
else if (qualifierType instanceof PsiArrayType) {
|
||||
final GrTypeDefinition arrayClass = GroovyPsiManager.getInstance(place.getProject()).getArrayClass();
|
||||
state = ResolveState.initial();
|
||||
if (!arrayClass.processDeclarations(processor, state, null, place)) return false;
|
||||
}
|
||||
else if (qualifierType instanceof PsiIntersectionType) {
|
||||
for (PsiType conjunct : ((PsiIntersectionType)qualifierType).getConjuncts()) {
|
||||
if (!processClassQualifierType(processor, conjunct, resolveContext, place)) return false;
|
||||
|
||||
if (!(place.getParent() instanceof GrMethodCall)) {
|
||||
final PsiType componentType = getComponentTypeForSpreadDot(qualifierType, place);
|
||||
if (componentType != null) {
|
||||
final SpreadState spreadState = state.get(SpreadState.SPREAD_STATE);
|
||||
processQualifierType(processor, componentType, state.put(SpreadState.SPREAD_STATE, SpreadState.create(qualifierType, spreadState)), place);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
state = ResolveState.initial();
|
||||
}
|
||||
|
||||
if (!ResolveUtil.processCategoryMembers(place, processor)) return false;
|
||||
if (!ResolveUtil.processCategoryMembers(place, processor, state)) return false;
|
||||
if (!ResolveUtil.processNonCodeMembers(qualifierType, processor, place, state)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
+49
-2
@@ -35,6 +35,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrTypeConverter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.SpreadState;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignature;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression;
|
||||
@@ -688,14 +689,16 @@ public class TypesUtil {
|
||||
@Nullable
|
||||
public static PsiType substituteBoxAndNormalizeType(@Nullable PsiType type,
|
||||
@NotNull PsiSubstitutor substitutor,
|
||||
@NotNull GrExpression expression) {
|
||||
@Nullable SpreadState state, @NotNull GrExpression expression) {
|
||||
if (type == null) return null;
|
||||
GlobalSearchScope resolveScope = expression.getResolveScope();
|
||||
PsiManager manager = expression.getManager();
|
||||
type = substitutor.substitute(type);
|
||||
type = boxPrimitiveType(type, manager, resolveScope);
|
||||
if (type == null) return null;
|
||||
return PsiImplUtil.normalizeWildcardTypeByPosition(type, expression);
|
||||
type = PsiImplUtil.normalizeWildcardTypeByPosition(type, expression);
|
||||
type = SpreadState.apply(type, state, expression.getProject());
|
||||
return type;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -705,4 +708,48 @@ public class TypesUtil {
|
||||
if (containerType instanceof PsiArrayType) return ((PsiArrayType)containerType).getComponentType();
|
||||
return PsiUtil.extractIterableTypeParameter(containerType, false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiClassType createSimilarCollection(PsiType collection, Project project, PsiType... itemType) {
|
||||
if (InheritanceUtil.isInheritor(collection, "java.util.SortedSet")) {
|
||||
return createCollection(project, "java.util.SortedSet", itemType);
|
||||
}
|
||||
if (InheritanceUtil.isInheritor(collection, "java.util.LinkedHashSet")) {
|
||||
return createCollection(project, "java.util.LinkedHashSet", itemType);
|
||||
}
|
||||
if (InheritanceUtil.isInheritor(collection, "java.util.Set")) {
|
||||
return createCollection(project, "java.util.HashSet", itemType);
|
||||
}
|
||||
if (InheritanceUtil.isInheritor(collection, "java.util.LinkedList")) {
|
||||
return createCollection(project, "java.util.LInkedList", itemType);
|
||||
}
|
||||
if (InheritanceUtil.isInheritor(collection, "java.util.Stack")) {
|
||||
return createCollection(project, "java.util.Stack", itemType);
|
||||
}
|
||||
if (InheritanceUtil.isInheritor(collection, "java.util.Vector")) {
|
||||
return createCollection(project, "java.util.Vector", itemType);
|
||||
}
|
||||
if (InheritanceUtil.isInheritor(collection, "java.util.List")) {
|
||||
return createCollection(project, "java.util.ArrayList", itemType);
|
||||
}
|
||||
if (InheritanceUtil.isInheritor(collection, "java.util.Queue")) {
|
||||
return createCollection(project, "java.util.LinkedList", itemType);
|
||||
}
|
||||
|
||||
return createCollection(project, "java.util.ArrayList", itemType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiClassType createCollection(Project project, String collectionName, PsiType... item) {
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
||||
PsiClass collection =
|
||||
JavaPsiFacade.getInstance(project).findClass(collectionName, GlobalSearchScope.allScope(project));
|
||||
if (collection == null) return null;
|
||||
|
||||
PsiTypeParameter[] parameters = collection.getTypeParameters();
|
||||
if (parameters.length != 1) return null;
|
||||
|
||||
return factory.createType(collection, item);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+36
-29
@@ -21,7 +21,6 @@ import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.hash.HashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
|
||||
@@ -54,48 +53,56 @@ public class DefaultCallExpressionTypeCalculator extends GrCallExpressionTypeCal
|
||||
PsiManager manager = callExpression.getManager();
|
||||
PsiType result = null;
|
||||
for (GroovyResolveResult resolveResult : resolveResults) {
|
||||
PsiElement resolved = resolveResult.getElement();
|
||||
PsiType returnType = null;
|
||||
if (resolved instanceof PsiMethod) {
|
||||
PsiMethod method = (PsiMethod) resolved;
|
||||
if (resolveResult.isInvokedOnProperty()) {
|
||||
final PsiType propertyType = PsiUtil.getSmartReturnType(method);
|
||||
returnType = extractReturnTypeFromType(propertyType, true, callExpression);
|
||||
} else {
|
||||
returnType = getClosureMethodsReturnType(callExpression, refExpr, method);
|
||||
if (returnType == null) {
|
||||
returnType = PsiUtil.getSmartReturnType(method);
|
||||
}
|
||||
}
|
||||
} else if (resolved instanceof GrVariable) {
|
||||
PsiType refType = refExpr.getType();
|
||||
final PsiType type = refType == null ? ((GrVariable) resolved).getTypeGroovy() : refType;
|
||||
returnType = extractReturnTypeFromType(type, false, callExpression);
|
||||
}
|
||||
PsiType returnType = calculateReturnTypeInner(callExpression, refExpr, resolveResult);
|
||||
|
||||
if (returnType == null) return null;
|
||||
if (!(returnType instanceof GrLiteralClassType)) {
|
||||
returnType = TypesUtil.substituteBoxAndNormalizeType(returnType, resolveResult.getSubstitutor(), callExpression);
|
||||
returnType = TypesUtil.substituteBoxAndNormalizeType(returnType, resolveResult.getSubstitutor(), resolveResult.getSpreadState(), callExpression);
|
||||
LOG.assertTrue(returnType != null);
|
||||
}
|
||||
|
||||
if (result == null || returnType.isAssignableFrom(result)) result = returnType;
|
||||
else if (!result.isAssignableFrom(returnType))
|
||||
if (result == null || returnType.isAssignableFrom(result)) {
|
||||
result = returnType;
|
||||
}
|
||||
else if (!result.isAssignableFrom(returnType)) {
|
||||
result = TypesUtil.getLeastUpperBound(result, returnType, manager);
|
||||
}
|
||||
}
|
||||
|
||||
if (result == null) return null;
|
||||
|
||||
if (refExpr.getDotTokenType() != GroovyTokenTypes.mSPREAD_DOT) {
|
||||
return result;
|
||||
} else {
|
||||
return ResolveUtil.getListTypeForSpreadOperator(refExpr, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return extractReturnTypeFromType(invoked.getType(), false, callExpression);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiType calculateReturnTypeInner(GrMethodCall callExpression,
|
||||
GrReferenceExpression refExpr,
|
||||
GroovyResolveResult resolveResult) {
|
||||
PsiElement resolved = resolveResult.getElement();
|
||||
PsiType returnType = null;
|
||||
if (resolved instanceof PsiMethod) {
|
||||
PsiMethod method = (PsiMethod)resolved;
|
||||
if (resolveResult.isInvokedOnProperty()) {
|
||||
final PsiType propertyType = PsiUtil.getSmartReturnType(method);
|
||||
returnType = extractReturnTypeFromType(propertyType, true, callExpression);
|
||||
}
|
||||
else {
|
||||
returnType = getClosureMethodsReturnType(callExpression, refExpr, method);
|
||||
if (returnType == null) {
|
||||
returnType = PsiUtil.getSmartReturnType(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (resolved instanceof GrVariable) {
|
||||
PsiType refType = refExpr.getType();
|
||||
final PsiType type = refType == null ? ((GrVariable)resolved).getTypeGroovy() : refType;
|
||||
returnType = extractReturnTypeFromType(type, false, callExpression);
|
||||
}
|
||||
return returnType;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiType extractReturnTypeFromType(PsiType type, boolean returnTypeIfFail, GrMethodCall callExpression) {
|
||||
PsiType returnType = returnTypeIfFail ? type: null;
|
||||
|
||||
+2
-47
@@ -15,10 +15,7 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.path;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.containers.hash.HashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -28,6 +25,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethod
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.GrCallExpressionTypeCalculator;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
|
||||
|
||||
@@ -82,7 +80,7 @@ public class GrDGMTypeCalculator extends GrCallExpressionTypeCalculator {
|
||||
itemType = iitype;
|
||||
}
|
||||
}
|
||||
return createSimilarCollection(type, callExpression.getProject(), itemType);
|
||||
return TypesUtil.createSimilarCollection(type, callExpression.getProject(), itemType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,49 +98,6 @@ public class GrDGMTypeCalculator extends GrCallExpressionTypeCalculator {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiType createSimilarCollection(PsiType collection, Project project, PsiType... itemType) {
|
||||
if (InheritanceUtil.isInheritor(collection, "java.util.SortedSet")) {
|
||||
return createCollection(project, "java.util.SortedSet", itemType);
|
||||
}
|
||||
if (InheritanceUtil.isInheritor(collection, "java.util.LinkedHashSet")) {
|
||||
return createCollection(project, "java.util.LinkedHashSet", itemType);
|
||||
}
|
||||
if (InheritanceUtil.isInheritor(collection, "java.util.Set")) {
|
||||
return createCollection(project, "java.util.HashSet", itemType);
|
||||
}
|
||||
if (InheritanceUtil.isInheritor(collection, "java.util.LinkedList")) {
|
||||
return createCollection(project, "java.util.LInkedList", itemType);
|
||||
}
|
||||
if (InheritanceUtil.isInheritor(collection, "java.util.Stack")) {
|
||||
return createCollection(project, "java.util.Stack", itemType);
|
||||
}
|
||||
if (InheritanceUtil.isInheritor(collection, "java.util.Vector")) {
|
||||
return createCollection(project, "java.util.Vector", itemType);
|
||||
}
|
||||
if (InheritanceUtil.isInheritor(collection, "java.util.List")) {
|
||||
return createCollection(project, "java.util.ArrayList", itemType);
|
||||
}
|
||||
if (InheritanceUtil.isInheritor(collection, "java.util.Queue")) {
|
||||
return createCollection(project, "java.util.LinkedList", itemType);
|
||||
}
|
||||
|
||||
return createCollection(project, "java.util.ArrayList", itemType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiType createCollection(Project project, String collectionName, PsiType... item) {
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
||||
PsiClass collection =
|
||||
JavaPsiFacade.getInstance(project).findClass(collectionName, GlobalSearchScope.allScope(project));
|
||||
if (collection == null) return null;
|
||||
|
||||
PsiTypeParameter[] parameters = collection.getTypeParameters();
|
||||
if (parameters.length != 1) return null;
|
||||
|
||||
return factory.createType(collection, item);
|
||||
}
|
||||
|
||||
private static boolean isSimilarCollectionReturner(PsiMethod resolved) {
|
||||
PsiParameter[] params = resolved.getParameterList().getParameters();
|
||||
if (params.length == 0) return false;
|
||||
|
||||
+1
-1
@@ -270,7 +270,7 @@ public class GrIndexPropertyImpl extends GrExpressionImpl implements GrIndexProp
|
||||
PsiParameter[] parameters = ((PsiMethod)element).getParameterList().getParameters();
|
||||
if (parameters.length > 1) {
|
||||
PsiParameter last = parameters[parameters.length - 1];
|
||||
return TypesUtil.substituteBoxAndNormalizeType(last.getType(), candidate.getSubstitutor(), this);
|
||||
return TypesUtil.substituteBoxAndNormalizeType(last.getType(), candidate.getSubstitutor(), candidate.getSpreadState(), this);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
+1
-3
@@ -102,8 +102,7 @@ public class GrEnumConstantImpl extends GrFieldImpl implements GrEnumConstant {
|
||||
}
|
||||
|
||||
public GroovyResolveResult[] multiResolveClass() {
|
||||
final PsiClass psiClass = getContainingClass();
|
||||
GroovyResolveResult result = new GroovyResolveResultImpl(psiClass, this, PsiSubstitutor.EMPTY, true, true);
|
||||
GroovyResolveResult result = new GroovyResolveResultImpl(getContainingClass(), this, null, PsiSubstitutor.EMPTY, true, true);
|
||||
return new GroovyResolveResult[]{result};
|
||||
}
|
||||
|
||||
@@ -135,7 +134,6 @@ public class GrEnumConstantImpl extends GrFieldImpl implements GrEnumConstant {
|
||||
public GrExpression[] getExpressionArguments() {
|
||||
final GrArgumentList argumentList = getArgumentList();
|
||||
return argumentList == null ? GrExpression.EMPTY_ARRAY : argumentList.getExpressionArguments();
|
||||
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+1
-1
@@ -376,7 +376,7 @@ public class GrCodeReferenceElementImpl extends GrReferenceElementImpl<GrCodeRef
|
||||
final PsiSubstitutor substitutor = result.getSubstitutor();
|
||||
final PsiSubstitutor newSubstitutor = substitutor.putAll((PsiClass) element, args);
|
||||
GroovyPsiElement context = result.getCurrentFileResolveContext();
|
||||
GroovyResolveResultImpl newResult = new GroovyResolveResultImpl(element, context, newSubstitutor, result.isAccessible(), result.isStaticsOK());
|
||||
GroovyResolveResultImpl newResult = new GroovyResolveResultImpl(element, context, null, newSubstitutor, result.isAccessible(), result.isStaticsOK());
|
||||
results[i] = newResult;
|
||||
if (context instanceof GrImportStatement) {
|
||||
imported.add(newResult);
|
||||
|
||||
@@ -62,7 +62,7 @@ public class GdkMethodUtil {
|
||||
private GdkMethodUtil() {
|
||||
}
|
||||
|
||||
public static boolean categoryIteration(GrClosableBlock place, final PsiScopeProcessor processor) {
|
||||
public static boolean categoryIteration(GrClosableBlock place, final PsiScopeProcessor processor, ResolveState state) {
|
||||
final ClassHint classHint = processor.getHint(ClassHint.KEY);
|
||||
if (classHint != null && !classHint.shouldProcess(ClassHint.ResolveKind.METHOD)) return true;
|
||||
|
||||
@@ -79,11 +79,12 @@ public class GdkMethodUtil {
|
||||
|
||||
if (!(call.resolveMethod() instanceof GrGdkMethod)) return true;
|
||||
|
||||
state = state.put(ResolverProcessor.RESOLVE_CONTEXT, call);
|
||||
for (GrExpression arg : args) {
|
||||
if (arg instanceof GrReferenceExpression) {
|
||||
final PsiElement resolved = ((GrReferenceExpression)arg).resolve();
|
||||
if (resolved instanceof PsiClass) {
|
||||
if (!processCategoryMethods(place, processor, call, (PsiClass)resolved)) return false;
|
||||
if (!processCategoryMethods(place, processor, state, (PsiClass)resolved)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,7 +101,7 @@ public class GdkMethodUtil {
|
||||
*/
|
||||
public static boolean processCategoryMethods(final GroovyPsiElement place,
|
||||
final PsiScopeProcessor processor,
|
||||
@Nullable GroovyPsiElement resolveContext,
|
||||
@NotNull ResolveState state,
|
||||
@NotNull PsiClass categoryClass) {
|
||||
final DelegatingScopeProcessor delegate = new DelegatingScopeProcessor(processor) {
|
||||
@Override
|
||||
@@ -114,18 +115,17 @@ public class GdkMethodUtil {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
final ResolveState state = ResolveState.initial().put(ResolverProcessor.RESOLVE_CONTEXT, resolveContext);
|
||||
return categoryClass.processDeclarations(delegate, state, null, place);
|
||||
}
|
||||
|
||||
public static boolean withIteration(GrClosableBlock block, final PsiScopeProcessor processor, GroovyPsiElement place) {
|
||||
public static boolean withIteration(GrClosableBlock block, final PsiScopeProcessor processor) {
|
||||
GrMethodCall call = checkMethodCall(block, WITH);
|
||||
if (call == null) return true;
|
||||
final GrExpression invoked = call.getInvokedExpression();
|
||||
LOG.assertTrue(invoked instanceof GrReferenceExpression);
|
||||
final GrExpression qualifier = ((GrReferenceExpression)invoked).getQualifier();
|
||||
if (qualifier == null) return true;
|
||||
if (!GrReferenceResolveUtil.processQualifier(processor, qualifier, place)) return false;
|
||||
if (!GrReferenceResolveUtil.processQualifier(processor, qualifier, (GrReferenceExpression)invoked)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -937,7 +937,7 @@ public class PsiUtil {
|
||||
|
||||
final GroovyResolveResult grResult = resolveResult instanceof GroovyResolveResult
|
||||
? (GroovyResolveResult)resolveResult
|
||||
: new GroovyResolveResultImpl(psiClass, context, substitutor, true, true);
|
||||
: new GroovyResolveResultImpl(psiClass, context, null, substitutor, true, true);
|
||||
return getConstructorCandidates(context, new GroovyResolveResult[]{grResult}, argTypes);
|
||||
}
|
||||
|
||||
|
||||
@@ -101,20 +101,20 @@ public class ResolveUtil {
|
||||
}
|
||||
if (doProcessNonCodeMembers) {
|
||||
if (run instanceof GrTypeDefinition) {
|
||||
if (!processNonCodeMembers(factory.createType(((GrTypeDefinition)run)), processor, place)) return false;
|
||||
if (!processNonCodeMembers(factory.createType(((GrTypeDefinition)run)), processor, place, ResolveState.initial())) return false;
|
||||
}
|
||||
else if ((run instanceof GroovyFileBase) && ((GroovyFileBase)run).isScript()) {
|
||||
final PsiClass psiClass = ((GroovyFileBase)run).getScriptClass();
|
||||
if (psiClass != null) {
|
||||
if (!processNonCodeMembers(factory.createType(psiClass), processor, place)) return false;
|
||||
if (!processNonCodeMembers(factory.createType(psiClass), processor, place, ResolveState.initial())) return false;
|
||||
}
|
||||
}
|
||||
else if (run instanceof GrClosableBlock) {
|
||||
PsiClass superClass = getLiteralSuperClass((GrClosableBlock)run);
|
||||
if (superClass != null && !superClass.processDeclarations(processor, ResolveState.initial(), null, place)) return false;
|
||||
|
||||
if (!GdkMethodUtil.categoryIteration((GrClosableBlock)run, processor)) return false;
|
||||
if (!GdkMethodUtil.withIteration((GrClosableBlock)run, processor, place)) return false;
|
||||
if (!GdkMethodUtil.categoryIteration((GrClosableBlock)run, processor, ResolveState.initial())) return false;
|
||||
if (!GdkMethodUtil.withIteration((GrClosableBlock)run, processor)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,12 +128,12 @@ public class ResolveUtil {
|
||||
|
||||
public static boolean processChildren(PsiElement element,
|
||||
PsiScopeProcessor processor,
|
||||
ResolveState substitutor,
|
||||
ResolveState state,
|
||||
PsiElement lastParent,
|
||||
PsiElement place) {
|
||||
PsiElement run = lastParent == null ? element.getLastChild() : lastParent.getPrevSibling();
|
||||
while (run != null) {
|
||||
if (!run.processDeclarations(processor, substitutor, null, place)) return false;
|
||||
if (!run.processDeclarations(processor, state, null, place)) return false;
|
||||
run = run.getPrevSibling();
|
||||
}
|
||||
|
||||
@@ -175,16 +175,10 @@ public class ResolveUtil {
|
||||
}
|
||||
}
|
||||
if (!processNonCodeMembers(type, processor, place, state)) return false;
|
||||
if (!processCategoryMembers(place, processor)) return false;
|
||||
if (!processCategoryMembers(place, processor, state)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean processNonCodeMembers(PsiType type,
|
||||
PsiScopeProcessor processor,
|
||||
GroovyPsiElement place) {
|
||||
return processNonCodeMembers(type, processor, place, ResolveState.initial());
|
||||
}
|
||||
|
||||
public static boolean processNonCodeMembers(PsiType type,
|
||||
PsiScopeProcessor processor,
|
||||
GroovyPsiElement place,
|
||||
@@ -277,21 +271,6 @@ public class ResolveUtil {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiType getListTypeForSpreadOperator(GrReferenceExpression refExpr, PsiType componentType) {
|
||||
PsiClass clazz = JavaPsiFacade.getInstance(refExpr.getManager().getProject())
|
||||
.findClass(CommonClassNames.JAVA_UTIL_LIST, refExpr.getResolveScope());
|
||||
if (clazz != null) {
|
||||
PsiTypeParameter[] typeParameters = clazz.getTypeParameters();
|
||||
if (typeParameters.length == 1) {
|
||||
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY.put(typeParameters[0], componentType);
|
||||
return JavaPsiFacade.getInstance(refExpr.getProject()).getElementFactory().createType(clazz, substitutor);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static GroovyPsiElement resolveProperty(GroovyPsiElement place, String name) {
|
||||
PropertyResolverProcessor processor = new PropertyResolverProcessor(name, place);
|
||||
return resolveExistingElement(place, processor, GrVariable.class, GrReferenceExpression.class);
|
||||
@@ -384,9 +363,9 @@ public class ResolveUtil {
|
||||
return resolveLabelTargets(labelName, element, isBreak).first;
|
||||
}
|
||||
|
||||
public static boolean processCategoryMembers(GroovyPsiElement place, PsiScopeProcessor processor) {
|
||||
public static boolean processCategoryMembers(GroovyPsiElement place, PsiScopeProcessor processor, ResolveState state) {
|
||||
boolean gpp = GppTypeConverter.hasTypedContext(place);
|
||||
if (gpp && !processUseAnnotation(place, processor)) return false;
|
||||
if (gpp && !processUseAnnotation(place, processor, state)) return false;
|
||||
|
||||
boolean inCodeBlock = true;
|
||||
PsiElement run = place;
|
||||
@@ -395,14 +374,15 @@ public class ResolveUtil {
|
||||
inCodeBlock = false;
|
||||
}
|
||||
if (run instanceof GrClosableBlock) {
|
||||
if (inCodeBlock && !GdkMethodUtil.categoryIteration((GrClosableBlock)run, processor)) return false;
|
||||
if (inCodeBlock && !GdkMethodUtil.categoryIteration((GrClosableBlock)run, processor, state)) return false;
|
||||
|
||||
PsiClass superClass = getLiteralSuperClass((GrClosableBlock)run);
|
||||
if (superClass != null && !GdkMethodUtil.processCategoryMethods(((GrClosableBlock)run), processor, null, superClass)) return false;
|
||||
if (superClass != null && !GdkMethodUtil.processCategoryMethods(((GrClosableBlock)run), processor, state, superClass)) return false;
|
||||
}
|
||||
if (gpp && run instanceof GrTypeDefinition) {
|
||||
final GrTypeDefinition typeDefinition = (GrTypeDefinition)run;
|
||||
if (!GdkMethodUtil.processCategoryMethods(typeDefinition, processor, typeDefinition, typeDefinition)) return false;
|
||||
state = state.put(ResolverProcessor.RESOLVE_CONTEXT, typeDefinition);
|
||||
if (!GdkMethodUtil.processCategoryMethods(typeDefinition, processor, state, typeDefinition)) return false;
|
||||
}
|
||||
run = run.getContext();
|
||||
}
|
||||
@@ -410,13 +390,13 @@ public class ResolveUtil {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean processUseAnnotation(GroovyPsiElement place, PsiScopeProcessor processor) {
|
||||
private static boolean processUseAnnotation(GroovyPsiElement place, PsiScopeProcessor processor, ResolveState state) {
|
||||
PsiAnnotation use = AnnotatedContextFilter.findContextAnnotation(place, GroovyCommonClassNames.GROOVY_LANG_USE);
|
||||
if (use != null) {
|
||||
for (PsiElement element : PsiElementCategory.asList(use.findDeclaredAttributeValue("value"))) {
|
||||
if (element instanceof GrReferenceExpression) {
|
||||
PsiElement resolve = ((GrReferenceExpression)element).resolve();
|
||||
if (resolve instanceof PsiClass && !GdkMethodUtil.processCategoryMethods(place, processor, null, (PsiClass)resolve)) {
|
||||
if (resolve instanceof PsiClass && !GdkMethodUtil.processCategoryMethods(place, processor, state, (PsiClass)resolve)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -687,7 +667,7 @@ public class ResolveUtil {
|
||||
public static PsiType extractReturnTypeFromCandidate(GroovyResolveResult candidate, GrExpression expression, @Nullable PsiType[] args) {
|
||||
final PsiElement element = candidate.getElement();
|
||||
if (element instanceof PsiMethod && !candidate.isInvokedOnProperty()) {
|
||||
return TypesUtil.substituteBoxAndNormalizeType(getSmartReturnType((PsiMethod)element), candidate.getSubstitutor(), expression);
|
||||
return TypesUtil.substituteBoxAndNormalizeType(getSmartReturnType((PsiMethod)element), candidate.getSubstitutor(), candidate.getSpreadState(), expression);
|
||||
}
|
||||
|
||||
final PsiType type;
|
||||
@@ -703,7 +683,7 @@ public class ResolveUtil {
|
||||
if (type instanceof GrClosureType) {
|
||||
final GrSignature signature = ((GrClosureType)type).getSignature();
|
||||
PsiType returnType = GrClosureSignatureUtil.getReturnType(signature, args, expression);
|
||||
return TypesUtil.substituteBoxAndNormalizeType(returnType, candidate.getSubstitutor(), expression);
|
||||
return TypesUtil.substituteBoxAndNormalizeType(returnType, candidate.getSubstitutor(), candidate.getSpreadState(), expression);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
+3
-1
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.SpreadState;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
|
||||
@@ -78,9 +79,10 @@ public class AccessorResolverProcessor extends MethodResolverProcessor {
|
||||
}
|
||||
boolean isAccessible = isAccessible(method);
|
||||
final GroovyPsiElement resolveContext = state.get(RESOLVE_CONTEXT);
|
||||
final SpreadState spreadState = state.get(SpreadState.SPREAD_STATE);
|
||||
boolean isStaticsOK = isStaticsOK(method, resolveContext, true);
|
||||
final GroovyResolveResultImpl candidate =
|
||||
new GroovyResolveResultImpl(method, resolveContext, substitutor, isAccessible, isStaticsOK, true);
|
||||
new GroovyResolveResultImpl(method, resolveContext, spreadState, substitutor, isAccessible, isStaticsOK, true);
|
||||
if (isAccessible && isStaticsOK) {
|
||||
addCandidate(candidate);
|
||||
return method instanceof GrGdkMethod; //don't stop searching if we found only gdk method
|
||||
|
||||
+5
-2
@@ -27,6 +27,7 @@ import org.jetbrains.plugins.groovy.gpp.GppClosureParameterTypeProvider;
|
||||
import org.jetbrains.plugins.groovy.gpp.GppTypeConverter;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.SpreadState;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl;
|
||||
@@ -100,12 +101,14 @@ public class MethodResolverProcessor extends ResolverProcessor {
|
||||
}
|
||||
boolean isAccessible = isAccessible(method);
|
||||
GroovyPsiElement resolveContext = state.get(RESOLVE_CONTEXT);
|
||||
final SpreadState spreadState = state.get(SpreadState.SPREAD_STATE);
|
||||
|
||||
boolean isStaticsOK = isStaticsOK(method, resolveContext, true);
|
||||
if (!myAllVariants && isStaticsOK && isAccessible &&
|
||||
PsiUtil.isApplicable(myArgumentTypes, method, substitutor, (GroovyPsiElement)myPlace, myByShape)) {
|
||||
addCandidate(new GroovyResolveResultImpl(method, resolveContext, substitutor, isAccessible, isStaticsOK));
|
||||
addCandidate(new GroovyResolveResultImpl(method, resolveContext, spreadState, substitutor, isAccessible, isStaticsOK));
|
||||
} else {
|
||||
myInapplicableCandidates.add(new GroovyResolveResultImpl(method, resolveContext, substitutor, isAccessible, isStaticsOK));
|
||||
myInapplicableCandidates.add(new GroovyResolveResultImpl(method, resolveContext, spreadState, substitutor, isAccessible, isStaticsOK));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
+3
-1
@@ -26,6 +26,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.SpreadState;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod;
|
||||
@@ -97,8 +98,9 @@ public class ResolverProcessor implements PsiScopeProcessor, NameHint, ClassHint
|
||||
|
||||
boolean isAccessible = isAccessible(namedElement);
|
||||
final GroovyPsiElement resolveContext = state.get(RESOLVE_CONTEXT);
|
||||
final SpreadState spreadState = state.get(SpreadState.SPREAD_STATE);
|
||||
boolean isStaticsOK = isStaticsOK(namedElement, resolveContext, true);
|
||||
addCandidate(new GroovyResolveResultImpl(namedElement, resolveContext, substitutor, isAccessible, isStaticsOK));
|
||||
addCandidate(new GroovyResolveResultImpl(namedElement, resolveContext, spreadState, substitutor, isAccessible, isStaticsOK));
|
||||
return !isAccessible || !isStaticsOK;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -180,7 +180,7 @@ public class ResolveMethodTest extends GroovyResolveTestCase {
|
||||
assertTrue(type instanceof PsiClassType);
|
||||
PsiClass clazz = ((PsiClassType) type).resolve();
|
||||
assertNotNull(clazz);
|
||||
assertEquals("java.util.List", clazz.getQualifiedName());
|
||||
assertEquals("java.util.ArrayList", clazz.getQualifiedName());
|
||||
}
|
||||
|
||||
|
||||
|
||||
+51
@@ -426,6 +426,57 @@ print ma<caret>p
|
||||
''', "$JAVA_UTIL_MAP<$JAVA_LANG_STRING,$JAVA_LANG_STRING>")
|
||||
}
|
||||
|
||||
void testSpread1() {
|
||||
myFixture.addClass('''\
|
||||
class A {
|
||||
String getString() {return "a";}
|
||||
}''')
|
||||
doTest('''\
|
||||
[new A()].stri<caret>ng
|
||||
''', "$JAVA_UTIL_ARRAY_LIST<$JAVA_LANG_STRING>")
|
||||
}
|
||||
|
||||
void testSpread2() {
|
||||
|
||||
myFixture.addClass('''\
|
||||
class A {
|
||||
String getString() {return "a";}
|
||||
}''')
|
||||
doTest('''\
|
||||
class Cat {
|
||||
static getFoo(String b) {2}
|
||||
}
|
||||
use(Cat) {
|
||||
[new A()].string.fo<caret>o
|
||||
}
|
||||
''', "$JAVA_UTIL_ARRAY_LIST<$JAVA_LANG_INTEGER>")
|
||||
}
|
||||
|
||||
void testSpread3() {
|
||||
myFixture.addClass('''\
|
||||
class A {
|
||||
String getString() {return "a";}
|
||||
}''')
|
||||
doTest('''\
|
||||
[[new A()]].stri<caret>ng
|
||||
''', "$JAVA_UTIL_ARRAY_LIST<$JAVA_UTIL_ARRAY_LIST<$JAVA_LANG_STRING>>")
|
||||
}
|
||||
|
||||
void testSpread4() {
|
||||
myFixture.addClass('''\
|
||||
class A {
|
||||
String getString() {return "a";}
|
||||
}''')
|
||||
doTest('''\
|
||||
class Cat {
|
||||
static getFoo(String b) {2}
|
||||
}
|
||||
|
||||
use(Cat){
|
||||
[[new A()]].string.fo<caret>o
|
||||
}
|
||||
''', "$JAVA_UTIL_ARRAY_LIST<$JAVA_UTIL_ARRAY_LIST<$JAVA_LANG_INTEGER>>")
|
||||
}
|
||||
|
||||
private void doTest(String text, String type) {
|
||||
def file = myFixture.configureByText('_.groovy', text)
|
||||
|
||||
@@ -1050,11 +1050,9 @@ public class MethodEntry extends ClassContentsEntry implements RelatableEntry {
|
||||
return;
|
||||
}
|
||||
createAlternateValueString();
|
||||
/**
|
||||
* we don't want to check for comments in the body of the method. So reduce the alternate value string
|
||||
* to only that text up to and including the open brace. Temporarily remove the rest of the text; append
|
||||
* it again after checking for comments.
|
||||
*/
|
||||
// We don't want to check for comments in the body of the method. So reduce the alternate value string
|
||||
// to only that text up to and including the open brace. Temporarily remove the rest of the text; append
|
||||
// it again after checking for comments.
|
||||
int brace = myAlternateValue.indexOf('{');
|
||||
String temp = "";
|
||||
if (brace >= 0) {
|
||||
|
||||
@@ -361,7 +361,7 @@ public final class RearrangerSettings {
|
||||
// Level 2 methods
|
||||
|
||||
public void setGlobalCommentPattern(String globalCommentPattern) {
|
||||
this.myGlobalCommentPattern = globalCommentPattern;
|
||||
myGlobalCommentPattern = globalCommentPattern;
|
||||
}
|
||||
|
||||
// end of Level 2 methods
|
||||
@@ -384,7 +384,7 @@ public final class RearrangerSettings {
|
||||
// Level 2 methods
|
||||
|
||||
public void setOverloadedOrder(int overloadedOrder) {
|
||||
this.myOverloadedOrder = overloadedOrder;
|
||||
myOverloadedOrder = overloadedOrder;
|
||||
}
|
||||
|
||||
// end of Level 2 methods
|
||||
@@ -403,7 +403,7 @@ public final class RearrangerSettings {
|
||||
// Level 2 methods
|
||||
|
||||
public void setAskBeforeRearranging(boolean askBeforeRearranging) {
|
||||
this.myAskBeforeRearranging = askBeforeRearranging;
|
||||
myAskBeforeRearranging = askBeforeRearranging;
|
||||
}
|
||||
|
||||
public boolean isKeepGettersSettersTogether() {
|
||||
@@ -413,7 +413,7 @@ public final class RearrangerSettings {
|
||||
// Level 2 methods
|
||||
|
||||
public void setKeepGettersSettersTogether(boolean keepGettersSettersTogether) {
|
||||
this.myKeepGettersSettersTogether = keepGettersSettersTogether;
|
||||
myKeepGettersSettersTogether = keepGettersSettersTogether;
|
||||
}
|
||||
|
||||
public boolean isKeepGettersSettersWithProperty() {
|
||||
@@ -421,7 +421,7 @@ public final class RearrangerSettings {
|
||||
}
|
||||
|
||||
public void setKeepGettersSettersWithProperty(boolean keepGettersSettersWithProperty) {
|
||||
this.myKeepGettersSettersWithProperty = keepGettersSettersWithProperty;
|
||||
myKeepGettersSettersWithProperty = keepGettersSettersWithProperty;
|
||||
}
|
||||
// end of Level 2 methods
|
||||
// end of Level 1 methods
|
||||
@@ -434,7 +434,7 @@ public final class RearrangerSettings {
|
||||
// Level 2 methods
|
||||
|
||||
public void setKeepOverloadedMethodsTogether(boolean keepOverloadedMethodsTogether) {
|
||||
this.myKeepOverloadedMethodsTogether = keepOverloadedMethodsTogether;
|
||||
myKeepOverloadedMethodsTogether = keepOverloadedMethodsTogether;
|
||||
}
|
||||
|
||||
// end of Level 2 methods
|
||||
@@ -445,7 +445,7 @@ public final class RearrangerSettings {
|
||||
}
|
||||
|
||||
public void setRearrangeInnerClasses(boolean rearrangeInnerClasses) {
|
||||
this.myRearrangeInnerClasses = rearrangeInnerClasses;
|
||||
myRearrangeInnerClasses = rearrangeInnerClasses;
|
||||
}
|
||||
|
||||
// end of Level 2 methods
|
||||
@@ -459,7 +459,7 @@ public final class RearrangerSettings {
|
||||
// Level 2 methods
|
||||
|
||||
public void setRemoveBlanksInsideCodeBlocks(boolean removeBlanksInsideCodeBlocks) {
|
||||
this.myRemoveBlanksInsideCodeBlocks = removeBlanksInsideCodeBlocks;
|
||||
myRemoveBlanksInsideCodeBlocks = removeBlanksInsideCodeBlocks;
|
||||
}
|
||||
|
||||
public boolean isShowComments() {
|
||||
@@ -467,7 +467,7 @@ public final class RearrangerSettings {
|
||||
}
|
||||
|
||||
public void setShowComments(boolean showComments) {
|
||||
this.myShowComments = showComments;
|
||||
myShowComments = showComments;
|
||||
}
|
||||
|
||||
// end of Level 2 methods
|
||||
@@ -481,7 +481,7 @@ public final class RearrangerSettings {
|
||||
// Level 2 methods
|
||||
|
||||
public void setShowFields(boolean showFields) {
|
||||
this.myShowFields = showFields;
|
||||
myShowFields = showFields;
|
||||
}
|
||||
|
||||
public boolean isShowMatchedRules() {
|
||||
@@ -489,7 +489,7 @@ public final class RearrangerSettings {
|
||||
}
|
||||
|
||||
public void setShowMatchedRules(boolean showMatchedRules) {
|
||||
this.myShowMatchedRules = showMatchedRules;
|
||||
myShowMatchedRules = showMatchedRules;
|
||||
}
|
||||
|
||||
public boolean isShowParameterNames() {
|
||||
@@ -499,7 +499,7 @@ public final class RearrangerSettings {
|
||||
// Level 2 methods
|
||||
|
||||
public void setShowParameterNames(boolean showParameterNames) {
|
||||
this.myShowParameterNames = showParameterNames;
|
||||
myShowParameterNames = showParameterNames;
|
||||
}
|
||||
|
||||
// end of Level 2 methods
|
||||
@@ -513,7 +513,7 @@ public final class RearrangerSettings {
|
||||
// Level 2 methods
|
||||
|
||||
public void setShowParameterTypes(boolean showParameterTypes) {
|
||||
this.myShowParameterTypes = showParameterTypes;
|
||||
myShowParameterTypes = showParameterTypes;
|
||||
}
|
||||
|
||||
// end of Level 2 methods
|
||||
@@ -524,7 +524,7 @@ public final class RearrangerSettings {
|
||||
}
|
||||
|
||||
public void setShowRules(boolean showRules) {
|
||||
this.myShowRules = showRules;
|
||||
myShowRules = showRules;
|
||||
}
|
||||
|
||||
// end of Level 2 methods
|
||||
@@ -534,7 +534,7 @@ public final class RearrangerSettings {
|
||||
}
|
||||
|
||||
public void setShowTypeAfterMethod(boolean showTypeAfterMethod) {
|
||||
this.myShowTypeAfterMethod = showTypeAfterMethod;
|
||||
myShowTypeAfterMethod = showTypeAfterMethod;
|
||||
}
|
||||
|
||||
// ------------------------ CANONICAL METHODS ------------------------
|
||||
|
||||
@@ -160,15 +160,13 @@ class RearrangerTest extends LightCodeInsightFixtureTestCase {
|
||||
testOpsBlockingQueueExampleWorker(false, "OpsBlockingQueue", false, "OpsBlockingQueue");
|
||||
}
|
||||
|
||||
// public final void testOpsBlockingQueueExampleWithGlobalPattern() throws Exception {
|
||||
// testOpsBlockingQueueExampleWorker(true, "/com/wrq/rearranger/OpsBlockingQueue.java",
|
||||
// false, "/com/wrq/rearranger/OpsBlockingQueue.java");
|
||||
// }
|
||||
//
|
||||
// public final void testOpsBlockingQueueExampleWithIndentedComments() throws Exception {
|
||||
// testOpsBlockingQueueExampleWorker(false, "/com/wrq/rearranger/OpsBlockingQueueIndented.java",
|
||||
// true, "/com/wrq/rearranger/OpsBlockingQueueIndentedResult.java");
|
||||
// }
|
||||
public final void testOpsBlockingQueueExampleWithGlobalPattern() throws Exception {
|
||||
testOpsBlockingQueueExampleWorker(true, "OpsBlockingQueue", false, "OpsBlockingQueue");
|
||||
}
|
||||
|
||||
public final void testOpsBlockingQueueExampleWithIndentedComments() throws Exception {
|
||||
testOpsBlockingQueueExampleWorker(false, "OpsBlockingQueueIndented", true, "OpsBlockingQueueIndentedResult");
|
||||
}
|
||||
|
||||
private void testOpsBlockingQueueExampleWorker(boolean doGlobalPattern,
|
||||
String srcFilename,
|
||||
@@ -294,36 +292,42 @@ class RearrangerTest extends LightCodeInsightFixtureTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
// public final void testReturnTypeMatch() throws Exception {
|
||||
// configureByFile("/com/wrq/rearranger/RearrangementTest12.java");
|
||||
// final PsiFile file = getFile();
|
||||
// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file);
|
||||
// MethodAttributes ma;
|
||||
// ma = new MethodAttributes();
|
||||
// ma.getReturnTypeAttr().setMatch(true);
|
||||
// ma.getReturnTypeAttr().setExpression("void");
|
||||
// rs.addItem(ma, 0);
|
||||
// FieldAttributes fa = new FieldAttributes();
|
||||
// fa.getTypeAttr().setMatch(true);
|
||||
// fa.getTypeAttr().setExpression("int");
|
||||
// rs.addItem(fa, 1);
|
||||
// ma = new MethodAttributes();
|
||||
// ma.getReturnTypeAttr().setMatch(true);
|
||||
// ma.getReturnTypeAttr().setExpression(".*je.*");
|
||||
// rs.addItem(ma, 2);
|
||||
// ma = new MethodAttributes();
|
||||
// ma.getReturnTypeAttr().setMatch(true);
|
||||
// ma.getReturnTypeAttr().setExpression("Integer\\[\\]");
|
||||
// rs.addItem(ma, 3);
|
||||
// ma = new MethodAttributes();
|
||||
// ma.getReturnTypeAttr().setMatch(true);
|
||||
// ma.getReturnTypeAttr().setExpression("int");
|
||||
// rs.addItem(ma, 4);
|
||||
// final RearrangerActionHandler rah = new RearrangerActionHandler();
|
||||
// rah.rearrangeDocument(getProject(), file, rs, doc);
|
||||
// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult12.java");
|
||||
// }
|
||||
//
|
||||
public final void testReturnTypeMatch() throws Exception {
|
||||
doTest('RearrangementTest12', 'RearrangementResult12') {
|
||||
methodRule.create { returnType( 'void' ) }
|
||||
fieldRule.create { type( 'int' ) }
|
||||
methodRule.create { returnType( '.*je.*' ) }
|
||||
methodRule.create { returnType( /Integer\[\]/) }
|
||||
methodRule.create { returnType( 'int' ) }
|
||||
}
|
||||
|
||||
|
||||
//MethodAttributes ma;
|
||||
//ma = new MethodAttributes();
|
||||
//ma.getReturnTypeAttr().setMatch(true);
|
||||
//ma.getReturnTypeAttr().setExpression("void");
|
||||
//rs.addItem(ma, 0);
|
||||
//FieldAttributes fa = new FieldAttributes();
|
||||
//fa.getTypeAttr().setMatch(true);
|
||||
//fa.getTypeAttr().setExpression("int");
|
||||
//rs.addItem(fa, 1);
|
||||
//ma = new MethodAttributes();
|
||||
//ma.getReturnTypeAttr().setMatch(true);
|
||||
//ma.getReturnTypeAttr().setExpression(".*je.*");
|
||||
//rs.addItem(ma, 2);
|
||||
//ma = new MethodAttributes();
|
||||
//ma.getReturnTypeAttr().setMatch(true);
|
||||
//ma.getReturnTypeAttr().setExpression("Integer\\[\\]");
|
||||
//rs.addItem(ma, 3);
|
||||
//ma = new MethodAttributes();
|
||||
//ma.getReturnTypeAttr().setMatch(true);
|
||||
//ma.getReturnTypeAttr().setExpression("int");
|
||||
//rs.addItem(ma, 4);
|
||||
//final RearrangerActionHandler rah = new RearrangerActionHandler();
|
||||
//rah.rearrangeDocument(getProject(), file, rs, doc);
|
||||
//super.checkResultByFile("/com/wrq/rearranger/RearrangementResult12.java");
|
||||
}
|
||||
|
||||
// public final void testRelatedMethodsDepthOriginal() throws Exception {
|
||||
// configureByFile("/com/wrq/rearranger/RearrangementTest13.java");
|
||||
// final PsiFile file = getFile();
|
||||
|
||||
@@ -16,6 +16,8 @@ public enum RearrangerTestDsl {
|
||||
INITIALIZER,
|
||||
/** Method target type (e.g. constructor). */
|
||||
TARGET,
|
||||
TYPE,
|
||||
RETURN_TYPE("returnType"),
|
||||
SORT,
|
||||
COMMENT,
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ class JavaFieldRuleBuilder extends AbstractJavaRuleBuilder<FieldAttributes> {
|
||||
{
|
||||
def handlers = [(InitializerType.ANONYMOUS_CLASS) : createBooleanAttributeHandler('initialisedByAnonymousClassAttr')]
|
||||
registerHandler(RearrangerTestDsl.INITIALIZER, { data, attributes, rule -> handlers[data](attributes, rule) })
|
||||
registerHandler(RearrangerTestDsl.TYPE, createStringAttributeHandler('typeAttr'))
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -18,6 +18,7 @@ class JavaMethodRuleBuilder extends AbstractJavaRuleBuilder<MethodAttributes> {
|
||||
(MethodType.OTHER) : createRawBooleanAttributeHandler('otherMethodType')
|
||||
]
|
||||
registerHandler(RearrangerTestDsl.TARGET, { data, attributes, rule -> handlers[data](attributes, rule) })
|
||||
registerHandler(RearrangerTestDsl.RETURN_TYPE, createStringAttributeHandler('returnTypeAttr'))
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
-7
@@ -10,22 +10,20 @@ import opsx.server.email.OpsEmailGenerator;
|
||||
|
||||
/** @author dchan */
|
||||
public class OpsBlockingQueue extends OpsNonBlockingQueue {
|
||||
//*********************************** PROTECTED/PACKAGE FIELDS **************************************
|
||||
//*********************************** PROTECTED/PACKAGE FIELDS **************************************
|
||||
protected final Object putLock;
|
||||
protected final Object takeLock;
|
||||
protected volatile int waitCount;
|
||||
//************************************** PRIVATE FIELDS *****************************************
|
||||
//************************************** PRIVATE FIELDS *****************************************
|
||||
private static final OpsLogCategory logCat = (OpsLogCategory)OpsLogCategory.getInstance(OpsEmailGenerator.class);
|
||||
//************************************** CONSTRUCTORS *************************************
|
||||
|
||||
/** Creates new OpsBlockingQueue */
|
||||
public OpsBlockingQueue() {
|
||||
takeLock = new Object();
|
||||
putLock = new Object();
|
||||
waitCount = 0;
|
||||
}
|
||||
|
||||
//************************************** PUBLIC METHODS *************************************
|
||||
//************************************** PUBLIC METHODS *************************************
|
||||
// PUBLIC METHODS LINE 2
|
||||
public void put(Object obj) {
|
||||
synchronized (putLock) {
|
||||
@@ -61,8 +59,7 @@ public class OpsBlockingQueue extends OpsNonBlockingQueue {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//********************************* PACKAGE/PROTECTED METHODS ********************************
|
||||
//********************************* PACKAGE/PROTECTED METHODS ********************************
|
||||
protected Object takeNext() {
|
||||
synchronized (takeLock) {
|
||||
return super.takeNext();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
class RearrangementTest12 {
|
||||
|
||||
void method(int y) {
|
||||
x = y;
|
||||
}
|
||||
|
||||
int x;
|
||||
int x;
|
||||
|
||||
Object convertX() {
|
||||
return new Integer(x);
|
||||
@@ -16,6 +16,5 @@ class RearrangementTest12 {
|
||||
int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
String s;
|
||||
}
|
||||
Reference in New Issue
Block a user