Merge branch 'master' into uta-python

This commit is contained in:
Alexey Utkin
2015-12-21 19:46:35 +03:00
1110 changed files with 19846 additions and 11913 deletions
+1 -1
View File
@@ -9,6 +9,6 @@
<plugin id="com.intellij.properties" />
<plugin id="com.intellij.uiDesigner" />
<plugin id="org.intellij.groovy" />
<plugin id="org.jetbrains.kotlin" min-version="1.0.0-beta-2423" max-version="1.1" />
<plugin id="org.jetbrains.kotlin" min-version="1.0.0-beta-3595" max-version="1.1" />
</component>
</project>
+2 -2
View File
@@ -4,11 +4,11 @@
<root url="file://$PROJECT_DIR$/lib/annotations/netty"/>
</ANNOTATIONS>
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/netty-all-4.1.0.Beta7.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/netty-all-4.1.0.Beta8.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$PROJECT_DIR$/lib/src/netty-all-4.1.0.Beta7-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/src/netty-all-4.1.0.Beta8-sources.jar!/" />
</SOURCES>
</library>
</component>
-1
View File
@@ -230,7 +230,6 @@
<module fileurl="file://$PROJECT_DIR$/plugins/groovy/structuralsearch-groovy/structuralsearch-groovy.iml" filepath="$PROJECT_DIR$/plugins/groovy/structuralsearch-groovy/structuralsearch-groovy.iml" group="plugins/Groovy" />
<module fileurl="file://$PROJECT_DIR$/java/structuralsearch-java/structuralsearch-java.iml" filepath="$PROJECT_DIR$/java/structuralsearch-java/structuralsearch-java.iml" group="java" />
<module fileurl="file://$PROJECT_DIR$/platform/structuralsearch/structuralsearch-tests.iml" filepath="$PROJECT_DIR$/platform/structuralsearch/structuralsearch-tests.iml" group="plugins/structuralsearch" />
<module fileurl="file://$PROJECT_DIR$/platform/structure-view-api/structure-view-api.iml" filepath="$PROJECT_DIR$/platform/structure-view-api/structure-view-api.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/structure-view-impl/structure-view-impl.iml" filepath="$PROJECT_DIR$/platform/structure-view-impl/structure-view-impl.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/plugins/svn4idea/svn4idea.iml" filepath="$PROJECT_DIR$/plugins/svn4idea/svn4idea.iml" group="plugins/VCS" />
<module fileurl="file://$PROJECT_DIR$/plugins/svn4idea/svn4idea-tests.iml" filepath="$PROJECT_DIR$/plugins/svn4idea/svn4idea-tests.iml" group="plugins/VCS" />
Binary file not shown.
Binary file not shown.
+4
View File
@@ -61,6 +61,9 @@ if [ -n "$@@product_uc@@_JDK" -a -x "$@@product_uc@@_JDK/bin/java" ]; then
JDK="$@@product_uc@@_JDK"
elif [ -s "$HOME/.@@system_selector@@/config/@@vm_options@@.jdk" ]; then
JDK=`$CAT $HOME/.@@system_selector@@/config/@@vm_options@@.jdk`
if [ ! -d $JDK ]; then
JDK=$IDE_HOME/$JDK
fi
elif [ -x "$IDE_HOME/jre/jre/bin/java" ] && "$IDE_HOME/jre/jre/bin/java" -version > /dev/null 2>&1 ; then
JDK="$IDE_HOME/jre"
elif [ -n "$JDK_HOME" -a -x "$JDK_HOME/bin/java" ]; then
@@ -184,6 +187,7 @@ LD_LIBRARY_PATH="$IDE_BIN_HOME:$LD_LIBRARY_PATH" "$JAVA_BIN" \
$VM_OPTIONS \
"-Djb.vmOptionsFile=$VM_OPTIONS_FILE" \
"-XX:ErrorFile=$HOME/java_error_in_@@product_uc@@_%p.log" \
"-XX:HeapDumpPath=$HOME/java_error_in_@@product_uc@@.hprof" \
-Djb.restart.code=88 -Didea.paths.selector=@@system_selector@@ \
$IDE_PROPERTIES_PROPERTY \
@@ide_jvm_args@@ \
+1 -1
View File
@@ -49,7 +49,7 @@ SET ACC=
FOR /F "usebackq delims=" %%i IN ("%VM_OPTIONS_FILE%") DO CALL "%IDE_BIN_DIR%\append.bat" "%%i"
IF EXIST "%VM_OPTIONS_FILE%" SET ACC=%ACC% -Djb.vmOptionsFile="%VM_OPTIONS_FILE%"
SET COMMON_JVM_ARGS="-XX:ErrorFile=%USERPROFILE%\java_error_in_@@product_uc@@_%%p.log" "-Xbootclasspath/a:%IDE_HOME%/lib/boot.jar" -Didea.paths.selector=@@system_selector@@ %IDE_PROPERTIES_PROPERTY%
SET COMMON_JVM_ARGS="-XX:ErrorFile=%USERPROFILE%\java_error_in_@@product_uc@@_%%p.log" "-XX:HeapDumpPath=%USERPROFILE%\java_error_in_@@product_uc@@.hprof" "-Xbootclasspath/a:%IDE_HOME%/lib/boot.jar" -Didea.paths.selector=@@system_selector@@ %IDE_PROPERTIES_PROPERTY%
SET IDE_JVM_ARGS=@@ide_jvm_args@@
SET ALL_JVM_ARGS=%ACC% %COMMON_JVM_ARGS% %IDE_JVM_ARGS%
Binary file not shown.
+2 -1
View File
@@ -995,7 +995,8 @@ FunctionEnd
Function un.ConfirmDeleteSettings
!insertmacro MUI_HEADER_TEXT "$(uninstall_options)" "$(uninstall_options_prompt)"
!insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 1" "Text" "$(prompt_delete_settings)"
!insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 2" "Text" $INSTDIR
${UnStrRep} $R1 $INSTDIR '\' '\\'
!insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 2" "Text" $R1
!insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 3" "Text" "$(text_delete_settings)"
!insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 4" "Text" "$(confirm_delete_caches)"
!insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 5" "Text" "$(confirm_delete_settings)"
+1 -1
View File
@@ -18,7 +18,7 @@ import com.intellij.util.text.VersionComparatorUtil
import static org.jetbrains.jps.idea.IdeaProjectLoader.guessHome
includeTargets << new File("${guessHome(this)}/build/scripts/utils.gant")
String kotlinBuildConfigurationOnPublicTeamCity = "Kotlin_Beta2_Idea142branch150versionNoTests"
String kotlinBuildConfigurationOnPublicTeamCity = "Kotlin_Beta3_Idea142branch150versionNoTests"
target('default': 'Ensures that build/kotlinc directory contains JARs from Kotlin plugin compatible with current IDEA sources. These JARs are used by build scripts.') {
def communityHome = guessHome(this)
+8 -2
View File
@@ -39,6 +39,14 @@ binding.setVariable("p", {String key, String defaultValue = null ->
}
})
binding.setVariable("versionSelector", {
def fullVersion = p("component.version.major") + "." + p("component.version.minor")
def versionParts = fullVersion.split("\\.")
def minor = versionParts[1]
versionParts[0] + (minor == "0" ? "": "." + minor)
})
binding.setVariable("guessJdk", {
String javaHome = p("java.home")
@@ -379,7 +387,6 @@ binding.setVariable("platformApiModules", [
"projectModel-api",
"remote-servers-agent-rt",
"remote-servers-api",
"structure-view-api",
"usageView",
"vcs-api-core",
"vcs-api",
@@ -1255,7 +1262,6 @@ binding.setVariable("analysisApiModules", [
"jps-model-api",
"jps-model-serialization",
"projectModel-api",
"structure-view-api",
"util",
"util-rt",
"xml-analysis-api",
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 83 KiB

@@ -1,11 +1,12 @@
<component>
<version codename="Community Edition" major="15" minor="1" eap="true"/>
<version codename="Community Edition" major="16" minor="0" eap="true"/>
<company name="JetBrains s.r.o." url="https://www.jetbrains.com/?fromIDE"/>
<build number="__BUILD_NUMBER__" date="__BUILD_DATE__"/>
<install-over minbuild="129.1" maxbuild="139.9999" version="14"/>
<logo url="/idea_community_logo.png" textcolor="aaaaaa" progressColor="FDA916" progressY="230" progressTailIcon="/community_progress_tail.png"/>
<about url="/idea_community_about.png" foreground="333333" copyrightForeground="7A858F" linkColor="9b5121" logoX="300" logoY="265" logoW="75" logoH="30"/>
<icon size32="/icon_CE.png" size16="/icon_CEsmall.png" size12="/toolwindows/toolWindowProject.png" size128="/icon_CE_128.png" ico="idea_CE.ico"/>
<logo url="/idea_community_logo.png" textcolor="444444" progressColor="f87206" progressX="0" progressY="271" progressHeight="3" licenseOffsetY="30" />
<about url="/idea_community_about.png" foreground="444444" copyrightForeground="7A858F" linkColor="9b5121" logoX="300" logoY="265" logoW="75" logoH="30"/>
<icon size32="/icon_CE.png" size16="/icon_CEsmall.png" size128="/icon_CE_128.png" ico="idea_CE.ico"/>
<package code="__PACKAGE_CODE__"/>
<names product="IDEA" fullname="IntelliJ IDEA" script="idea"/>
<welcome-screen logo-url="/Logo_welcomeScreen.png"/>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 175 KiB

After

Width:  |  Height:  |  Size: 263 KiB

@@ -53,7 +53,8 @@ com.android.tools.idea.wizard.TemplateWizardStateTest
com.android.tools.idea.wizard.TemplateWizardModuleBuilderTest
com.android.tools.idea.wizard.NewTemplateObjectWizardTest
org.jetbrains.android.run.AndroidRunConfigurationTest
org.jetbrains.android.run.GradleApkProviderTest
com.android.tools.idea.run.GradleApkProviderTest
com.android.tools.idea.run.LaunchUtilsTest
org.jetbrains.android.facet.IdeaSourceProviderTest
com.android.tools.idea.gradle.service.resolve.AndroidResolveTest
com.android.tools.idea.gradle.service.resolve.AndroidDslContributorTest
@@ -91,6 +92,7 @@ com.android.tools.idea.sdk.IdeSdksTest
com.android.tools.idea.welcome.wizard.FirstRunWizardTest
com.android.tools.idea.wizard.template.TemplateWizardStateTest
com.android.tools.swing.layoutlib.GraphicsLayoutRendererTest
org.jetbrains.android.databinding.GeneratedCodeMatchTest
[ANDROID_BOMBED]
com.android.tools.idea.gradle.project.GradleModuleImportTest
-1
View File
@@ -3,7 +3,6 @@
<vendor>JetBrains</vendor>
<extensions defaultExtensionNs="com.intellij">
<errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
<search.topHitProvider implementation="org.intellij.images.options.impl.ImagesOptionsTopHitProvider"/>
<applicationConfigurable groupId="editor" instance="org.intellij.images.options.impl.OptionsConfigurabe" id="Images" displayName="Images"/>
<fileEditorProvider implementation="org.intellij.images.editor.impl.ImageFileEditorProvider"/>
@@ -26,6 +26,7 @@ import org.intellij.images.editor.ImageEditor;
import org.intellij.images.editor.ImageZoomModel;
import org.intellij.images.fileTypes.ImageFileTypeManager;
import org.intellij.images.thumbnail.actionSystem.ThumbnailViewActions;
import org.intellij.images.ui.ImageComponent;
import org.intellij.images.vfs.IfsUtil;
import org.jetbrains.annotations.NotNull;
@@ -79,7 +80,7 @@ final class ImageEditorImpl implements ImageEditor {
return document.getValue() != null;
}
public JComponent getComponent() {
public ImageEditorUI getComponent() {
return editorUI;
}
@@ -74,6 +74,8 @@ final class ImageEditorUI extends JPanel implements DataProvider, CopyProvider,
private static final String IMAGE_PANEL = "image";
@NonNls
private static final String ERROR_PANEL = "error";
@NonNls
private static final String ZOOM_FACTOR_PROP = "ImageEditor.zoomFactor";
private final @Nullable ImageEditor editor;
private final DeleteProvider deleteProvider;
@@ -348,6 +350,8 @@ final class ImageEditorUI extends JPanel implements DataProvider, CopyProvider,
}
public void setZoomFactor(double zoomFactor) {
double oldZoomFactor = getZoomFactor();
// Change current size
Dimension size = imageComponent.getCanvasSize();
BufferedImage image = imageComponent.getDocument().getValue();
@@ -359,6 +363,8 @@ final class ImageEditorUI extends JPanel implements DataProvider, CopyProvider,
revalidate();
repaint();
myZoomLevelChanged = false;
imageComponent.firePropertyChange(ZOOM_FACTOR_PROP, oldZoomFactor, zoomFactor);
}
private double getMinimumZoomFactor() {
@@ -24,6 +24,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.EventDispatcher;
import org.intellij.images.editor.ImageEditor;
import org.intellij.images.editor.ImageFileEditor;
import org.intellij.images.editor.ImageZoomModel;
@@ -31,6 +32,7 @@ import org.intellij.images.options.*;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
/**
@@ -38,10 +40,11 @@ import java.beans.PropertyChangeListener;
*
* @author <a href="mailto:aefimov.box@gmail.com">Alexey Efimov</a>
*/
final class ImageFileEditorImpl extends UserDataHolderBase implements ImageFileEditor {
final class ImageFileEditorImpl extends UserDataHolderBase implements ImageFileEditor, PropertyChangeListener {
private static final String NAME = "ImageFileEditor";
private final ImageEditor imageEditor;
private final EventDispatcher<PropertyChangeListener> myDispatcher = EventDispatcher.create(PropertyChangeListener.class);
ImageFileEditorImpl(@NotNull Project project, @NotNull VirtualFile file) {
imageEditor = new ImageEditorImpl(project, file);
@@ -54,6 +57,8 @@ final class ImageFileEditorImpl extends UserDataHolderBase implements ImageFileE
TransparencyChessboardOptions transparencyChessboardOptions = editorOptions.getTransparencyChessboardOptions();
imageEditor.setGridVisible(gridOptions.isShowDefault());
imageEditor.setTransparencyChessboardVisible(transparencyChessboardOptions.isShowDefault());
((ImageEditorImpl)imageEditor).getComponent().getImageComponent().addPropertyChangeListener(this);
}
@NotNull
@@ -104,9 +109,17 @@ final class ImageFileEditorImpl extends UserDataHolderBase implements ImageFileE
}
public void addPropertyChangeListener(@NotNull PropertyChangeListener listener) {
myDispatcher.addListener(listener);
}
public void removePropertyChangeListener(@NotNull PropertyChangeListener listener) {
myDispatcher.removeListener(listener);
}
@Override
public void propertyChange(@NotNull PropertyChangeEvent event) {
PropertyChangeEvent editorEvent = new PropertyChangeEvent(this, event.getPropertyName(), event.getOldValue(), event.getNewValue());
myDispatcher.getMulticaster().propertyChange(editorEvent);
}
public BackgroundEditorHighlighter getBackgroundHighlighter() {
@@ -1,5 +1,6 @@
package com.intellij.compiler.instrumentation;
import org.jetbrains.org.objectweb.asm.ClassReader;
import org.jetbrains.org.objectweb.asm.ClassWriter;
/**
@@ -9,6 +10,11 @@ import org.jetbrains.org.objectweb.asm.ClassWriter;
public class InstrumenterClassWriter extends ClassWriter {
private final InstrumentationClassFinder myFinder;
public InstrumenterClassWriter(ClassReader reader, int flags, final InstrumentationClassFinder finder) {
super(reader, flags);
myFinder = finder;
}
public InstrumenterClassWriter(int flags, final InstrumentationClassFinder finder) {
super(flags);
myFinder = finder;
@@ -437,7 +437,7 @@ public class Javac2 extends Javac {
int version = getClassFileVersion(reader);
if (version >= Opcodes.V1_5 && !shouldBeSkippedByAnnotationPattern(reader)) {
ClassWriter writer = new InstrumenterClassWriter(getAsmClassWriterFlags(version), finder);
ClassWriter writer = new InstrumenterClassWriter(reader, getAsmClassWriterFlags(version), finder);
if (NotNullVerifyingInstrumenter.processClassFile(reader, writer)) {
final FileOutputStream fileOutputStream = new FileOutputStream(path);
@@ -171,6 +171,9 @@ public class CompoundPositionManager extends PositionManagerEx implements MultiR
return xStackFrame;
}
}
catch (VMDisconnectedException e) {
throw e;
}
catch (Throwable e) {
LOG.error(e);
}
@@ -2104,6 +2104,9 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
@Override
public void contextAction() {
breakpointManager.applyThreadFilter(DebugProcessImpl.this, null); // clear the filter on resume
if (myReturnValueWatcher != null) {
myReturnValueWatcher.clear();
}
super.contextAction();
}
@@ -23,6 +23,7 @@ import com.intellij.debugger.impl.PositionUtil;
import com.intellij.debugger.jdi.StackFrameProxyImpl;
import com.intellij.debugger.ui.impl.watch.ArgumentValueDescriptorImpl;
import com.intellij.debugger.ui.impl.watch.FieldDescriptorImpl;
import com.intellij.debugger.ui.impl.watch.MethodReturnValueDescriptorImpl;
import com.intellij.debugger.ui.tree.FieldDescriptor;
import com.intellij.debugger.ui.tree.LocalVariableDescriptor;
import com.intellij.debugger.ui.tree.NodeDescriptor;
@@ -61,14 +62,20 @@ public class DefaultSourcePositionProvider extends SourcePositionProvider {
return getSourcePositionForLocalVariable(names.iterator().next(), project, context, nearest);
}
}
else if (descriptor instanceof MethodReturnValueDescriptorImpl) {
DebugProcessImpl debugProcess = context.getDebugProcess();
if (debugProcess != null) {
return debugProcess.getPositionManager().getSourcePosition(((MethodReturnValueDescriptorImpl)descriptor).getMethod().location());
}
}
return null;
}
@Nullable
protected SourcePosition getSourcePositionForField(@NotNull FieldDescriptor descriptor,
@NotNull Project project,
@NotNull DebuggerContextImpl context,
boolean nearest) {
private SourcePosition getSourcePositionForField(@NotNull FieldDescriptor descriptor,
@NotNull Project project,
@NotNull DebuggerContextImpl context,
boolean nearest) {
final ReferenceType type = descriptor.getField().declaringType();
final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
final String fieldName = descriptor.getField().name();
@@ -134,10 +141,10 @@ public class DefaultSourcePositionProvider extends SourcePositionProvider {
}
@Nullable
protected SourcePosition getSourcePositionForLocalVariable(String name,
@NotNull Project project,
@NotNull DebuggerContextImpl context,
boolean nearest) {
private SourcePosition getSourcePositionForLocalVariable(String name,
@NotNull Project project,
@NotNull DebuggerContextImpl context,
boolean nearest) {
PsiElement place = PositionUtil.getContextElement(context);
if (place == null) return null;
@@ -65,7 +65,8 @@ public class JavaDebuggerEvaluator extends XDebuggerEvaluator {
public void evaluate(@NotNull final XExpression expression,
@NotNull final XEvaluationCallback callback,
@Nullable XSourcePosition expressionPosition) {
myDebugProcess.getManagerThread().schedule(new DebuggerContextCommandImpl(myDebugProcess.getDebuggerContext()) {
myDebugProcess.getManagerThread().schedule(new DebuggerContextCommandImpl(myDebugProcess.getDebuggerContext(),
myStackFrame.getStackFrameProxy().threadProxy()) {
@Override
public Priority getPriority() {
return Priority.NORMAL;
@@ -149,8 +149,7 @@ public class MethodReturnValueWatcher {
public void setFeatureEnabled(final boolean featureEnabled) {
myFeatureEnabled = featureEnabled;
myLastExecutedMethod = null;
myLastMethodReturnValue = null;
clear();
}
public void enable(ThreadReference thread) {
@@ -166,6 +165,12 @@ public class MethodReturnValueWatcher {
updateRequestState(trackingEnabled && myFeatureEnabled, thread);
}
public void clear() {
myLastExecutedMethod = null;
myLastMethodReturnValue = null;
myThread = null;
}
private void updateRequestState(final boolean enabled, @Nullable final ThreadReference thread) {
DebuggerManagerThreadImpl.assertIsManagerThread();
try {
@@ -178,8 +183,7 @@ public class MethodReturnValueWatcher {
myExitRequest = null;
}
if (enabled) {
myLastExecutedMethod = null;
myLastMethodReturnValue = null;
clear();
myThread = thread;
if (Registry.is("debugger.watch.return.speedup")) {
@@ -388,7 +388,7 @@ public class DebuggerSession implements AbstractDebuggerSession {
public void dispose() {
getProcess().dispose();
Disposer.dispose(myUpdateAlarm);
DebuggerInvocationUtil.invokeLater(getProject(), new Runnable() {
DebuggerInvocationUtil.swingInvokeLater(getProject(), new Runnable() {
@Override
public void run() {
getContextManager().setState(SESSION_EMPTY_CONTEXT, State.DISPOSED, Event.DISPOSE, null);
@@ -59,6 +59,7 @@ import com.intellij.ui.content.Content;
import com.intellij.unscramble.ThreadDumpPanel;
import com.intellij.unscramble.ThreadState;
import com.intellij.util.DocumentUtil;
import com.intellij.util.Function;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.xdebugger.XSourcePosition;
@@ -556,6 +557,23 @@ public abstract class DebuggerUtilsEx extends DebuggerUtils {
}
}
public static String methodNameWithArguments(Method m) {
StringBuilder res = new StringBuilder();
res.append(m.name()).append("(");
res.append(StringUtil.join(m.argumentTypeNames(), new Function<String, String>() {
@Override
public String fun(String s) {
return getSimpleName(s);
}
}, ", "));
res.append(")");
return res.toString();
}
public static String getSimpleName(String fqn) {
return fqn.substring(fqn.lastIndexOf('.') + 1);
}
public static String methodName(final Method m) {
return methodName(signatureToName(m.declaringType().signature()), m.name(), m.signature());
}
@@ -150,6 +150,7 @@ public class DebuggerSettings implements Cloneable, PersistentStateComponent<Ele
StringUtil.equals(EVALUATE_FINALLY_ON_POP_FRAME, secondSettings.EVALUATE_FINALLY_ON_POP_FRAME) &&
FORCE_CLASSIC_VM == secondSettings.FORCE_CLASSIC_VM &&
DISABLE_JIT == secondSettings.DISABLE_JIT &&
SHOW_ALTERNATIVE_SOURCE == secondSettings.SHOW_ALTERNATIVE_SOURCE &&
HOTSWAP_IN_BACKGROUND == secondSettings.HOTSWAP_IN_BACKGROUND &&
SKIP_SYNTHETIC_METHODS == secondSettings.SKIP_SYNTHETIC_METHODS &&
SKIP_CLASSLOADERS == secondSettings.SKIP_CLASSLOADERS &&
@@ -3,7 +3,7 @@
<grid id="a2574" binding="myPanel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="126" y="76" width="271" height="203"/>
<xy x="126" y="76" width="271" height="217"/>
</constraints>
<properties/>
<border type="none"/>
@@ -43,7 +43,7 @@
</component>
</children>
</grid>
<grid id="f4cba" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="0">
<grid id="f4cba" layout-manager="GridLayoutManager" row-count="5" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="0">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="1" fill="1" indent="0" use-parent-layout="false"/>
@@ -84,6 +84,14 @@
<text resource-bundle="messages/DebuggerBundle" key="label.threads.view.configurable.show.package"/>
</properties>
</component>
<component id="9be9b" class="javax.swing.JCheckBox" binding="myArgsTypesCheckBox">
<constraints>
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/DebuggerBundle" key="label.threads.view.configurable.show.prams.types"/>
</properties>
</component>
</children>
</grid>
</children>
@@ -38,6 +38,7 @@ public class ThreadsViewConfigurable extends BaseConfigurable {
private JCheckBox myShowSyntheticsCheckBox;
private JCheckBox myShowCurrentThreadChechBox;
private JCheckBox myPackageCheckBox;
private JCheckBox myArgsTypesCheckBox;
private final CompositeDataBinding myDataBinding = new CompositeDataBinding();
public ThreadsViewConfigurable(ThreadsViewSettings settings) {
@@ -45,6 +46,7 @@ public class ThreadsViewConfigurable extends BaseConfigurable {
myDataBinding.addBinding(new ToggleButtonBinding("SHOW_CLASS_NAME", myClassNameCheckBox));
myDataBinding.addBinding(new ToggleButtonBinding("SHOW_PACKAGE_NAME", myPackageCheckBox));
myDataBinding.addBinding(new ToggleButtonBinding("SHOW_ARGUMENTS_TYPES", myArgsTypesCheckBox));
myDataBinding.addBinding(new ToggleButtonBinding("SHOW_LINE_NUMBER", myLineNumberCheckBox));
myDataBinding.addBinding(new ToggleButtonBinding("SHOW_SOURCE_NAME", mySourceCheckBox));
myDataBinding.addBinding(new ToggleButtonBinding("SHOW_THREAD_GROUPS", myShowGroupsCheckBox));
@@ -33,6 +33,7 @@ public class ThreadsViewSettings implements PersistentStateComponent<ThreadsView
public boolean SHOW_SOURCE_NAME = false;
public boolean SHOW_SYNTHETIC_FRAMES = true;
public boolean SHOW_CURRENT_THREAD = true;
public boolean SHOW_ARGUMENTS_TYPES = false;
public static ThreadsViewSettings getInstance() {
return ServiceManager.getService(ThreadsViewSettings.class);
@@ -81,8 +81,6 @@ public class AlternativeSourceNotificationProvider extends EditorNotifications.P
return null;
}
if (file.getFileType() == JavaClassFileType.INSTANCE) return null;
final PsiFile psiFile = PsiManager.getInstance(myProject).findFile(file);
if (psiFile == null) return null;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -18,12 +18,15 @@ package com.intellij.debugger.ui.impl.watch;
import com.intellij.debugger.DebuggerContext;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.settings.NodeRendererSettings;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiExpression;
import com.sun.jdi.ClassNotLoadedException;
import com.sun.jdi.Method;
import com.sun.jdi.Type;
import com.sun.jdi.Value;
import org.jetbrains.annotations.NotNull;
/**
* User: lex
@@ -34,7 +37,7 @@ public class MethodReturnValueDescriptorImpl extends ValueDescriptorImpl{
private final Method myMethod;
private final Value myValue;
public MethodReturnValueDescriptorImpl(Project project, final Method method, Value value) {
public MethodReturnValueDescriptorImpl(Project project, @NotNull Method method, Value value) {
super(project);
myMethod = method;
myValue = value;
@@ -44,9 +47,14 @@ public class MethodReturnValueDescriptorImpl extends ValueDescriptorImpl{
return myValue;
}
@NotNull
public Method getMethod() {
return myMethod;
}
public String getName() {
//noinspection HardCodedStringLiteral
return myMethod.toString();
return NodeRendererSettings.getInstance().getClassRenderer().renderTypeName(myMethod.declaringType().name()) + "." +
DebuggerUtilsEx.methodNameWithArguments(myMethod);
}
public Type getType() {
@@ -61,7 +69,7 @@ public class MethodReturnValueDescriptorImpl extends ValueDescriptorImpl{
}
public PsiExpression getDescriptorEvaluation(DebuggerContext context) throws EvaluateException {
throw new EvaluateException("Evaluation not supported for method return value");
return null;
}
public boolean canSetValue() {
@@ -19,6 +19,7 @@ import com.intellij.debugger.SourcePosition;
import com.intellij.debugger.engine.*;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.jdi.StackFrameProxyImpl;
import com.intellij.debugger.settings.ThreadsViewSettings;
import com.intellij.debugger.ui.tree.StackFrameDescriptor;
@@ -180,8 +181,7 @@ public class StackFrameDescriptorImpl extends NodeDescriptorImpl implements Stac
Method method = myMethodOccurrence.getMethod();
if (method != null) {
myName = method.name();
label.append(myName);
label.append("()");
label.append(settings.SHOW_ARGUMENTS_TYPES ? DebuggerUtilsEx.methodNameWithArguments(method) : myName);
}
if (settings.SHOW_LINE_NUMBER) {
String lineNumber;
@@ -20,7 +20,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.options.ex.SingleConfigurableEditor;
import com.intellij.openapi.options.newEditor.OptionsEditorDialog;
import com.intellij.openapi.options.newEditor.SettingsDialog;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
@@ -40,7 +40,7 @@ public class ShowStructureSettingsAction extends AnAction implements DumbAware {
static void showDialog(Project project) {
if (Registry.is("ide.new.project.settings")) {
new SingleConfigurableEditor(project, ProjectStructureConfigurable.getInstance(project), OptionsEditorDialog.DIMENSION_KEY) {
new SingleConfigurableEditor(project, ProjectStructureConfigurable.getInstance(project), SettingsDialog.DIMENSION_KEY) {
@NotNull
@Override
protected DialogStyle getStyle() {
@@ -50,7 +50,7 @@ public class ShowStructureSettingsAction extends AnAction implements DumbAware {
}
else {
ShowSettingsUtil
.getInstance().editConfigurable(project, OptionsEditorDialog.DIMENSION_KEY, ProjectStructureConfigurable.getInstance(project));
.getInstance().editConfigurable(project, SettingsDialog.DIMENSION_KEY, ProjectStructureConfigurable.getInstance(project));
}
}
}
@@ -137,7 +137,7 @@ public class RootDetectionProcessor {
}
final File parentToSkip = result.getParentToSkip();
if (parentToSkip != null && !parentToSkip.equals(dir)) {
if (parentToSkip != null && !FileUtil.filesEqual(parentToSkip, dir)) {
parentsToSkip.add(Pair.create(parentToSkip, i));
}
}
@@ -153,7 +153,7 @@ public class RootDetectionProcessor {
}
for (Pair<File, Integer> pair : toSkip) {
enabledForChildren.set(pair.getSecond(), false);
if (!pair.getFirst().equals(dir)) {
if (!FileUtil.filesEqual(pair.getFirst(), dir)) {
parentsToSkip.add(pair);
}
}
@@ -285,7 +285,7 @@ public abstract class AbstractProjectWizard extends AbstractWizard<ModuleWizardS
}
protected boolean isLastStep() {
return myCurrentStep == mySteps.size() - 1 || isLastStep(getCurrentStep());
return isLastStep(getCurrentStep());
}
private boolean isLastStep(int step) {
@@ -57,6 +57,10 @@ public class JavaModuleSourceRoot extends DetectedSourceRoot {
@NotNull
public JavaModuleSourceRoot combineWith(@NotNull JavaModuleSourceRoot root) {
return new JavaModuleSourceRoot(getDirectory(), getPackagePrefix(), ContainerUtil.concat(myLanguages, root.myLanguages));
List<String> union = new ArrayList<String>(myLanguages.size() + root.myLanguages.size());
union.addAll(myLanguages);
union.addAll(root.myLanguages);
ContainerUtil.removeDuplicates(union);
return new JavaModuleSourceRoot(getDirectory(), getPackagePrefix(), union);
}
}
@@ -35,24 +35,41 @@ public abstract class JavaSourceRootDetector extends ProjectStructureDetector {
@NotNull List<DetectedProjectRoot> result) {
final String fileExtension = getFileExtension();
for (File child : children) {
if (child.isFile()) {
if (FileUtilRt.extensionEquals(child.getName(), fileExtension)) {
Pair<File, String> root = CommonSourceRootDetectionUtil.IO_FILE.suggestRootForFileWithPackageStatement(child, base,
getPackageNameFetcher(),
true);
if (root != null) {
result.add(new JavaModuleSourceRoot(root.getFirst(), root.getSecond(), getLanguageName()));
if (child.isFile() && FileUtilRt.extensionEquals(child.getName(), fileExtension)) {
Pair<File, String> root = CommonSourceRootDetectionUtil.IO_FILE.suggestRootForFileWithPackageStatement(child, base,
getPackageNameFetcher(),
true);
if (root != null) {
JavaModuleSourceRoot sourceRoot = new JavaModuleSourceRoot(root.getFirst(), root.getSecond(), getLanguageName());
result.add(sourceRoot);
// sometimes java files from test data have package statement which includes names of all parent directories
// (e.g. files in jdk/test/java/awt/regtesthelpers in JDK sources have package 'test.java.awt.regtesthelpers')
// This check allows us to not skip searching for other java source roots when first such java file is found.
if (areLastRootsTheSame(result, sourceRoot, 20)) {
return DirectoryProcessingResult.skipChildrenAndParentsUpTo(root.getFirst());
}
else {
return DirectoryProcessingResult.SKIP_CHILDREN;
}
}
return DirectoryProcessingResult.SKIP_CHILDREN;
}
}
return DirectoryProcessingResult.PROCESS_CHILDREN;
}
private static boolean areLastRootsTheSame(List<DetectedProjectRoot> result, JavaModuleSourceRoot root, int threshold) {
if (result.size() < threshold) return false;
List<DetectedProjectRoot> lastItems = result.subList(result.size() - threshold, result.size());
for (DetectedProjectRoot item : lastItems) {
if (!(item instanceof JavaModuleSourceRoot)) return false;
JavaModuleSourceRoot oldRoot = (JavaModuleSourceRoot)item;
if (!FileUtil.filesEqual(oldRoot.getDirectory(), root.getDirectory()) || !oldRoot.getPackagePrefix().equals(root.getPackagePrefix())
|| !oldRoot.getRootTypeName().equals(root.getRootTypeName())) {
return false;
}
}
return true;
}
@Override
public String getDetectorId() {
return "Java";
@@ -1339,7 +1339,9 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
if (!myHolder.hasErrorResults()) {
if (results.length == 0) {
if (results.length == 0 || results[0] instanceof MethodCandidateInfo &&
!((MethodCandidateInfo)results[0]).isApplicable() &&
expression.getFunctionalInterfaceType() != null) {
String description = null;
if (expression.isConstructor()) {
final PsiClass containingClass = PsiMethodReferenceUtil.getQualifierResolveResult(expression).getContainingClass();
@@ -1359,7 +1361,9 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (description != null) {
final PsiElement referenceNameElement = expression.getReferenceNameElement();
final HighlightInfo highlightInfo =
HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).descriptionAndTooltip(description).range(referenceNameElement).create();
HighlightInfo.newHighlightInfo(results.length == 0 ? HighlightInfoType.WRONG_REF
: HighlightInfoType.ERROR)
.descriptionAndTooltip(description).range(referenceNameElement).create();
myHolder.add(highlightInfo);
final TextRange fixRange = HighlightMethodUtil.getFixRange(referenceNameElement);
QuickFixAction.registerQuickFixAction(highlightInfo, fixRange, QuickFixFactory.getInstance().createCreateMethodFromUsageFix(expression));
@@ -25,6 +25,7 @@ import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.util.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
@@ -119,7 +120,8 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp
map.put(methodReferenceExpression, functionalInterfaceType);
final JavaResolveResult result = methodReferenceExpression.advancedResolve(false);
final PsiElement element = result.getElement();
if (element != null && result.isAccessible()) {
if (element != null && result.isAccessible() &&
!(result instanceof MethodCandidateInfo && !((MethodCandidateInfo)result).isApplicable())) {
if (element instanceof PsiMethod && !isSimpleCall(parameters, callExpression, (PsiMethod)element)) {
return null;
}
@@ -290,9 +292,9 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp
}
@Nullable
protected static String createMethodReferenceText(final PsiElement element,
final PsiType functionalInterfaceType,
final PsiParameter[] parameters) {
public static String createMethodReferenceText(final PsiElement element,
final PsiType functionalInterfaceType,
final PsiParameter[] parameters) {
if (element instanceof PsiMethodCallExpression) {
final PsiMethodCallExpression methodCall = (PsiMethodCallExpression)element;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -29,6 +29,7 @@ import com.intellij.ToolExtensionPoints;
import com.intellij.analysis.AnalysisScope;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInsight.daemon.ImplicitUsageProvider;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtilBase;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.ex.EntryPointsManager;
@@ -78,7 +79,7 @@ public class UnusedDeclarationInspectionBase extends GlobalInspectionTool {
private Set<RefElement> myProcessedSuspicious = null;
private int myPhase;
public static final String DISPLAY_NAME = InspectionsBundle.message("inspection.dead.code.display.name");
@NonNls public static final String SHORT_NAME = "unused";
@NonNls public static final String SHORT_NAME = HighlightInfoType.UNUSED_SYMBOL_SHORT_NAME;
@NonNls public static final String ALTERNATIVE_ID = "UnusedDeclaration";
final List<EntryPoint> myExtensions = ContainerUtil.createLockFreeCopyOnWriteList();
@@ -0,0 +1,261 @@
/*
* Copyright 2000-2015 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.codeInspection.visibility;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInsight.daemon.impl.UnusedSymbolUtil;
import com.intellij.codeInspection.BaseJavaBatchLocalInspectionTool;
import com.intellij.codeInspection.InspectionProfile;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspectionBase;
import com.intellij.openapi.progress.EmptyProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Condition;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.*;
import com.intellij.psi.util.ClassUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import com.siyeh.ig.fixes.ChangeModifierFix;
import com.siyeh.ig.psiutils.MethodUtils;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
class AccessCanBeTightenedInspection extends BaseJavaBatchLocalInspectionTool {
private final VisibilityInspection myVisibilityInspection;
AccessCanBeTightenedInspection(@NotNull VisibilityInspection visibilityInspection) {
myVisibilityInspection = visibilityInspection;
}
@Override
public boolean isEnabledByDefault() {
return true;
}
@Override
@NotNull
public String getGroupDisplayName() {
return GroupNames.VISIBILITY_GROUP_NAME;
}
@Override
@NotNull
public String getDisplayName() {
return "Member access can be tightened";
}
@Override
@NotNull
public String getShortName() {
return VisibilityInspection.SHORT_NAME;
}
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
return new MyVisitor(holder);
}
private class MyVisitor extends JavaElementVisitor {
private final ProblemsHolder myHolder;
private final UnusedDeclarationInspectionBase myDeadCodeInspection;
public MyVisitor(@NotNull ProblemsHolder holder) {
myHolder = holder;
InspectionProfile profile = InspectionProjectProfileManager.getInstance(holder.getProject()).getInspectionProfile();
UnusedDeclarationInspectionBase tool = (UnusedDeclarationInspectionBase)profile.getUnwrappedTool(UnusedDeclarationInspectionBase.SHORT_NAME, holder.getFile());
myDeadCodeInspection = tool == null ? new UnusedDeclarationInspectionBase() : tool;
}
private final Set<PsiClass> childMembersAreUsedOutsideMyPackage = ContainerUtil.newConcurrentSet();
@Override
public void visitClass(PsiClass aClass) {
checkMember(aClass);
}
@Override
public void visitMethod(PsiMethod method) {
checkMember(method);
}
@Override
public void visitField(PsiField field) {
checkMember(field);
}
private void checkMember(@NotNull final PsiMember member) {
if (member.hasModifierProperty(PsiModifier.PRIVATE) || member.hasModifierProperty(PsiModifier.NATIVE)) return;
if (member instanceof PsiMethod && member instanceof SyntheticElement || !member.isPhysical()) return;
if (member instanceof PsiMethod) {
PsiMethod method = (PsiMethod)member;
if (!method.getHierarchicalMethodSignature().getSuperSignatures().isEmpty()) {
log(member.getName() + " overrides");
return; // overrides
}
if (MethodUtils.isOverridden(method)) {
log(member.getName() + " overridden");
return;
}
}
if (member instanceof PsiEnumConstant) return;
if (member instanceof PsiClass && (member instanceof PsiAnonymousClass ||
member instanceof PsiTypeParameter ||
member instanceof PsiSyntheticClass ||
PsiUtil.isLocalClass((PsiClass)member))) {
return;
}
final PsiClass memberClass = member.getContainingClass();
if (memberClass != null && (memberClass.isInterface() || memberClass.isEnum() || memberClass.isAnnotationType() || PsiUtil.isLocalClass(memberClass) && member instanceof PsiClass)) {
return;
}
final PsiFile memberFile = member.getContainingFile();
Project project = memberFile.getProject();
if (myDeadCodeInspection.isEntryPoint(member)) {
log(member.getName() +" is entry point");
return;
}
PsiModifierList memberModifierList = member.getModifierList();
if (memberModifierList == null) return;
final int currentLevel = PsiUtil.getAccessLevel(memberModifierList);
final AtomicInteger maxLevel = new AtomicInteger(PsiUtil.ACCESS_LEVEL_PRIVATE);
final AtomicBoolean foundUsage = new AtomicBoolean();
PsiDirectory memberDirectory = memberFile.getContainingDirectory();
final PsiPackage memberPackage = memberDirectory == null ? null : JavaDirectoryService.getInstance().getPackage(memberDirectory);
log(member.getName()+ ": checking effective level for "+member);
boolean result =
UnusedSymbolUtil.processUsages(project, memberFile, member, new EmptyProgressIndicator(), null, new Processor<UsageInfo>() {
@Override
public boolean process(UsageInfo info) {
foundUsage.set(true);
PsiFile psiFile = info.getFile();
if (psiFile == null) return true;
if (!(psiFile instanceof PsiJavaFile)) {
log(" refd from " + psiFile.getName() + "; set to public");
maxLevel.set(PsiUtil.ACCESS_LEVEL_PUBLIC);
if (memberClass != null) {
childMembersAreUsedOutsideMyPackage.add(memberClass);
}
return false; // referenced from XML, has to be public
}
//int offset = info.getNavigationOffset();
//if (offset == -1) return true;
PsiElement element = info.getElement();
if (element == null) return true;
@PsiUtil.AccessLevel
int level = getEffectiveLevel(element, psiFile, member, memberFile, memberClass, memberPackage);
log(" ref in file " + psiFile.getName() + "; level = " + PsiUtil.getAccessModifier(level) + "; (" + element + ")");
while (true) {
int oldLevel = maxLevel.get();
if (level <= oldLevel || maxLevel.compareAndSet(oldLevel, level)) break;
}
if (level == PsiUtil.ACCESS_LEVEL_PUBLIC && memberClass != null) {
childMembersAreUsedOutsideMyPackage.add(memberClass);
}
return level != PsiUtil.ACCESS_LEVEL_PUBLIC;
}
});
if (!foundUsage.get()) {
log(member.getName() + " unused; ignore");
return; // do not propose private for unused method
}
int max = maxLevel.get();
if (max == PsiUtil.ACCESS_LEVEL_PRIVATE && memberClass == null) {
max = suggestPackageLocal(member);
}
log(member.getName()+": effective level is '" + PsiUtil.getAccessModifier(max) + "'");
if (max < currentLevel) {
if (max == PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL && member instanceof PsiClass && childMembersAreUsedOutsideMyPackage.contains(member)) {
log(member.getName() + " children used outside my package; ignore");
return; // e.g. some public method is used outside my package (without importing class)
}
PsiElement toHighlight = currentLevel == PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL ? ((PsiNameIdentifierOwner)member).getNameIdentifier() : ContainerUtil.find(
memberModifierList.getChildren(), new Condition<PsiElement>() {
@Override
public boolean value(PsiElement element) {
return element instanceof PsiKeyword && element.getText().equals(PsiUtil.getAccessModifier(currentLevel));
}
});
assert toHighlight != null : member +" ; " + ((PsiNameIdentifierOwner)member).getNameIdentifier() + "; "+ memberModifierList.getText();
myHolder.registerProblem(toHighlight, "Access can be "+PsiUtil.getAccessModifier(max), new ChangeModifierFix(PsiUtil.getAccessModifier(max)));
}
}
@PsiUtil.AccessLevel
private int getEffectiveLevel(@NotNull PsiElement element,
@NotNull PsiFile file,
@NotNull PsiMember member,
@NotNull PsiFile memberFile,
PsiClass memberClass,
PsiPackage memberPackage) {
PsiClass aClass = PsiTreeUtil.getParentOfType(element, PsiClass.class);
if (memberClass != null && PsiTreeUtil.isAncestor(aClass, memberClass, false) ||
aClass != null && PsiTreeUtil.isAncestor(memberClass, aClass, false)) {
// access from the same file can be via private
// except when used in annotation:
// @Ann(value = C.VAL) class C { public static final String VAL = "xx"; }
PsiAnnotation annotation = PsiTreeUtil.getParentOfType(element, PsiAnnotation.class);
if (annotation != null && annotation.getParent() instanceof PsiModifierList && annotation.getParent().getParent() == aClass) {
return suggestPackageLocal(member);
}
return myVisibilityInspection.SUGGEST_PRIVATE_FOR_INNERS || memberClass == aClass ? PsiUtil.ACCESS_LEVEL_PRIVATE : suggestPackageLocal(member);
}
//if (file == memberFile) {
// return PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL;
//}
PsiDirectory directory = file.getContainingDirectory();
PsiPackage aPackage = directory == null ? null : JavaDirectoryService.getInstance().getPackage(directory);
if (aPackage == memberPackage || aPackage != null && memberPackage != null && Comparing.strEqual(aPackage.getQualifiedName(), memberPackage.getQualifiedName())) {
return suggestPackageLocal(element);
}
if (aClass != null && memberClass != null && aClass.isInheritor(memberClass, true)) {
//access from subclass can be via protected, except for constructors
PsiElement resolved = element instanceof PsiReference ? ((PsiReference)element).resolve() : null;
boolean isConstructor = resolved instanceof PsiClass && element.getParent() instanceof PsiNewExpression
|| resolved instanceof PsiMethod && ((PsiMethod)resolved).isConstructor();
if (!isConstructor) {
return PsiUtil.ACCESS_LEVEL_PROTECTED;
}
}
return PsiUtil.ACCESS_LEVEL_PUBLIC;
}
}
private int suggestPackageLocal(@NotNull PsiElement member) {
boolean suggestPackageLocal = member instanceof PsiClass && ClassUtil.isTopLevelClass((PsiClass)member)
? myVisibilityInspection.SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES
: myVisibilityInspection.SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS;
return suggestPackageLocal ? PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL : PsiUtil.ACCESS_LEVEL_PUBLIC;
}
private static void log(String s) {
//System.out.println(s);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -124,6 +124,12 @@ public class VisibilityInspection extends GlobalJavaBatchInspectionTool {
return new OptionsPanel();
}
@Nullable
@Override
public LocalInspectionTool getSharedLocalInspectionTool() {
return new AccessCanBeTightenedInspection(this);
}
@Override
@NotNull
public String getDisplayName() {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -47,6 +47,7 @@ import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.event.MouseEvent;
import java.util.Collection;
import java.util.List;
@@ -85,7 +86,7 @@ public class ExternalAnnotationsLineMarkerProvider extends LineMarkerProviderDes
return null;
}
return new LineMarkerInfo<PsiElement>(element, element.getTextRange().getStartOffset(),
return new LineMarkerInfo<PsiElement>(element, element.getTextRange(),
AllIcons.Gutter.ExtAnnotation,
Pass.UPDATE_ALL,
ourTooltipProvider, MyIconGutterHandler.INSTANCE,
@@ -160,6 +161,12 @@ public class ExternalAnnotationsLineMarkerProvider extends LineMarkerProviderDes
return "External annotations";
}
@Nullable
@Override
public Icon getIcon() {
return AllIcons.Gutter.ExtAnnotation;
}
private static class MyIconGutterHandler implements GutterIconNavigationHandler<PsiElement> {
static final MyIconGutterHandler INSTANCE = new MyIconGutterHandler();
@@ -352,9 +352,9 @@ public class MethodReturnTypeFix extends LocalQuickFixAndIntentionActionOnPsiEle
final TypeMigrationRules rules = new TypeMigrationRules();
final PsiSubstitutor compoundSubstitutor =
TypeConversionUtil.getSuperClassSubstitutor(superClass, derivedClass, PsiSubstitutor.EMPTY).putAll(psiSubstitutor);
rules.setMigrationRootType(JavaPsiFacade.getElementFactory(project).createType(baseClass, compoundSubstitutor));
rules.setBoundScope(new LocalSearchScope(derivedClass));
TypeMigrationProcessor.runHighlightingTypeMigration(project, editor, rules, referenceParameterList);
TypeMigrationProcessor.runHighlightingTypeMigration(project, editor, rules, referenceParameterList,
JavaPsiFacade.getElementFactory(project).createType(baseClass, compoundSubstitutor));
return false;
}
@@ -72,10 +72,9 @@ public class VariableTypeFromCallFix implements IntentionAction {
@Override
public void invoke(@NotNull final Project project, final Editor editor, PsiFile file) throws IncorrectOperationException {
final TypeMigrationRules rules = new TypeMigrationRules();
rules.setMigrationRootType(myExpressionType);
rules.setBoundScope(PsiSearchHelper.SERVICE.getInstance(project).getUseScope(myVar));
TypeMigrationProcessor.runHighlightingTypeMigration(project, editor, rules, myVar);
TypeMigrationProcessor.runHighlightingTypeMigration(project, editor, rules, myVar, myExpressionType);
}
@Override
@@ -386,7 +386,9 @@ public class PseudoLambdaReplaceTemplate {
lambdaExpression = convertClassTypeExpression(lambdaExpression);
lambdaExpression = convertToJavaLambda(lambdaExpression);
}
LOG.assertTrue(lambdaExpression != null);
if (lambdaExpression == null) {
return expression;
}
final String lambdaExpressionText;
final String elementText;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -29,6 +29,7 @@ import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.util.ClassUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes;
@@ -147,28 +148,14 @@ public class ClassesTreeStructureProvider implements SelectableTreeStructureProv
return viewProvider.getPsi(viewProvider.getBaseLanguage());
}
private static boolean isTopLevelClass(final PsiElement element, PsiFile baseRootFile) {
private static boolean isTopLevelClass(final PsiElement element, @NotNull PsiFile baseRootFile) {
if (!(element instanceof PsiClass)) {
return false;
}
if (element instanceof PsiAnonymousClass) {
return false;
}
final PsiFile parentFile = parentFileOf((PsiClass)element);
// do not select JspClass
return parentFile != null && parentFile.getLanguage() == baseRootFile.getLanguage();
}
@Nullable
private static PsiFile parentFileOf(final PsiClass psiClass) {
return psiClass.getContainingClass() == null ? psiClass.getContainingFile() : null;
return ClassUtil.isTopLevelClass((PsiClass)element);
}
private static class PsiClassOwnerTreeNode extends PsiFileNode {
public PsiClassOwnerTreeNode(PsiClassOwner classOwner, ViewSettings settings) {
super(classOwner.getProject(), classOwner, settings);
}
@@ -36,6 +36,7 @@ import com.intellij.refactoring.util.EnumConstantsUtil;
import com.intellij.refactoring.util.FixableUsageInfo;
import com.intellij.refactoring.util.RefactoringUIUtil;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.Functions;
import com.intellij.util.IncorrectOperationException;
import java.util.*;
@@ -146,10 +147,11 @@ public class ExtractEnumProcessor {
final TypeMigrationRules rules = new TypeMigrationRules();
rules.addConversionDescriptor(new EnumTypeConversionRule(myEnumConstants));
rules.setMigrationRootType(
JavaPsiFacade.getElementFactory(myProject).createType(myClass));
rules.setBoundScope(GlobalSearchScope.projectScope(myProject));
myTypeMigrationProcessor = new TypeMigrationProcessor(myProject, PsiUtilCore.toPsiElementArray(myEnumConstants), rules);
myTypeMigrationProcessor = new TypeMigrationProcessor(myProject,
PsiUtilCore.toPsiElementArray(myEnumConstants),
Functions.<PsiElement, PsiType>constant(JavaPsiFacade.getElementFactory(myProject).createType(myClass)),
rules);
for (UsageInfo usageInfo : myTypeMigrationProcessor.findUsages()) {
final PsiElement migrateElement = usageInfo.getElement();
if (migrateElement instanceof PsiField) {
@@ -25,6 +25,7 @@
package com.intellij.refactoring.introduceParameter;
import com.intellij.codeInspection.AnonymousCanBeLambdaInspection;
import com.intellij.codeInspection.LambdaCanBeMethodReferenceInspection;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.help.HelpManager;
import com.intellij.openapi.options.ConfigurationException;
@@ -275,15 +276,25 @@ public class IntroduceParameterDialog extends RefactoringDialog {
isDeleteLocalVariable = myPanel.isDeleteLocalVariable();
}
final PsiType selectedType = getSelectedType();
final IntroduceParameterProcessor processor = new IntroduceParameterProcessor(
myProject, myMethodToReplaceIn, myMethodToSearchFor,
parameterInitializer, myExpression,
myLocalVar, isDeleteLocalVariable,
getParameterName(), myPanel.isReplaceAllOccurences(),
myPanel.getReplaceFieldsWithGetters(), isDeclareFinal(), myPanel.isGenerateDelegate(), getSelectedType(), myPanel.getParametersToRemove());
myPanel.getReplaceFieldsWithGetters(), isDeclareFinal(), myPanel.isGenerateDelegate(), selectedType, myPanel.getParametersToRemove());
if (myCbCollapseToLambda.isVisible() && myCbCollapseToLambda.isSelected() && parameterInitializer != null) {
PsiExpression lambda = AnonymousCanBeLambdaInspection.replaceAnonymousWithLambda(parameterInitializer, getSelectedType());
PsiExpression lambda = AnonymousCanBeLambdaInspection.replaceAnonymousWithLambda(parameterInitializer, selectedType);
if (lambda != null) {
final PsiParameter[] lambdaParameters = ((PsiLambdaExpression)lambda).getParameterList().getParameters();
final PsiCallExpression toConvertCall = LambdaCanBeMethodReferenceInspection.canBeMethodReferenceProblem(((PsiLambdaExpression)lambda).getBody(), lambdaParameters, selectedType);
if (toConvertCall != null) {
final String methodReferenceText = LambdaCanBeMethodReferenceInspection.createMethodReferenceText(toConvertCall, selectedType, lambdaParameters);
if (methodReferenceText != null) {
lambda = JavaPsiFacade.getElementFactory(getProject()).createExpressionFromText(methodReferenceText, lambda);
}
}
processor.setParameterInitializer(lambda);
}
}
@@ -558,7 +558,9 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
? new PsiElement[] {exprInRange}
: CodeInsightUtil.findStatementsInRange(copy, elements[0].getTextRange().getStartOffset(),
elements[elements.length - 1].getTextRange().getEndOffset());
final MyExtractMethodProcessor processor = new MyExtractMethodProcessor(project, editor, elementsCopy);
final List<PsiMethod> enclosingMethodsInCopy = getEnclosingMethods(Util.getContainingMethod(elementsCopy[0]));
final MyExtractMethodProcessor processor = new MyExtractMethodProcessor(project, editor, elementsCopy,
enclosingMethodsInCopy.get(enclosingMethodsInCopy.size() - 1));
try {
if (!processor.prepare()) return false;
processor.showDialog();
@@ -700,8 +702,11 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
}
private static class MyExtractMethodProcessor extends ExtractMethodProcessor {
public MyExtractMethodProcessor(Project project, Editor editor, PsiElement[] elements) {
private final PsiMethod myTopEnclosingMethod;
public MyExtractMethodProcessor(Project project, Editor editor, PsiElement[] elements, PsiMethod topEnclosing) {
super(project, editor, elements, null, REFACTORING_NAME, null, null);
myTopEnclosingMethod = topEnclosing;
}
@Override
@@ -755,7 +760,8 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
final InputVariables inputVariables = getInputVariables();
List<VariableData> datas = new ArrayList<VariableData>();
for (VariableData data : inputVariables.getInputVariables()) {
if (data.variable instanceof PsiParameter) {
final PsiVariable variable = data.variable;
if (variable instanceof PsiParameter && myTopEnclosingMethod.equals(((PsiParameter)variable).getDeclarationScope())) {
continue;
}
datas.add(data);
@@ -27,6 +27,7 @@ import com.intellij.refactoring.RefactoringActionHandler;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.typeMigration.ui.TypeMigrationDialog;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
public class ChangeTypeSignatureHandler implements RefactoringActionHandler {
@@ -42,7 +43,7 @@ public class ChangeTypeSignatureHandler implements RefactoringActionHandler {
while (typeElement != null) {
final PsiElement parent = typeElement.getParent();
if (parent instanceof PsiVariable || (parent instanceof PsiMember && !(parent instanceof PsiClass)) || isClassArgument(parent)) {
invoke(project, parent, null, editor);
invoke(project, parent, null, null, editor);
return;
}
typeElement = PsiTreeUtil.getParentOfType(parent, PsiTypeElement.class, false);
@@ -61,11 +62,11 @@ public class ChangeTypeSignatureHandler implements RefactoringActionHandler {
public static boolean invokeOnElement(final Project project, final PsiElement element) {
if (element instanceof PsiVariable || (element instanceof PsiMember && !(element instanceof PsiClass)) || element instanceof PsiFile) {
invoke(project, element, null, null);
invoke(project, element, null, null, null);
return true;
}
if (isClassArgument(element)) {
invoke(project, element, null, null);
invoke(project, element, null, null, null);
return true;
}
return false;
@@ -87,9 +88,9 @@ public class ChangeTypeSignatureHandler implements RefactoringActionHandler {
return false;
}
public static void invoke(final Project project, final PsiElement root, final TypeMigrationRules rules, final Editor editor) {
public static void invoke(final Project project, final PsiElement root, final PsiType type, final TypeMigrationRules rules, final Editor editor) {
if (Util.canBeMigrated(root)) {
TypeMigrationDialog dialog = new TypeMigrationDialog(project, root, rules);
TypeMigrationDialog dialog = new TypeMigrationDialog.SingleElement(project, root, type, rules);
dialog.show();
return;
}
@@ -0,0 +1,80 @@
/*
* Copyright 2000-2015 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.refactoring.typeMigration;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiType;
import com.intellij.refactoring.typeMigration.usageInfo.OverridenUsageInfo;
import com.intellij.util.ui.UIUtil;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author Dmitry Batkovich
*/
class MigrateGetterNameSetting {
private static final String CODE_ALWAYS_YES = "Always Migrate Method Names";
private static final String CODE_ALWAYS_NO = "Never Migrate Method Names";
private static final String[] CODES = new String[]{CODE_ALWAYS_YES, Messages.YES_BUTTON, CODE_ALWAYS_NO, Messages.NO_BUTTON};
private final AtomicReference<Boolean> myGlobalValue = new AtomicReference<Boolean>();
void askUserIfNeed(final OverridenUsageInfo info, final String newMethodName, final PsiType migrationReturnType) {
final Boolean globalValue = myGlobalValue.get();
if (globalValue == null) {
final String currentName = ((PsiMethod)info.getElement()).getName();
final String messageText = String.format("Do migrate getter name from '%s' to '%s' since return type is migrated to '%s'?",
currentName,
newMethodName,
migrationReturnType.getCanonicalText());
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
final Boolean globalValue = myGlobalValue.get();
if (globalValue == null) {
final int code = showChooserDialog(messageText);
if (code == 0) {
myGlobalValue.set(true);
info.setMigrateMethodName(newMethodName);
}
else if (code == 1) {
info.setMigrateMethodName(newMethodName);
}
else if (code == 2) {
myGlobalValue.set(false);
}
}
else if (globalValue.equals(Boolean.TRUE)) {
info.setMigrateMethodName(newMethodName);
}
}
});
}
else if (globalValue.equals(Boolean.TRUE)) {
info.setMigrateMethodName(newMethodName);
}
}
private static int showChooserDialog(String messageText) {
if (ApplicationManager.getApplication().isUnitTestMode()) {
return messageText.contains("dontMigrateName") ? 3 : 1;
} else {
return Messages.showIdeaMessageDialog(null, messageText, "Type Migration", CODES, 0, null, null);
}
}
}
@@ -20,6 +20,7 @@ import com.intellij.psi.PsiSubstitutor;
import com.intellij.psi.PsiType;
import com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class TypeConversionDescriptorBase {
@@ -54,7 +55,7 @@ public class TypeConversionDescriptorBase {
return null;
}
public PsiExpression replace(PsiExpression expression) throws IncorrectOperationException {
public PsiExpression replace(PsiExpression expression, @NotNull TypeEvaluator evaluator) throws IncorrectOperationException {
return expression;
}
@@ -47,18 +47,19 @@ public class TypeEvaluator {
private final TypeMigrationRules myRules;
private final TypeMigrationLabeler myLabeler;
public TypeEvaluator(final LinkedList<Pair<TypeMigrationUsageInfo, PsiType>> types, final TypeMigrationLabeler labeler) {
myLabeler = labeler;
myRules = labeler.getRules();
myRules = labeler == null ? new TypeMigrationRules() : labeler.getRules();
myTypeMap = new HashMap<TypeMigrationUsageInfo, LinkedList<PsiType>>();
for (final Pair<TypeMigrationUsageInfo, PsiType> p : types) {
final LinkedList<PsiType> e = new LinkedList<PsiType>();
if (types != null) {
for (final Pair<TypeMigrationUsageInfo, PsiType> p : types) {
final LinkedList<PsiType> e = new LinkedList<PsiType>();
e.addFirst(p.getSecond());
e.addFirst(p.getSecond());
myTypeMap.put(p.getFirst(), e);
myTypeMap.put(p.getFirst(), e);
}
}
}
@@ -475,7 +476,15 @@ public class TypeEvaluator {
}
void bindTypeParameters(PsiType formal, final PsiType actual) {
if (formal instanceof PsiWildcardType) formal = ((PsiWildcardType)formal).getBound();
if (formal instanceof PsiWildcardType) {
if (actual instanceof PsiCapturedWildcardType &&
((PsiWildcardType)formal).isExtends() == ((PsiCapturedWildcardType)actual).getWildcard().isExtends()) {
bindTypeParameters(((PsiWildcardType)formal).getBound(), ((PsiCapturedWildcardType)actual).getWildcard().getBound());
return;
} else {
formal = ((PsiWildcardType)formal).getBound();
}
}
if (formal instanceof PsiArrayType && actual instanceof PsiArrayType) {
bindTypeParameters(((PsiArrayType)formal).getComponentType(), ((PsiArrayType)actual).getComponentType());
@@ -15,6 +15,8 @@
*/
package com.intellij.refactoring.typeMigration;
import com.intellij.codeInsight.generation.GenerateMembersUtil;
import com.intellij.codeInsight.generation.GetterSetterPrototypeProvider;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -35,13 +37,14 @@ import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.rename.RenameProcessor;
import com.intellij.refactoring.typeMigration.usageInfo.OverridenUsageInfo;
import com.intellij.refactoring.typeMigration.usageInfo.OverriderUsageInfo;
import com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.*;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.*;
import com.intellij.util.graph.DFSTBuilder;
import com.intellij.util.graph.GraphGenerator;
import org.jetbrains.annotations.NotNull;
@@ -50,6 +53,8 @@ import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
/**
* @author db
@@ -65,6 +70,7 @@ public class TypeMigrationLabeler {
}
private final TypeMigrationRules myRules;
private final Function<PsiElement, PsiType> myMigrationRootTypeFunction;
private TypeEvaluator myTypeEvaluator;
private final LinkedHashMap<PsiElement, Object> myConversions;
private final HashSet<Pair<SmartPsiElementPointer<PsiExpression>, PsiType>> myFailedConversions;
@@ -80,10 +86,14 @@ public class TypeMigrationLabeler {
private final Map<Pair<TypeMigrationUsageInfo, TypeMigrationUsageInfo>, Set<PsiElement>> myRootUsagesTree = new HashMap<Pair<TypeMigrationUsageInfo, TypeMigrationUsageInfo>, Set<PsiElement>>();
private final Set<TypeMigrationUsageInfo> myProcessedRoots = new HashSet<TypeMigrationUsageInfo>();
public TypeMigrationLabeler(final TypeMigrationRules rules, PsiType rootType) {
this(rules, Functions.<PsiElement, PsiType>constant(rootType));
}
public TypeMigrationLabeler(final TypeMigrationRules rules) {
public TypeMigrationLabeler(final TypeMigrationRules rules, Function<PsiElement, PsiType> migrationRootTypeFunction) {
myRules = rules;
myMigrationRootTypeFunction = migrationRootTypeFunction;
myConversions = new LinkedHashMap<PsiElement, Object>();
myFailedConversions = new HashSet<Pair<SmartPsiElementPointer<PsiExpression>, PsiType>>();
myNewExpressionTypeChange = new LinkedHashMap<TypeMigrationUsageInfo, PsiType>();
@@ -94,6 +104,10 @@ public class TypeMigrationLabeler {
return myFailedConversions.size() > 0;
}
public Function<PsiElement, PsiType> getMigrationRootTypeFunction() {
return myMigrationRootTypeFunction;
}
public String[] getFailedConversionsReport() {
final String[] report = new String[myFailedConversions.size()];
int j = 0;
@@ -245,45 +259,77 @@ public class TypeMigrationLabeler {
return infos;
}
MigrationProducer createMigratorFor(UsageInfo[] usages) {
final Map<UsageInfo, Object> conversions = new com.intellij.util.containers.HashMap<UsageInfo, Object>();
for (UsageInfo usage : usages) {
final Object conversion = getConversion(usage.getElement());
if (conversion != null) {
conversions.put(usage, conversion);
}
}
return new MigrationProducer(conversions);
}
public void change(final TypeMigrationUsageInfo usageInfo, @NotNull Consumer<PsiNewExpression> consumer) {
final PsiElement element = usageInfo.getElement();
if (element == null) return;
final Project project = element.getProject();
if (element instanceof PsiExpression) {
final PsiExpression expression = (PsiExpression)element;
if (element instanceof PsiNewExpression) {
for (Map.Entry<TypeMigrationUsageInfo, PsiType> info : myNewExpressionTypeChange.entrySet()) {
final PsiElement expressionToReplace = info.getKey().getElement();
if (expression.equals(expressionToReplace)) {
final PsiNewExpression newExpression =
TypeMigrationReplacementUtil.replaceNewExpressionType(project, (PsiNewExpression)expressionToReplace, info);
if (newExpression != null) {
consumer.consume(newExpression);
class MigrationProducer {
private final Map<UsageInfo, Object> myRemainConversions;
private MigrationProducer(Map<UsageInfo, Object> conversions) {
myRemainConversions = conversions;
}
public void change(final TypeMigrationUsageInfo usageInfo, @NotNull Consumer<PsiNewExpression> consumer) {
final PsiElement element = usageInfo.getElement();
if (element == null) return;
final Project project = element.getProject();
if (element instanceof PsiExpression) {
final PsiExpression expression = (PsiExpression)element;
if (element instanceof PsiNewExpression) {
for (Map.Entry<TypeMigrationUsageInfo, PsiType> info : myNewExpressionTypeChange.entrySet()) {
final PsiElement expressionToReplace = info.getKey().getElement();
if (expression.equals(expressionToReplace)) {
final PsiNewExpression newExpression =
TypeMigrationReplacementUtil.replaceNewExpressionType(project, (PsiNewExpression)expressionToReplace, info);
if (newExpression != null) {
consumer.consume(newExpression);
}
}
}
}
final Object conversion = myRemainConversions.get(usageInfo);
if (conversion != null) {
myRemainConversions.remove(usageInfo);
TypeMigrationReplacementUtil.replaceExpression(expression, project, conversion, myTypeEvaluator);
}
} else if (element instanceof PsiReferenceParameterList) {
for (Map.Entry<TypeMigrationUsageInfo, PsiClassType> entry : myClassTypeArgumentsChange.entrySet()) {
if (element.equals(entry.getKey().getElement())) { //todo check null
final PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
try {
element.getParent().replace(factory.createReferenceElementByType(entry.getValue()));
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
}
}
final Object conversion = myConversions.get(element);
if (conversion != null) {
myConversions.remove(element);
TypeMigrationReplacementUtil.replaceExpression(expression, project, conversion);
}
} else if (element instanceof PsiReferenceParameterList) {
for (Map.Entry<TypeMigrationUsageInfo, PsiClassType> entry : myClassTypeArgumentsChange.entrySet()) {
if (element.equals(entry.getKey().getElement())) { //todo check null
final PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
try {
element.getParent().replace(factory.createReferenceElementByType(entry.getValue()));
}
catch (IncorrectOperationException e) {
LOG.error(e);
else {
TypeMigrationReplacementUtil.migratePsiMemberType(element, project, getTypeEvaluator().getType(usageInfo));
if (usageInfo instanceof OverridenUsageInfo) {
final String migrationName = ((OverridenUsageInfo)usageInfo).getMigrateMethodName();
if (migrationName != null) {
new RenameProcessor(project, element, migrationName, false, false).run();
}
}
}
}
else {
TypeMigrationReplacementUtil.migratePsiMemberType(element, project, getTypeEvaluator().getType(usageInfo));
Object getConversion(UsageInfo info) {
return myRemainConversions.remove(info);
}
boolean allOfConversionsUsed() {
return myRemainConversions.isEmpty();
}
}
@@ -530,12 +576,16 @@ public class TypeMigrationLabeler {
final PsiMethod[] methods = OverridingMethodsSearch.search(method, true).toArray(PsiMethod.EMPTY_ARRAY);
final OverridenUsageInfo overridenUsageInfo = new OverridenUsageInfo(method);
final OverriderUsageInfo[] overriders = new OverriderUsageInfo[methods.length];
for (int i = -1; i < methods.length; i++) {
final TypeMigrationUsageInfo m;
if (i < 0) {
final OverridenUsageInfo overridenUsageInfo = new OverridenUsageInfo(method);
m = overridenUsageInfo;
final String newMethodName = isMethodNameCanBeChanged(method);
if (newMethodName != null) {
myRules.getMigrateGetterNameSetting().askUserIfNeed(overridenUsageInfo, newMethodName, myTypeEvaluator.getType(myCurrentRoot));
}
}
else {
overriders[i] = new OverriderUsageInfo(methods[i], method);
@@ -544,7 +594,6 @@ public class TypeMigrationLabeler {
alreadyProcessed = addRoot(m, type, place, alreadyProcessed);
}
overridenUsageInfo.setOverriders(overriders);
return !alreadyProcessed;
}
@@ -570,8 +619,6 @@ public class TypeMigrationLabeler {
alreadyProcessed = addRoot(paramUsageInfo, type, place, alreadyProcessed);
}
overridenUsageInfo.setOverriders(overriders);
return !alreadyProcessed;
}
else {
@@ -579,6 +626,47 @@ public class TypeMigrationLabeler {
}
}
@Nullable
private String isMethodNameCanBeChanged(PsiMethod method) {
if (myCurrentRoot == null) {
return null;
}
final PsiElement root = myCurrentRoot.getElement();
if (!(root instanceof PsiField)) {
return null;
}
PsiField field = (PsiField) root;
final PsiType migrationType = myTypeEvaluator.getType(root);
if (migrationType == null) {
return null;
}
final PsiType sourceType = field.getType();
if (TypeConversionUtil.isAssignable(migrationType, sourceType)) {
return null;
}
if (!(migrationType.equals(PsiType.BOOLEAN) || migrationType.equals(PsiType.BOOLEAN.getBoxedType(field))) &&
!(sourceType.equals(PsiType.BOOLEAN) || sourceType.equals(PsiType.BOOLEAN.getBoxedType(field)))) {
return null;
}
final PsiMethod[] getters =
GetterSetterPrototypeProvider.findGetters(field.getContainingClass(), field.getName(), field.hasModifierProperty(PsiModifier.STATIC));
if (getters != null) {
for (PsiMethod getter : getters) {
if (getter.isEquivalentTo(method)) {
final String suggestedName = GenerateMembersUtil.suggestGetterName(field.getName(), migrationType, method.getProject());
if (!suggestedName.equals(method.getName())) {
if (getter.getContainingClass().findMethodsByName(suggestedName, true).length == 0) {
return null;
}
return suggestedName;
}
return null;
}
}
}
return null;
}
static boolean typeContainsTypeParameters(@Nullable PsiType originalType, @NotNull Set<PsiTypeParameter> excluded) {
if (originalType instanceof PsiClassType) {
final PsiClassType psiClassType = (PsiClassType)originalType;
@@ -884,9 +972,8 @@ public class TypeMigrationLabeler {
myTypeEvaluator = new TypeEvaluator(myMigrationRoots, this);
final PsiType rootType = myRules.getMigrationRootType();
for (PsiElement victim : victims) {
addMigrationRoot(victim, rootType, null, false, true, true);
addMigrationRoot(victim, myMigrationRootTypeFunction.fun(victim), null, false, true, true);
}
if (autoMigrate) {
@@ -16,6 +16,7 @@
package com.intellij.refactoring.typeMigration;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
@@ -34,49 +35,64 @@ import com.intellij.ui.content.Content;
import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewDescriptor;
import com.intellij.usageView.UsageViewManager;
import com.intellij.util.Consumer;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.SmartList;
import com.intellij.usages.Usage;
import com.intellij.util.*;
import com.intellij.util.containers.*;
import com.intellij.util.containers.HashMap;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.*;
import static com.intellij.util.ObjectUtils.assertNotNull;
public class TypeMigrationProcessor extends BaseRefactoringProcessor {
private final static Logger LOG = Logger.getInstance(TypeMigrationProcessor.class);
private final static int MAX_ROOT_IN_PREVIEW_PRESENTATION = 3;
private PsiElement[] myRoot;
private Function<PsiElement, PsiType> myRootTypes;
private final TypeMigrationRules myRules;
private TypeMigrationLabeler myLabeler;
public TypeMigrationProcessor(final Project project, final PsiElement root, final TypeMigrationRules rules) {
this(project, new PsiElement[]{root}, rules);
}
public TypeMigrationProcessor(final Project project, final PsiElement[] roots, final TypeMigrationRules rules) {
public TypeMigrationProcessor(final Project project, final PsiElement[] roots, final Function<PsiElement, PsiType> rootTypes, final TypeMigrationRules rules) {
super(project);
myRoot = roots;
myRules = rules;
myRootTypes = rootTypes;
}
public static void runHighlightingTypeMigration(final Project project,
final Editor editor,
final TypeMigrationRules rules,
final PsiElement root,
final PsiType migrationType) {
runHighlightingTypeMigration(project, editor, rules, root, migrationType, false);
}
public static void runHighlightingTypeMigration(final Project project,
final Editor editor,
final TypeMigrationRules rules,
final PsiElement root,
final PsiType migrationType,
final boolean optimizeImports) {
runHighlightingTypeMigration(project, editor, rules, new PsiElement[] {root}, Functions.<PsiElement, PsiType>constant(migrationType), optimizeImports);
}
public static void runHighlightingTypeMigration(final Project project,
final Editor editor,
final TypeMigrationRules rules,
final PsiElement root) {
runHighlightingTypeMigration(project, editor, rules, root, false);
}
public static void runHighlightingTypeMigration(final Project project,
final Editor editor,
final TypeMigrationRules rules,
final PsiElement root,
final boolean optimizeImports) {
final PsiFile containingFile = root.getContainingFile();
final TypeMigrationProcessor processor = new TypeMigrationProcessor(project, root, rules) {
final Editor editor,
final TypeMigrationRules rules,
final PsiElement[] roots,
final Function<PsiElement, PsiType> migrationTypeFunction,
final boolean optimizeImports) {
final Set<PsiFile> containingFiles = ContainerUtil.map2Set(roots, new Function<PsiElement, PsiFile>() {
@Override
public PsiFile fun(PsiElement element) {
return element.getContainingFile();
}
});
final TypeMigrationProcessor processor = new TypeMigrationProcessor(project, roots, migrationTypeFunction, rules) {
@Override
public void performRefactoring(@NotNull final UsageInfo[] usages) {
super.performRefactoring(usages);
@@ -86,7 +102,7 @@ public class TypeMigrationProcessor extends BaseRefactoringProcessor {
final List<PsiElement> result = new ArrayList<PsiElement>();
for (UsageInfo usage : usages) {
final PsiElement element = usage.getElement();
if (element == null || containingFile != element.getContainingFile()) continue;
if (element == null || !containingFiles.contains(element.getContainingFile())) continue;
if (element instanceof PsiMethod) {
result.add(((PsiMethod)element).getReturnTypeElement());
}
@@ -120,6 +136,7 @@ public class TypeMigrationProcessor extends BaseRefactoringProcessor {
processor.run();
}
@NotNull
@Override
protected UsageViewDescriptor createUsageViewDescriptor(@NotNull UsageInfo[] usages) {
@@ -152,35 +169,56 @@ public class TypeMigrationProcessor extends BaseRefactoringProcessor {
@Override
protected void previewRefactoring(@NotNull final UsageInfo[] usages) {
MigrationPanel panel = new MigrationPanel(myRoot[0], myLabeler, myProject, isPreviewUsages());
String text;
if (myRoot[0] instanceof PsiField) {
text = "field \'" + ((PsiField)myRoot[0]).getName() + "\'";
MigrationPanel panel = new MigrationPanel(myRoot, myLabeler, myProject, isPreviewUsages());
String name;
if (myRoot.length == 1) {
String fromType = assertNotNull(TypeMigrationLabeler.getElementType(myRoot[0])).getPresentableText();
String toType = myRootTypes.fun(myRoot[0]).getPresentableText();
String text;
text = getPresentation(myRoot[0]);
name = "Migrate Type of " + text + " from \'" + fromType + "\' to \'" + toType + "\'";
} else {
final int rootsInPresentationCount = myRoot.length > MAX_ROOT_IN_PREVIEW_PRESENTATION ? MAX_ROOT_IN_PREVIEW_PRESENTATION : myRoot.length;
String[] rootsPresentation = new String[rootsInPresentationCount];
for (int i = 0; i < rootsInPresentationCount; i++) {
final PsiElement root = myRoot[i];
rootsPresentation[i] = root instanceof PsiNamedElement ? ((PsiNamedElement)root).getName() : root.getText();
}
rootsPresentation = StringUtil.surround(rootsPresentation, "\'", "\'");
name = "Migrate Type of " + StringUtil.join(rootsPresentation, ", ");
if (myRoot.length > MAX_ROOT_IN_PREVIEW_PRESENTATION) {
name += "...";
}
}
else if (myRoot[0] instanceof PsiParameter) {
text = "parameter \'" + ((PsiParameter)myRoot[0]).getName() + "\'";
}
else if (myRoot[0] instanceof PsiLocalVariable) {
text = "variable \'" + ((PsiLocalVariable)myRoot[0]).getName() + "\'";
}
else if (myRoot[0] instanceof PsiMethod) {
text = "method \'" + ((PsiMethod)myRoot[0]).getName() + "\' return";
}
else {
text = Arrays.toString(myRoot);
}
String fromType = assertNotNull(TypeMigrationLabeler.getElementType(myRoot[0])).getPresentableText();
String toType = myRules.getMigrationRootType().getPresentableText();
String name = "Migrate Type of " + text + " from \'" + fromType + "\' to \'" + toType + "\'";
Content content = UsageViewManager.getInstance(myProject).addContent(name, false, panel, true, true);
panel.setContent(content);
ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.FIND).activate(null);
}
public static String getPresentation(PsiElement element) {
String text;
if (element instanceof PsiField) {
text = "field \'" + ((PsiField)element).getName() + "\'";
}
else if (element instanceof PsiParameter) {
text = "parameter \'" + ((PsiParameter)element).getName() + "\'";
}
else if (element instanceof PsiLocalVariable) {
text = "variable \'" + ((PsiLocalVariable)element).getName() + "\'";
}
else if (element instanceof PsiMethod) {
text = "method \'" + ((PsiMethod)element).getName() + "\' return";
}
else {
text = element.getText();
}
return text;
}
@NotNull
@Override
public UsageInfo[] findUsages() {
myLabeler = new TypeMigrationLabeler(myRules);
myLabeler = new TypeMigrationLabeler(myRules, myRootTypes);
try {
return myLabeler.getMigratedUsages(!isPreviewUsages(), myRoot);
@@ -209,6 +247,7 @@ public class TypeMigrationProcessor extends BaseRefactoringProcessor {
public static void change(TypeMigrationLabeler labeler, UsageInfo[] usages) {
final List<PsiNewExpression> newExpressionsToCheckDiamonds = new SmartList<PsiNewExpression>();
final TypeMigrationLabeler.MigrationProducer producer = labeler.createMigratorFor(usages);
List<UsageInfo> nonCodeUsages = new ArrayList<UsageInfo>();
for (UsageInfo usage : usages) {
@@ -218,7 +257,7 @@ public class TypeMigrationProcessor extends BaseRefactoringProcessor {
element instanceof PsiMember ||
element instanceof PsiExpression ||
element instanceof PsiReferenceParameterList) {
labeler.change((TypeMigrationUsageInfo)usage, new Consumer<PsiNewExpression>() {
producer.change((TypeMigrationUsageInfo)usage, new Consumer<PsiNewExpression>() {
@Override
public void consume(@NotNull PsiNewExpression expression) {
newExpressionsToCheckDiamonds.add(expression);
@@ -239,7 +278,7 @@ public class TypeMigrationProcessor extends BaseRefactoringProcessor {
if (element != null) {
final PsiReference reference = element.getReference();
if (reference != null) {
final Object target = labeler.getConversion(element);
final Object target = producer.getConversion(usageInfo);
if (target instanceof PsiMember) {
try {
reference.bindToElement((PsiElement)target);
@@ -39,10 +39,13 @@ public class TypeMigrationReplacementUtil {
private TypeMigrationReplacementUtil() {
}
public static PsiElement replaceExpression(PsiExpression expression, final Project project, Object conversion) {
public static PsiElement replaceExpression(PsiExpression expression,
final Project project,
Object conversion,
TypeEvaluator typeEvaluator) {
if (conversion instanceof TypeConversionDescriptorBase) {
try {
return ((TypeConversionDescriptorBase)conversion).replace(expression);
return ((TypeConversionDescriptorBase)conversion).replace(expression, typeEvaluator);
} catch (IncorrectOperationException e) {
LOG.error(e);
}
@@ -35,24 +35,16 @@ import java.util.LinkedList;
*/
public class TypeMigrationRules {
private final LinkedList<TypeConversionRule> myConversionRules = new LinkedList<TypeConversionRule>();
private PsiType myMigrationRootType;
private SearchScope mySearchScope;
private final MigrateGetterNameSetting myMigrateGetterNameSetting = new MigrateGetterNameSetting();
public TypeMigrationRules() {
myConversionRules.add(new RootTypeConversionRule());
myConversionRules.add(new DisjunctionTypeConversionRule());
ContainerUtil.addAll(myConversionRules, Extensions.getExtensions(TypeConversionRule.EP_NAME));
}
public void setMigrationRootType(PsiType migrationRootType) {
myMigrationRootType = migrationRootType;
}
public PsiType getMigrationRootType() {
return myMigrationRootType;
}
public void addConversionDescriptor(TypeConversionRule rule) {
myConversionRules.add(rule);
}
@@ -92,6 +84,10 @@ public class TypeMigrationRules {
return mySearchScope;
}
public MigrateGetterNameSetting getMigrateGetterNameSetting() {
return myMigrateGetterNameSetting;
}
@Nullable
public Pair<PsiType, PsiType> bindTypeParameters(final PsiType from, final PsiType to, final PsiMethod method,
final PsiExpression context, final TypeMigrationLabeler labeler) {
@@ -506,7 +506,10 @@ class TypeMigrationStatementProcessor extends JavaRecursiveElementVisitor {
case TypeInfection.LEFT_INFECTED:
final PsiType valueType = right.getType();
if (valueType != null && declarationType != null) {
myLabeler.migrateExpressionType(value, declarationType, myStatement, TypeConversionUtil.isAssignable(declarationType, valueType), true);
myLabeler.migrateExpressionType(value,
adjustMigrationTypeIfGenericArrayCreation(declarationType, value),
myStatement,
TypeConversionUtil.isAssignable(declarationType, valueType), true);
}
break;
@@ -515,7 +518,11 @@ class TypeMigrationStatementProcessor extends JavaRecursiveElementVisitor {
if (psiType != null && declarationType != null &&
!myLabeler.addMigrationRoot(variable, psiType, myStatement, TypeConversionUtil.isAssignable(declarationType, psiType), true) &&
!TypeConversionUtil.isAssignable(left.getType(), psiType)) {
myLabeler.convertExpression(value, psiType, left.getType(), isCovariantPosition);
PsiType initialType = left.getType();
if (initialType instanceof PsiEllipsisType) {
initialType = ((PsiEllipsisType)initialType).getComponentType();
}
myLabeler.convertExpression(value, psiType, initialType, isCovariantPosition);
}
break;
@@ -528,6 +535,21 @@ class TypeMigrationStatementProcessor extends JavaRecursiveElementVisitor {
}
}
private static PsiType adjustMigrationTypeIfGenericArrayCreation(PsiType migrationType, PsiExpression expression) {
if (expression instanceof PsiNewExpression) {
if (migrationType instanceof PsiArrayType) {
final PsiType componentType = migrationType.getDeepComponentType();
if (componentType instanceof PsiClassType) {
final PsiClassType rawType = ((PsiClassType)componentType).rawType();
if (!rawType.equals(componentType)) {
return com.intellij.refactoring.typeCook.Util.createArrayType(rawType, migrationType.getArrayDimensions());
}
}
}
}
return migrationType;
}
private void addTypeUsage(final PsiElement typedElement) {
if (typedElement instanceof PsiReferenceExpression) {
@@ -21,6 +21,7 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase;
import com.intellij.refactoring.typeMigration.TypeEvaluator;
import com.intellij.refactoring.typeMigration.TypeMigrationLabeler;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.ig.style.UnnecessarilyQualifiedStaticUsageInspection;
@@ -64,7 +65,7 @@ public class RootTypeConversionRule extends TypeConversionRule {
if (Comparing.equal(functionalInterfaceType, to) && method.isEquivalentTo(LambdaUtil.getFunctionalInterfaceMethod(from))) {
return new TypeConversionDescriptorBase() {
@Override
public PsiExpression replace(PsiExpression expression) throws IncorrectOperationException {
public PsiExpression replace(PsiExpression expression, TypeEvaluator evaluator) throws IncorrectOperationException {
final PsiMethodReferenceExpression methodReferenceExpression = (PsiMethodReferenceExpression)expression;
final PsiExpression qualifierExpression = methodReferenceExpression.getQualifierExpression();
if (qualifierExpression != null) {
@@ -139,7 +140,7 @@ public class RootTypeConversionRule extends TypeConversionRule {
}
@Override
public PsiExpression replace(PsiExpression expression) throws IncorrectOperationException {
public PsiExpression replace(PsiExpression expression, TypeEvaluator evaluator) throws IncorrectOperationException {
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
final PsiExpression qualifierExpression = methodCallExpression.getMethodExpression().getQualifierExpression();
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(expression.getProject());
@@ -38,7 +38,6 @@ public class MigrationNode extends AbstractTreeNode<TypeMigrationUsageInfo> impl
private List<MigrationNode> myCachedChildren;
private final TypeMigrationLabeler myLabeler;
private final PsiType myMigrationType;
private final TypeMigrationTreeBuilder myBuilder;
private final HashMap<TypeMigrationUsageInfo, Set<MigrationNode>> myProcessed;
private final HashSet<TypeMigrationUsageInfo> myParents;
@@ -46,13 +45,11 @@ public class MigrationNode extends AbstractTreeNode<TypeMigrationUsageInfo> impl
final TypeMigrationUsageInfo info,
final PsiType migrationType,
final TypeMigrationLabeler labeler,
final TypeMigrationTreeBuilder builder,
final HashSet<TypeMigrationUsageInfo> parents,
final HashMap<TypeMigrationUsageInfo, Set<MigrationNode>> processed) {
super(project, info);
myLabeler = labeler;
myMigrationType = migrationType;
myBuilder = builder;
myProcessed = processed;
myParents = parents;
@@ -99,7 +96,7 @@ public class MigrationNode extends AbstractTreeNode<TypeMigrationUsageInfo> impl
parents.add(info);
final MigrationNode migrationNode =
new MigrationNode(getProject(), info, root.getSecond(), myLabeler, myBuilder, parents, myProcessed);
new MigrationNode(getProject(), info, root.getSecond(), myLabeler, parents, myProcessed);
if (myInfo.isExcluded()) {
info.setExcluded(true);
@@ -37,7 +37,6 @@ import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.psi.util.PsiFormatUtilBase;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.typeMigration.ChangeTypeSignatureHandler;
import com.intellij.refactoring.typeMigration.TypeMigrationLabeler;
import com.intellij.refactoring.typeMigration.TypeMigrationProcessor;
import com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo;
@@ -68,7 +67,9 @@ import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
@@ -79,7 +80,7 @@ public class MigrationPanel extends JPanel implements Disposable {
@NonNls private static final String MIGRATION_USAGES = "migration.usages";
private static final DataKey<TypeMigrationUsageInfo[]> MIGRATION_USAGES_KEYS = DataKey.create(MIGRATION_USAGES);
private final PsiElement myInitialRoot;
private final PsiElement[] myInitialRoots;
private final TypeMigrationLabeler myLabeler;
@@ -89,15 +90,16 @@ public class MigrationPanel extends JPanel implements Disposable {
private final MigrationUsagesPanel myUsagesPanel;
private final MigrationConflictsPanel myConflictsPanel;
public MigrationPanel(final PsiElement root, TypeMigrationLabeler labeler, final Project project, final boolean previewUsages) {
public MigrationPanel(final PsiElement[] roots, TypeMigrationLabeler labeler, final Project project, final boolean previewUsages) {
super(new BorderLayout());
myInitialRoot = root;
myInitialRoots = roots;
myLabeler = labeler;
myProject = project;
myRootsTree = new MyTree(new DefaultTreeModel(new DefaultMutableTreeNode()));
final TypeMigrationTreeBuilder builder = new TypeMigrationTreeBuilder(myRootsTree, project);
final MigrationRootNode currentRoot = new MigrationRootNode(project, myLabeler, builder, root, previewUsages);
final MigrationRootNode currentRoot = new MigrationRootNode(project, myLabeler, roots, previewUsages);
builder.setRoot(currentRoot);
initTree(myRootsTree);
myRootsTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
@@ -254,7 +256,9 @@ public class MigrationPanel extends JPanel implements Disposable {
UsageViewManager.getInstance(myProject).closeContent(myContent);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ChangeTypeSignatureHandler.invoke(myProject, myInitialRoot, myLabeler.getRules(), null);
final TypeMigrationDialog.MultipleElements dialog =
new TypeMigrationDialog.MultipleElements(myProject, myInitialRoots, myLabeler.getMigrationRootTypeFunction(), myLabeler.getRules());
dialog.show();
}
});
}
@@ -37,18 +37,16 @@ import java.util.*;
public class MigrationRootNode extends AbstractTreeNode<TypeMigrationLabeler> implements DuplicateNodeRenderer.DuplicatableNode {
private final TypeMigrationLabeler myLabeler;
private List<MigrationNode> myCachedChildren;
private final TypeMigrationTreeBuilder myBuilder;
private final PsiElement myRoot;
private final PsiElement myRoots[];
private final boolean myPreviewUsages;
protected MigrationRootNode(Project project,
TypeMigrationLabeler labeler,
final TypeMigrationTreeBuilder builder, final PsiElement root,
final PsiElement[] roots,
final boolean previewUsages) {
super(project, labeler);
myLabeler = labeler;
myBuilder = builder;
myRoot = root;
myRoots = roots;
myPreviewUsages = previewUsages;
}
@@ -62,7 +60,9 @@ public class MigrationRootNode extends AbstractTreeNode<TypeMigrationLabeler> im
}
}
else {
addRoot(new TypeMigrationUsageInfo(myRoot), myLabeler.getRules().getMigrationRootType());
for (PsiElement root : myRoots) {
addRoot(new TypeMigrationUsageInfo(root), myLabeler.getMigrationRootTypeFunction().fun(root));
}
}
}
return myCachedChildren;
@@ -72,7 +72,7 @@ public class MigrationRootNode extends AbstractTreeNode<TypeMigrationLabeler> im
final HashSet<TypeMigrationUsageInfo> parents = new HashSet<TypeMigrationUsageInfo>();
parents.add(info);
final MigrationNode migrationNode =
new MigrationNode(getProject(), info, migrationType, myLabeler, myBuilder, parents, new HashMap<TypeMigrationUsageInfo, Set<MigrationNode>>());
new MigrationNode(getProject(), info, migrationType, myLabeler, parents, new HashMap<TypeMigrationUsageInfo, Set<MigrationNode>>());
myCachedChildren.add(migrationNode);
}
@@ -41,6 +41,8 @@ import com.intellij.refactoring.typeMigration.TypeMigrationRules;
import com.intellij.refactoring.ui.RefactoringDialog;
import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
import com.intellij.ui.EditorComboBox;
import com.intellij.util.Function;
import com.intellij.util.Functions;
import com.intellij.util.VisibilityUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -56,52 +58,22 @@ import java.util.List;
* @author anna
* Date: 25-Mar-2008
*/
public class TypeMigrationDialog extends RefactoringDialog {
public abstract class TypeMigrationDialog extends RefactoringDialog {
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.typeMigration.ui.TypeMigrationDialog");
public static final String REFACTORING_NAME = "Type Migration";
private final EditorComboBox myToTypeEditor;
private final PsiElement myRoot;
protected final PsiElement[] myRoots;
private TypeMigrationRules myRules;
private final PsiTypeCodeFragment myTypeCodeFragment;
private final ScopeChooserCombo myScopeChooserCombo;
public TypeMigrationDialog(@NotNull Project project, PsiElement root, TypeMigrationRules rules) {
public TypeMigrationDialog(@NotNull Project project,
PsiElement roots[],
TypeMigrationRules rules) {
super(project, false);
myRoot = root;
myRoots = roots;
myRules = rules;
final PsiType migrationRootType = rules != null ? rules.getMigrationRootType() : null;
final PsiType rootType = getRootType();
final String text = migrationRootType != null ? migrationRootType.getCanonicalText(true) :
rootType != null ? rootType.getCanonicalText(true) : "";
int flags = 0;
if (root instanceof PsiParameter) {
final PsiElement scope = ((PsiParameter)root).getDeclarationScope();
if (scope instanceof PsiMethod) {
flags |= JavaCodeFragmentFactory.ALLOW_ELLIPSIS;
}
else if (scope instanceof PsiCatchSection && PsiUtil.getLanguageLevel(root).isAtLeast(LanguageLevel.JDK_1_7)) {
flags |= JavaCodeFragmentFactory.ALLOW_DISJUNCTION;
}
}
myTypeCodeFragment = JavaCodeFragmentFactory.getInstance(project).createTypeCodeFragment(text, root, true, flags);
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
final Document document = documentManager.getDocument(myTypeCodeFragment);
assert document != null;
myToTypeEditor = new EditorComboBox(document, project, StdFileTypes.JAVA);
final String[] types = getValidTypes(project, root);
myToTypeEditor.setHistory(types != null ? types : new String[]{document.getText()});
document.addDocumentListener(new DocumentAdapter() {
@Override
public void documentChanged(final DocumentEvent e) {
documentManager.commitDocument(document);
validateButtons();
}
});
myScopeChooserCombo = new ScopeChooserCombo(project, false, true, FindSettings.getInstance().getDefaultScopeName());
Disposer.register(myDisposable, myScopeChooserCombo);
myScopeChooserCombo.getChildComponent().addActionListener(new ActionListener() {
@@ -109,115 +81,29 @@ public class TypeMigrationDialog extends RefactoringDialog {
validateButtons();
}
});
init();
setTitle(REFACTORING_NAME);
}
public PsiElement getRoot() {
return myRoot;
}
@Nullable
public PsiType getMigrationType() {
try {
return myTypeCodeFragment.getType();
}
catch (PsiTypeCodeFragment.TypeSyntaxException e) {
LOG.info(e);
return null;
}
catch (PsiTypeCodeFragment.NoTypeException e) {
LOG.info(e);
return null;
}
}
@Nullable
private String[] getValidTypes(final Project project, final PsiElement root) {
if (root instanceof PsiField || root instanceof PsiMethod) {
final PsiModifierList modifierList = ((PsiModifierListOwner)root).getModifierList();
if (VisibilityUtil.compare(VisibilityUtil.getVisibilityModifier(modifierList), PsiModifier.PRIVATE) < 0) return null;
}
final List<PsiExpression> expressions = new ArrayList<PsiExpression>();
for (PsiReference reference : ReferencesSearch.search(root, GlobalSearchScope.fileScope(root.getContainingFile()))) {
final PsiElement element = reference.getElement();
final PsiExpression expr = PsiTreeUtil.getParentOfType(element, PsiExpression.class, false);
if (expr != null) {
expressions.add(expr);
}
}
try {
final PsiExpression[] occurrences = expressions.toArray(new PsiExpression[expressions.size()]);
final PsiType[] psiTypes = new TypeSelectorManagerImpl(project, myTypeCodeFragment.getType(), occurrences).getTypesForAll();
if (psiTypes.length > 0) {
final String[] history = new String[psiTypes.length];
for (int i = 0; i < psiTypes.length; i++) {
PsiType psiType = psiTypes[i];
history[i] = psiType.getCanonicalText(true);
}
return history;
}
}
catch (PsiTypeCodeFragment.TypeSyntaxException e) {
LOG.info(e);
return null;
}
catch (PsiTypeCodeFragment.NoTypeException e) {
LOG.info(e);
return null;
}
return null;
}
@Override
protected void canRun() throws ConfigurationException {
if (!checkType(getMigrationType())) throw new ConfigurationException("\'" + myTypeCodeFragment.getText() + "\' is invalid type");
if (myScopeChooserCombo.getSelectedScope() == null) throw new ConfigurationException("Scope is not chosen");
}
private static boolean checkType(final PsiType type) {
if (type == null) return false;
if (!type.isValid()) return false;
if (type instanceof PsiClassType){
final PsiClassType psiClassType = (PsiClassType)type;
if (psiClassType.resolve() == null) return false;
final PsiType[] types = psiClassType.getParameters();
for (PsiType paramType : types) {
if (paramType instanceof PsiPrimitiveType ||
(paramType instanceof PsiWildcardType && ((PsiWildcardType)paramType).getBound() instanceof PsiPrimitiveType)) return false;
if (!checkType(paramType)) return false;
}
}
if (type instanceof PsiArrayType) {
return checkType(type.getDeepComponentType());
}
return true;
}
@Override
protected void doAction() {
FindSettings.getInstance().setDefaultScopeName(myScopeChooserCombo.getSelectedScopeName());
final PsiType rootType = getRootType();
final PsiType migrationType = getMigrationType();
if (migrationType == null || ChangeSignatureUtil.deepTypeEqual(rootType, migrationType)) {
close(DialogWrapper.OK_EXIT_CODE);
return;
}
if (myRules == null) {
myRules = new TypeMigrationRules();
myRules.setMigrationRootType(migrationType);
myRules.setBoundScope(myScopeChooserCombo.getSelectedScope());
}
invokeRefactoring(new TypeMigrationProcessor(myProject, myRoot, myRules));
invokeRefactoring(new TypeMigrationProcessor(myProject, myRoots, getMigrationTypeFunction(), myRules));
}
@Nullable
private PsiType getRootType() {
return TypeMigrationLabeler.getElementType(myRoot);
@NotNull
protected abstract Function<PsiElement, PsiType> getMigrationTypeFunction();
protected void appendMigrationTypeEditor(JPanel panel, GridBagConstraints cs) {
}
@Override
@@ -225,11 +111,7 @@ public class TypeMigrationDialog extends RefactoringDialog {
final JPanel panel = new JPanel(new GridBagLayout());
final GridBagConstraints gc = new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1, 0, GridBagConstraints.NORTHWEST,
GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0, 0), 0, 0);
final PsiType type = getRootType();
final String typeText = type != null ? type.getPresentableText() : "<unknown>";
panel.add(new JLabel("Migrate " + getElementPresentation(myRoot) + " \"" + typeText + "\" to"), gc);
panel.add(myToTypeEditor, gc);
appendMigrationTypeEditor(panel, gc);
LabeledComponent<ScopeChooserCombo> scopeChooserComponent = new LabeledComponent<ScopeChooserCombo>();
scopeChooserComponent.setComponent(myScopeChooserCombo);
scopeChooserComponent.setText("Choose scope where change signature may occur");
@@ -239,42 +121,215 @@ public class TypeMigrationDialog extends RefactoringDialog {
@Override
public JComponent getPreferredFocusedComponent() {
return myToTypeEditor;
}
private static String getElementPresentation(PsiElement element) {
if (element instanceof PsiMethod) {
return "return type of method " + ((PsiMethod)element).getName();
}
if (element instanceof PsiField) {
return "type of field " + ((PsiField)element).getName();
}
if (element instanceof PsiLocalVariable) {
return "type of variable " + ((PsiLocalVariable)element).getName();
}
if (element instanceof PsiReferenceParameterList) {
return "class type arguments ";
}
if (element instanceof PsiParameter) {
final PsiParameter param = (PsiParameter)element;
String result = "type of parameter " + param.getName();
if (param.getParent() instanceof PsiParameterList) {
final PsiMethod method = PsiTreeUtil.getParentOfType(param, PsiMethod.class);
assert method != null;
result += " of method " + method.getName();
}
return result;
}
return element.toString();
return myScopeChooserCombo;
}
@Override
protected void doHelpAction() {
HelpManager.getInstance().invokeHelp("reference.typeMigrationDialog");
}
public static class MultipleElements extends TypeMigrationDialog {
private final Function<PsiElement, PsiType> myMigrationTypeFunction;
public MultipleElements(@NotNull Project project, PsiElement[] roots, Function<PsiElement, PsiType> migrationTypeFunction, TypeMigrationRules rules) {
super(project, roots, rules);
myMigrationTypeFunction = migrationTypeFunction;
init();
}
@NotNull
@Override
protected Function<PsiElement, PsiType> getMigrationTypeFunction() {
return myMigrationTypeFunction;
}
}
public static class SingleElement extends TypeMigrationDialog {
private final PsiTypeCodeFragment myTypeCodeFragment;
private final EditorComboBox myToTypeEditor;
public SingleElement(@NotNull Project project,
PsiElement root,
PsiType migrationType,
TypeMigrationRules rules) {
super(project, new PsiElement[]{root}, rules);
final PsiType rootType = getRootType();
final String text = migrationType != null ? migrationType.getCanonicalText(true) :
rootType != null ? rootType.getCanonicalText(true) : "";
int flags = 0;
if (root instanceof PsiParameter) {
final PsiElement scope = ((PsiParameter)root).getDeclarationScope();
if (scope instanceof PsiMethod) {
flags |= JavaCodeFragmentFactory.ALLOW_ELLIPSIS;
}
else if (scope instanceof PsiCatchSection && PsiUtil.getLanguageLevel(root).isAtLeast(LanguageLevel.JDK_1_7)) {
flags |= JavaCodeFragmentFactory.ALLOW_DISJUNCTION;
}
}
myTypeCodeFragment = JavaCodeFragmentFactory.getInstance(project).createTypeCodeFragment(text, root, true, flags);
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
final Document document = documentManager.getDocument(myTypeCodeFragment);
assert document != null;
myToTypeEditor = new EditorComboBox(document, project, StdFileTypes.JAVA);
final String[] types = getValidTypes(project, root);
myToTypeEditor.setHistory(types != null ? types : new String[]{document.getText()});
document.addDocumentListener(new DocumentAdapter() {
@Override
public void documentChanged(final DocumentEvent e) {
documentManager.commitDocument(document);
validateButtons();
}
});
init();
}
@Override
protected void canRun() throws ConfigurationException {
super.canRun();
if (!checkType(getMigrationType())) throw new ConfigurationException("\'" + myTypeCodeFragment.getText() + "\' is invalid type");
}
@Override
public JComponent getPreferredFocusedComponent() {
return myToTypeEditor;
}
protected void appendMigrationTypeEditor(JPanel panel, GridBagConstraints gc) {
final PsiType type = getRootType();
final String typeText = type != null ? type.getPresentableText() : "<unknown>";
panel.add(new JLabel("Migrate " + getElementPresentation(myRoots[0]) + " \"" + typeText + "\" to"), gc);
panel.add(myToTypeEditor, gc);
}
@Nullable
private String[] getValidTypes(final Project project, final PsiElement root) {
if (root instanceof PsiField || root instanceof PsiMethod) {
final PsiModifierList modifierList = ((PsiModifierListOwner)root).getModifierList();
if (VisibilityUtil.compare(VisibilityUtil.getVisibilityModifier(modifierList), PsiModifier.PRIVATE) < 0) return null;
}
final List<PsiExpression> expressions = new ArrayList<PsiExpression>();
for (PsiReference reference : ReferencesSearch.search(root, GlobalSearchScope.fileScope(root.getContainingFile()))) {
final PsiElement element = reference.getElement();
final PsiExpression expr = PsiTreeUtil.getParentOfType(element, PsiExpression.class, false);
if (expr != null) {
expressions.add(expr);
}
}
try {
final PsiExpression[] occurrences = expressions.toArray(new PsiExpression[expressions.size()]);
final PsiType[] psiTypes = new TypeSelectorManagerImpl(project, myTypeCodeFragment.getType(), occurrences).getTypesForAll();
if (psiTypes.length > 0) {
final String[] history = new String[psiTypes.length];
for (int i = 0; i < psiTypes.length; i++) {
PsiType psiType = psiTypes[i];
history[i] = psiType.getCanonicalText(true);
}
return history;
}
}
catch (PsiTypeCodeFragment.TypeSyntaxException e) {
LOG.info(e);
return null;
}
catch (PsiTypeCodeFragment.NoTypeException e) {
LOG.info(e);
return null;
}
return null;
}
@Override
protected void doAction() {
final PsiType rootType = getRootType();
final PsiType migrationType = getMigrationType();
if (migrationType == null || ChangeSignatureUtil.deepTypeEqual(rootType, migrationType)) {
close(DialogWrapper.OK_EXIT_CODE);
return;
}
super.doAction();
}
@NotNull
@Override
protected Function<PsiElement, PsiType> getMigrationTypeFunction() {
return Functions.constant(getMigrationType());
}
@Nullable
public PsiType getMigrationType() {
try {
return myTypeCodeFragment.getType();
}
catch (PsiTypeCodeFragment.TypeSyntaxException e) {
LOG.info(e);
return null;
}
catch (PsiTypeCodeFragment.NoTypeException e) {
LOG.info(e);
return null;
}
}
@Nullable
private PsiType getRootType() {
return TypeMigrationLabeler.getElementType(myRoots[0]);
}
private static String getElementPresentation(PsiElement element) {
if (element instanceof PsiMethod) {
return "return type of method " + ((PsiMethod)element).getName();
}
if (element instanceof PsiField) {
return "type of field " + ((PsiField)element).getName();
}
if (element instanceof PsiLocalVariable) {
return "type of variable " + ((PsiLocalVariable)element).getName();
}
if (element instanceof PsiReferenceParameterList) {
return "class type arguments ";
}
if (element instanceof PsiParameter) {
final PsiParameter param = (PsiParameter)element;
String result = "type of parameter " + param.getName();
if (param.getParent() instanceof PsiParameterList) {
final PsiMethod method = PsiTreeUtil.getParentOfType(param, PsiMethod.class);
assert method != null;
result += " of method " + method.getName();
}
return result;
}
return element.toString();
}
private static boolean checkType(final PsiType type) {
if (type == null) return false;
if (!type.isValid()) return false;
if (type instanceof PsiClassType){
final PsiClassType psiClassType = (PsiClassType)type;
if (psiClassType.resolve() == null) return false;
final PsiType[] types = psiClassType.getParameters();
for (PsiType paramType : types) {
if (paramType instanceof PsiPrimitiveType ||
(paramType instanceof PsiWildcardType && ((PsiWildcardType)paramType).getBound() instanceof PsiPrimitiveType)) {
return false;
}
if (!checkType(paramType)) return false;
}
}
if (type instanceof PsiArrayType) {
return checkType(type.getDeepComponentType());
}
return true;
}
}
}
@@ -22,6 +22,7 @@ import com.intellij.openapi.project.Project;
import javax.swing.*;
import javax.swing.tree.DefaultTreeModel;
import java.util.List;
/**
* @author anna
@@ -38,6 +39,6 @@ public class TypeMigrationTreeBuilder extends AbstractTreeBuilder{
}
public void setRoot(MigrationRootNode root) {
((TypeMigrationTreeStructure)getTreeStructure()).setRoot(root);
((TypeMigrationTreeStructure)getTreeStructure()).setRoots(root);
}
}
@@ -15,10 +15,14 @@
*/
package com.intellij.refactoring.typeMigration.ui;
import com.intellij.ide.projectView.PresentationData;
import com.intellij.ide.projectView.TreeStructureProvider;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.ide.util.treeView.AbstractTreeStructureBase;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -33,7 +37,7 @@ public class TypeMigrationTreeStructure extends AbstractTreeStructureBase {
super(project);
}
public void setRoot(final MigrationRootNode root) {
public void setRoots(final MigrationRootNode root) {
myRoot = root;
}
@@ -23,17 +23,17 @@ import org.jetbrains.annotations.NotNull;
* Date: 27-Mar-2008
*/
public class OverridenUsageInfo extends TypeMigrationUsageInfo {
private OverriderUsageInfo[] myOverriders;
private volatile String myMigrateMethodName;
public OverridenUsageInfo(@NotNull PsiElement element) {
super(element);
}
public OverriderUsageInfo[] getOverridingElements() {
return myOverriders;
public String getMigrateMethodName() {
return myMigrateMethodName;
}
public void setOverriders(final OverriderUsageInfo[] overriders) {
myOverriders = overriders;
public void setMigrateMethodName(String migrateMethodName) {
myMigrateMethodName = migrateMethodName;
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
@@ -15,6 +15,7 @@
*/
package com.intellij.psi.util;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
@@ -256,4 +257,18 @@ public class ClassUtil {
public static PsiClass findPsiClassByJVMName(@NotNull PsiManager manager, @NotNull String jvmClassName) {
return findPsiClass(manager, jvmClassName.replace('/', '.'), null, true);
}
public static boolean isTopLevelClass(@NotNull PsiClass aClass) {
if (aClass.getContainingClass() != null) {
return false;
}
if (aClass instanceof PsiAnonymousClass) {
return false;
}
final PsiFile parentFile = aClass.getContainingFile();
// do not select JspClass
return parentFile != null && parentFile.getLanguage() == JavaLanguage.INSTANCE;
}
}
@@ -298,18 +298,32 @@ public class MethodSignatureUtil {
}
/**
* * 8.4.4 Generic Methods :: same type parameters condition
* Two methods or constructors M and N have the same type parameters if both of the following are true:
* • M and N have same number of type parameters (possibly zero).
* • Where A1, ..., An are the type parameters of M and B1, ..., Bn are the type parameters of N, let θ=[B1:=A1, ..., Bn:=An].
* Then, for all i (1 ≤ i ≤ n), the bound of Ai is the same type as θ applied to the bound of Bi.
*
* @param methodSignature method signature
* @param superMethodSignature super method signature
* @return null if signatures do not match
*/
@Nullable
public static PsiSubstitutor getSuperMethodSignatureSubstitutor(@NotNull MethodSignature methodSignature, @NotNull MethodSignature superMethodSignature) {
PsiSubstitutor result = getSuperMethodSignatureSubstitutorImpl(methodSignature, superMethodSignature);
if (result == null) return null;
PsiTypeParameter[] methodTypeParameters = methodSignature.getTypeParameters();
PsiTypeParameter[] superTypeParameters = superMethodSignature.getTypeParameters();
PsiSubstitutor methodSubstitutor = methodSignature.getSubstitutor();
// both methods are parameterized and number of parameters mismatch
if (methodTypeParameters.length != superTypeParameters.length) return null;
PsiSubstitutor result = superMethodSignature.getSubstitutor();
for (int i = 0; i < methodTypeParameters.length; i++) {
PsiTypeParameter methodTypeParameter = methodTypeParameters[i];
PsiElementFactory factory = JavaPsiFacade.getInstance(methodTypeParameter.getProject()).getElementFactory();
result = result.put(superTypeParameters[i], factory.createType(methodTypeParameter));
}
final PsiSubstitutor methodSubstitutor = methodSignature.getSubstitutor();
//check bounds
for (int i = 0; i < methodTypeParameters.length; i++) {
@@ -332,26 +346,6 @@ public class MethodSignatureUtil {
return result;
}
@Nullable
private static PsiSubstitutor getSuperMethodSignatureSubstitutorImpl(@NotNull MethodSignature methodSignature, @NotNull MethodSignature superSignature) {
// normalize generic method declarations: correlate type parameters
// todo: correlate type params by name?
PsiTypeParameter[] methodTypeParameters = methodSignature.getTypeParameters();
PsiTypeParameter[] superTypeParameters = superSignature.getTypeParameters();
// both methods are parameterized and number of parameters mismatch
if (methodTypeParameters.length != superTypeParameters.length) return null;
PsiSubstitutor result = superSignature.getSubstitutor();
for (int i = 0; i < methodTypeParameters.length; i++) {
PsiTypeParameter methodTypeParameter = methodTypeParameters[i];
PsiElementFactory factory = JavaPsiFacade.getInstance(methodTypeParameter.getProject()).getElementFactory();
result = result.put(superTypeParameters[i], factory.createType(methodTypeParameter));
}
return result;
}
@NotNull
public static PsiSubstitutor combineSubstitutors(@NotNull PsiSubstitutor substitutor1, @NotNull PsiSubstitutor substitutor2) {
if (substitutor1 == PsiSubstitutor.EMPTY) return substitutor2;
@@ -398,4 +392,36 @@ public class MethodSignatureUtil {
}
return true;
}
/**
* 8.4.5 Method Result :: return type substitutable
*/
public static boolean isReturnTypeSubstitutable(MethodSignature d1, MethodSignature d2, PsiType r1, PsiType r2) {
//If R1 is void then R2 is void.
if (PsiType.VOID.equals(r1)) {
return PsiType.VOID.equals(r2);
}
//If R1 is a primitive type then R2 is identical to R1.
if (r1 instanceof PsiPrimitiveType) {
return r1.equals(r2);
}
if (r1 instanceof PsiClassType && r2 != null) {
//R1, adapted to the type parameters of d2 (§8.4.4), is a subtype of R2.
final PsiSubstitutor adaptingSubstitutor = getSuperMethodSignatureSubstitutor(d1, d2);
if (adaptingSubstitutor != null && r2.isAssignableFrom(adaptingSubstitutor.substitute(r1))) {
return true;
}
//d1 does not have the same signature as d2 (§8.4.2), and R1 = |R2|.
if (!areSignaturesEqual(d1, d2)) {
return r1.equals(TypeConversionUtil.erasure(r2));
}
}
return Comparing.equal(r1, r2);
}
}
@@ -137,9 +137,9 @@ public class TypeConversionUtil {
if (languageLevel.isAtLeast(LanguageLevel.JDK_1_7)) {
final PsiClassType classType = (PsiClassType)fromType;
final PsiClass psiClass = classType.resolve();
if (psiClass == null || psiClass instanceof PsiTypeParameter) return false;
if (psiClass == null) return false;
final PsiClassType boxedType = ((PsiPrimitiveType)toType).getBoxedType(psiClass.getManager(), psiClass.getResolveScope());
if (boxedType != null && isAssignable(fromType, boxedType)) {
if (boxedType != null && isNarrowingReferenceConversionAllowed(fromType, boxedType)) {
return true;
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
@@ -31,6 +31,8 @@ import com.intellij.psi.util.*;
import com.intellij.util.*;
import com.intellij.util.containers.ConcurrentFactoryMap;
import com.intellij.util.containers.FactoryMap;
import com.intellij.util.containers.hash.EqualityPolicy;
import com.intellij.util.containers.hash.LinkedHashMap;
import gnu.trove.THashMap;
import gnu.trove.THashSet;
import gnu.trove.TObjectHashingStrategy;
@@ -135,7 +137,37 @@ public class PsiSuperMethodImplUtil {
boolean isInRawContext,
GlobalSearchScope resolveScope) {
ProgressManager.checkCanceled();
Map<MethodSignature, HierarchicalMethodSignature> result = new LinkedHashMap<MethodSignature, HierarchicalMethodSignature>();
Map<MethodSignature, HierarchicalMethodSignature> result = new LinkedHashMap<MethodSignature, HierarchicalMethodSignature>(
new EqualityPolicy<MethodSignature>() {
@Override
public int getHashCode(MethodSignature object) {
return object.hashCode();
}
@Override
public boolean isEqual(MethodSignature o1, MethodSignature o2) {
if (o1.equals(o2)) {
final PsiMethod method1 = ((MethodSignatureBackedByPsiMethod)o1).getMethod();
final PsiType returnType1 = method1.getReturnType();
final PsiMethod method2 = ((MethodSignatureBackedByPsiMethod)o2).getMethod();
final PsiType returnType2 = method2.getReturnType();
if (method1.hasModifierProperty(PsiModifier.STATIC) || method2.hasModifierProperty(PsiModifier.STATIC)) {
return true;
}
if (MethodSignatureUtil.isReturnTypeSubstitutable(o1, o2, returnType1, returnType2)) {
return true;
}
final PsiClass containingClass1 = method1.getContainingClass();
final PsiClass containingClass2 = method2.getContainingClass();
if (containingClass1 != null && containingClass2 != null) {
return containingClass1.isAnnotationType() || containingClass2.isAnnotationType();
}
}
return false;
}
});
final Map<MethodSignature, List<PsiMethod>> sameParameterErasureMethods = new THashMap<MethodSignature, List<PsiMethod>>(MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY);
Map<MethodSignature, HierarchicalMethodSignatureImpl> map = new THashMap<MethodSignature, HierarchicalMethodSignatureImpl>(new TObjectHashingStrategy<MethodSignature>() {
@@ -443,4 +475,4 @@ public class PsiSuperMethodImplUtil {
}
return false;
}
}
}
@@ -150,7 +150,7 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
}
}
final PsiElement element = resolve.getElement();
if (element == null) {
if (element == null || resolve instanceof MethodCandidateInfo && !((MethodCandidateInfo)resolve).isApplicable()) {
session.registerIncompatibleErrorMessage("No compile-time declaration for the method reference is found");
return false;
}
@@ -133,6 +133,15 @@ public class MethodReferenceResolver implements ResolveCache.PolyVariantContextR
}
return session.infer(method.getParameterList().getParameters(), null, null);
}
@Override
public boolean isApplicable() {
if (signature == null) return false;
final PsiType[] argTypes = signature.getParameterTypes();
boolean hasReceiver = PsiMethodReferenceUtil.isSecondSearchPossible(argTypes, qualifierResolveResult, reference);
return MethodReferenceConflictResolver.isApplicableByFirstSearch(this, argTypes, hasReceiver, interfaceMethod.isVarArgs()) != null;
}
};
}
};
@@ -211,8 +220,14 @@ public class MethodReferenceResolver implements ResolveCache.PolyVariantContextR
protected CandidateInfo guardedOverloadResolution(@NotNull List<CandidateInfo> conflicts) {
if (mySignature == null) return null;
if (conflicts.size() > 1) checkSameSignatures(conflicts);
if (conflicts.size() > 1) checkAccessStaticLevels(conflicts, true);
if (conflicts.isEmpty()) return null;
if (conflicts.size() == 1) return conflicts.get(0);
checkSameSignatures(conflicts);
if (conflicts.size() == 1) return conflicts.get(0);
checkAccessStaticLevels(conflicts, true);
if (conflicts.size() == 1) return conflicts.get(0);
final PsiType[] argTypes = mySignature.getParameterTypes();
boolean hasReceiver = PsiMethodReferenceUtil.isSecondSearchPossible(argTypes, myQualifierResolveResult, myReferenceExpression);
@@ -222,23 +237,9 @@ public class MethodReferenceResolver implements ResolveCache.PolyVariantContextR
for (CandidateInfo conflict : conflicts) {
if (!(conflict instanceof MethodCandidateInfo)) continue;
final PsiMethod psiMethod = ((MethodCandidateInfo)conflict).getElement();
final PsiSubstitutor substitutor = ((MethodCandidateInfo)conflict).getSubstitutor(false);
final PsiType[] parameterTypes = psiMethod.getSignature(substitutor).getParameterTypes();
final boolean varargs = ((MethodCandidateInfo)conflict).isVarargs();
if (varargs && (!psiMethod.isVarArgs() || myFunctionalMethodVarArgs)) continue;
if ((varargs || argTypes.length == parameterTypes.length) &&
PsiMethodReferenceUtil.isCorrectAssignment(parameterTypes, argTypes, varargs, 0)) {
firstCandidates.add(conflict);
}
if (hasReceiver &&
(varargs || argTypes.length == parameterTypes.length + 1) &&
PsiMethodReferenceUtil.isCorrectAssignment(parameterTypes, argTypes, varargs, 1)) {
secondCandidates.add(conflict);
final Boolean applicableByFirstSearch = isApplicableByFirstSearch(conflict, argTypes, hasReceiver, myFunctionalMethodVarArgs);
if (applicableByFirstSearch != null) {
(applicableByFirstSearch ? firstCandidates : secondCandidates).add(conflict);
}
}
@@ -264,12 +265,42 @@ public class MethodReferenceResolver implements ResolveCache.PolyVariantContextR
return !firstCandidates.isEmpty() ? firstCandidates.get(0) : secondCandidates.get(0);
}
if (firstCandidates.isEmpty() && secondCandidates.isEmpty()) {
return null;
}
conflicts.clear();
firstCandidates.addAll(secondCandidates);
conflicts.addAll(firstCandidates);
return null;
}
private static Boolean isApplicableByFirstSearch(CandidateInfo conflict, PsiType[] argTypes,
boolean hasReceiver,
boolean functionalMethodVarArgs) {
final PsiMethod psiMethod = ((MethodCandidateInfo)conflict).getElement();
final PsiSubstitutor substitutor = ((MethodCandidateInfo)conflict).getSubstitutor(false);
final PsiType[] parameterTypes = psiMethod.getSignature(substitutor).getParameterTypes();
final boolean varargs = ((MethodCandidateInfo)conflict).isVarargs();
if (varargs && (!psiMethod.isVarArgs() || functionalMethodVarArgs)) {
return null;
}
if ((varargs || argTypes.length == parameterTypes.length) &&
PsiMethodReferenceUtil.isCorrectAssignment(parameterTypes, argTypes, varargs, 0)) {
return true;
}
if (hasReceiver &&
(varargs || argTypes.length == parameterTypes.length + 1) &&
PsiMethodReferenceUtil.isCorrectAssignment(parameterTypes, argTypes, varargs, 1)) {
return false;
}
return null;
}
private boolean resolveConflicts(List<CandidateInfo> firstCandidates, List<CandidateInfo> secondCandidates, int applicabilityLevel) {
final int firstApplicability = checkApplicability(firstCandidates);
@@ -450,6 +450,10 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
map.remove(this);
}
if (result instanceof MethodCandidateInfo && !((MethodCandidateInfo)result).isApplicable()) {
return false;
}
final PsiElement resolve = result.getElement();
if (resolve == null) {
return false;
@@ -0,0 +1,35 @@
class Test {
public <T> void foo(T valIn){
double val = (double ) valIn;
}
public <T extends Double> void foo1(T valIn){
double val = (double ) valIn;
}
public <T extends String> void foo2(T valIn){
double val = <error descr="Inconvertible types; cannot cast 'T' to 'double'">(double ) valIn</error>;
}
public <T extends S, S extends Double> void foo2(T valIn){
double val = (double ) valIn;
}
}
class Foo<T> {
private T _value;
T getValue() {
return _value;
}
static Foo<?> getFoo() {
return new Foo<>();
}
public static void main(String[] args) {
Foo<?> foo = getFoo();
double value = (double) foo.getValue();
}
}
@@ -0,0 +1,8 @@
interface I<T, S extends Throwable> {
int foo(T x);
void foo(S x);
}
class A implements I<Throwable, Throwable>{
public <error descr="'foo(Throwable)' in 'A' clashes with 'foo(T)' in 'I'; attempting to use incompatible return type">void</error> foo(Throwable x) { }
}
@@ -0,0 +1,17 @@
class Foo<T> {
private T _value;
T getValue() {
return _value;
}
static Foo<?> getFoo() {
return new Foo<>();
}
public static void main(String[] args) {
Foo<?> foo = getFoo();
double value = <error descr="Inconvertible types; cannot cast 'capture<?>' to 'double'">(double) foo.getValue()</error>;
}
}
@@ -26,7 +26,7 @@ class AlienTest {
static {
IInt i1 = MyTest::<error descr="Cannot resolve method 'abracadabra'">abracadabra</error>;
IInt i2 = MyTest::<error descr="Cannot resolve method 'foo'">foo</error>;
IInt i2 = <error descr="Bad return type in method reference: cannot convert void to int">MyTest::foo</error>;
IInt i3 = MyTest::<error descr="Cannot resolve method 'bar'">bar</error>;
<error descr="Incompatible types. Found: '<method reference>', required: 'AlienTest.IIntInt'">IIntInt i4 = MyTest::bar;</error>
IInt i5 = <error descr="Non-static method cannot be referenced from a static context">MyTest::baz</error>;
@@ -70,8 +70,8 @@ class MyTest3<X> {
static void test(I<Integer> s) { }
public static void main(String[] args) {
I<Integer> s = MyTest3<String>::<error descr="Cannot resolve constructor 'MyTest3'">new</error>;
test(MyTest3<String>::<error descr="Cannot resolve constructor 'MyTest3'">new</error>);
I<Integer> s = <error descr="Bad return type in method reference: cannot convert MyTest3<java.lang.String> to MyTest3<java.lang.Integer>">MyTest3<String>::new</error>;
test(<error descr="Bad return type in method reference: cannot convert MyTest3<java.lang.String> to MyTest3<java.lang.Integer>">MyTest3<String>::new</error>);
}
}
@@ -109,7 +109,7 @@ class NonStaticInner2 {
static {
I1 i1 = NonStaticInner2.Inner :: <error descr="Cannot resolve constructor 'Inner'">new</error>;
I1 i1 = <error descr="An enclosing instance of type NonStaticInner2 is not in scope">NonStaticInner2.Inner :: new</error>;
}
{
@@ -12,7 +12,7 @@ class MyTest {
{
I i = Foo<String> :: foo;
I i1 = Foo<Integer> :: <error descr="Cannot resolve method 'foo'">foo</error>;
I i1 = <error descr="Non-static method cannot be referenced from a static context">Foo<Integer> :: foo</error>;
}
}
}
@@ -56,8 +56,8 @@ class MyTest {
{
I1 i_1 = <error descr="Non-static method cannot be referenced from a static context">MyTest::_1</error>;
I1 i_2 = MyTest::<error descr="Cannot resolve method '_2'">_2</error>;
I1 i_3 = MyTest::<error descr="Cannot resolve method '_3'">_3</error>;
I1 i_2 = <error descr="Non-static method cannot be referenced from a static context">MyTest::_2</error>;
I1 i_3 = <error descr="Non-static method cannot be referenced from a static context">MyTest::_3</error>;
I1 i_4 = MyTest::<error descr="Cannot resolve method '_4'">_4</error>;
I1 i1 = this::_1;
@@ -4,7 +4,7 @@ class Test {
void test() {
Comparator<Test> r2 = Test::yyy;
Comparator1<Test> c1 = <error descr="Non-static method cannot be referenced from a static context">Test::yyy</error>;
Comparator1<Test> c2 = Test::<error descr="Cannot resolve method 'xxx'">xxx</error>;
Comparator1<Test> c2 = <error descr="Non-static method cannot be referenced from a static context">Test::xxx</error>;
}
int yyy(Test... p) { return 1; }
int xxx(Test t) {return 42;}
@@ -4,6 +4,6 @@ import java.util.Comparator;
class Main {
public void test() {
Collections.sort(new ArrayList<>(), Comparator::<error descr="Cannot resolve method 'reversed'">reversed</error>);
Collections.sort(new ArrayList<>(), <error descr="Non-static method cannot be referenced from a static context">Comparator::reversed</error>);
}
}
File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More