Merge remote branch 'origin/master'

This commit is contained in:
irengrig
2013-02-28 16:15:30 +04:00
763 changed files with 14562 additions and 4938 deletions
+2 -2
View File
@@ -1,11 +1,11 @@
<component name="libraryTable">
<library name="winp">
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/winp-1.16-patched.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/winp-1.17-patched.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$PROJECT_DIR$/lib/src/winp-1.16-patched-src.zip!/" />
<root url="jar://$PROJECT_DIR$/lib/src/winp-1.17-patched-src.zip!/" />
</SOURCES>
</library>
</component>
+1 -1
View File
@@ -1 +1 @@
126.SNAPSHOT
128.SNAPSHOT
+1 -1
View File
@@ -106,7 +106,7 @@ def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps =
layouts.layout_core_upsource(home, paths.artifacts_core_upsource)
notifyArtifactBuilt(paths.artifacts_core_upsource)
if (buildJps) {
layouts.layout_jps(home, paths.artifacts_jps)
layouts.layoutCommunityJps(home, paths.artifacts_jps)
notifyArtifactBuilt(paths.artifacts_jps)
}
+29 -13
View File
@@ -23,11 +23,6 @@ target('default': "Developers update") {
ant.delete(dir: patchedDescriptorDir)
}
target('build-jps': 'Build JPS standalone distribution') {
println("Building jps standalone distribution")
layout_jps("$home/build/lib/jps")
}
String appInfoFileName() {
return "idea/IdeaApplicationInfo.xml"
}
@@ -183,11 +178,13 @@ def layoutFull(String home, String targetDirectory, String patchedDescriptorDir
layoutCommunityPlugins(home)
layoutPlugin("javaFX") {
dir("lib") {
jar("javaFX.jar") {
module("javaFX")
module("javaFX-CE")
dir("plugins") {
dir("javaFX") {
dir("lib") {
jar("javaFX.jar") {
module("javaFX")
module("javaFX-CE")
}
}
}
}
@@ -569,7 +566,7 @@ def reorder(String home, String targetDirectory) {
}
}
def layout_jps(String home, String target) {
def layoutCommunityJps(String home, String target) {
layout(target) {
jar("util.jar") {
module("annotations")
@@ -596,9 +593,27 @@ def layout_jps(String home, String target) {
jar("groovy_rt.jar") {
module("groovy_rt")
}
jar("ui-designer-jps-plugin.jar") {
module("ui-designer-jps-plugin")
jar("ui-designer-jps-plugin.jar") { module("ui-designer-jps-plugin") }
jar("android-jps-plugin.jar") {
module("android-jps-plugin")
module("android-common")
module("android-rt")
}
fileset(dir: "${home}/plugins/android/lib") {
include(name: "**/*.jar")
exclude(name: "**/ddmlib_1.jar")
}
jar("maven-jps-plugin.jar") { module("maven-jps-plugin") }
fileset(dir: "$home/plugins/maven/maven3-server-impl/lib/maven3/lib") {include(name: "plexus-utils-*.jar")}
jar("eclipse-jps-plugin.jar") {
module("common-eclipse-util")
module("eclipse-jps-plugin")
}
jar("devkit-jps-plugin.jar") { module("devkit-jps-plugin") }
jar("intellilang-jps-plugin.jar") { module("intellilang-jps-plugin") }
fileset(dir: "$home/lib") {
include(name: "jdom.jar")
include(name: "jna.jar")
@@ -606,6 +621,7 @@ def layout_jps(String home, String target) {
include(name: "asm4-all.jar")
include(name: "nanoxml-*.jar")
include(name: "protobuf-*.jar")
include(name: "cli-parser-*.jar")
include(name: "optimizedFileManager.jar")
include(name: "log4j.jar")
include(name: "jgoodies-forms.jar")
+2 -1
View File
@@ -235,7 +235,7 @@ libraryLicense(name: "TestNG", version: "5.7 snapshot", license: "Apache 2.0", u
libraryLicense(name: "Trilead SSH", libraryName: "trilead-ssh2", version: "build 213", license: "BSD style (see LICENSE.txt in trilead.jar)", url: "http://www.trilead.com/SSH_Library/")
libraryLicense(name: "Trove4j", version: "1.1 (with patches by JetBrains)", license: "LGPL", url: "http://trove4j.sourceforge.net/", licenseUrl: "http://trove4j.sourceforge.net/html/license.html")
libraryLicense(name: "Velocity", version: "1.7", license: "Apache 2.0", url: "http://velocity.apache.org/", licenseUrl: "http://velocity.apache.org/index.html")
libraryLicense(name: "winp", version: "1.16 (patched)", license: "MIT", url: "http://java.net/projects/winp", licenseUrl: "http://opensource.org/licenses/mit-license.php")
libraryLicense(name: "winp", version: "1.17 (patched)", license: "MIT", url: "http://java.net/projects/winp", licenseUrl: "http://opensource.org/licenses/mit-license.php")
libraryLicense(name: "Xalan", libraryName:"Xalan-2.7.1", version: "2.7.1", license: "Apache 2.0", url: "http://xml.apache.org/xalan-j/", licenseUrl: "http://xml.apache.org/xalan-j/")
libraryLicense(name: "Xerces", version: "2.9.1", license: "Apache 2.0", url: "http://xerces.apache.org/xerces2-j/", licenseUrl: "http://xerces.apache.org/xerces2-j/")
libraryLicense(name: "XML Commons (xml-apis.jar, resolver.jar)", version: "", license: "Apache 2.0, W3C Software License , public domain", url: "http://xml.apache.org/commons/", licenseUrl: "http://xml.apache.org/commons/licenses.html")
@@ -254,6 +254,7 @@ libraryLicense(name: "proxy-vole", libraryName: "proxy-vole", version: "20120920
libraryLicense(name: "Rhino JavaScript Engine", libraryName: "rhino-js-1_7R4", version: "1.7R4", license: "MPL 1.1", url: "http://www.mozilla.org/rhino/", licenseUrl: "http://www.mozilla.org/MPL/MPL-1.1.html")
libraryLicense(name: "asm-4.0-all", libraryName: "asm-4.0-all", version: "4.0", attachedTo: "ByteCodeViewer", license: "BSD", url: "http://asm.objectweb.org/", licenseUrl: "http://asm.objectweb.org/license.html")
libraryLicense(name: "jsr305", libraryName: "jsr305", version: "snapshot", license: "BSD", url: "http://code.google.com/p/jsr-305/", licenseUrl: "http://code.google.com/p/jsr-305/source/browse/trunk/ri/LICENSE")
libraryLicense(name: "jzlib", libraryName: "jzlib", version: "1.1.1", license: "BSD", url: "http://www.jcraft.com/jzlib/", licenseUrl: "http://www.jcraft.com/jzlib/LICENSE.txt")
jetbrainsLibrary("JPS")
jetbrainsLibrary("Maven Embedder")
jetbrainsLibrary("tcServiceMessages")
+16 -202
View File
@@ -4,7 +4,7 @@
<option name="EDITOR_FONT_SIZE" value="12" />
<option name="EDITOR_FONT_NAME" value="Menlo" />
<colors>
<option name="ADDED_LINES_COLOR" value="d6822" />
<option name="ADDED_LINES_COLOR" value="295622" />
<option name="ANNOTATIONS_COLOR" value="8b999f" />
<option name="CARET_COLOR" value="bbbbbb" />
<option name="CARET_ROW_COLOR" value="323232" />
@@ -26,19 +26,19 @@
<option name="FILESTATUS_changelistConflict" value="d5756c" />
<option name="FILESTATUS_modifiedOutside" value="6897bb" />
<option name="GUTTER_BACKGROUND" value="313335" />
<option name="INDENT_GUIDE" value="4d4d4d" />
<option name="INDENT_GUIDE" value="373737" />
<option name="LINE_NUMBERS_COLOR" value="888888" />
<option name="METHOD_SEPARATORS_COLOR" value="4d4d4d" />
<option name="MODIFIED_LINES_COLOR" value="7180" />
<option name="MODIFIED_LINES_COLOR" value="415f69" />
<option name="NOTIFICATION_BACKGROUND" value="5c5c42" />
<option name="READONLY_FRAGMENT_BACKGROUND" value="" />
<option name="RECURSIVE_CALL_ATTRIBUTES" value="574300" />
<option name="REMOTE_HOST_MAPPED_BACKGROUND_KEY" value="164716" />
<option name="RIGHT_MARGIN_COLOR" value="4d4d4d" />
<option name="SELECTED_TEARLINE_COLOR" value="ffffff" />
<option name="SELECTED_INDENT_GUIDE" value="505050" />
<option name="SELECTED_TEARLINE_COLOR" value="787878" />
<option name="SELECTION_BACKGROUND" value="214283" />
<option name="SELECTION_FOREGROUND" value="" />
<option name="TEARLINE_COLOR" value="909090" />
<option name="TEARLINE_COLOR" value="555555" />
<option name="WHITESPACES" value="404040" />
</colors>
<attributes>
@@ -415,26 +415,26 @@
</option>
<option name="DIFF_CONFLICT">
<value>
<option name="BACKGROUND" value="763c3d" />
<option name="ERROR_STRIPE_COLOR" value="763c3d" />
<option name="BACKGROUND" value="45302b" />
<option name="ERROR_STRIPE_COLOR" value="8f5247" />
</value>
</option>
<option name="DIFF_DELETED">
<value>
<option name="BACKGROUND" value="0" />
<option name="ERROR_STRIPE_COLOR" value="0" />
<option name="BACKGROUND" value="484a4a" />
<option name="ERROR_STRIPE_COLOR" value="656e76" />
</value>
</option>
<option name="DIFF_INSERTED">
<value>
<option name="BACKGROUND" value="365d40" />
<option name="ERROR_STRIPE_COLOR" value="365d40" />
<option name="BACKGROUND" value="294436" />
<option name="ERROR_STRIPE_COLOR" value="447152" />
</value>
</option>
<option name="DIFF_MODIFIED">
<value>
<option name="BACKGROUND" value="337184" />
<option name="ERROR_STRIPE_COLOR" value="326174" />
<option name="BACKGROUND" value="385570" />
<option name="ERROR_STRIPE_COLOR" value="43698d" />
</value>
</option>
<option name="DOC_COMMENT_TAG_VALUE">
@@ -1143,192 +1143,6 @@
<option name="FONT_TYPE" value="1" />
</value>
</option>
<option name="RUBY_ATTR_ACCESSOR_CALL">
<value>
<option name="FOREGROUND" value="cc7833" />
</value>
</option>
<option name="RUBY_ATTR_READER_CALL">
<value>
<option name="FOREGROUND" value="cc7833" />
</value>
</option>
<option name="RUBY_ATTR_WRITER_CALL">
<value>
<option name="FOREGROUND" value="cc7833" />
</value>
</option>
<option name="RUBY_BACK_REF">
<value>
<option name="FOREGROUND" value="0" />
<option name="FONT_TYPE" value="1" />
</value>
</option>
<option name="RUBY_BAD_CHARACTER">
<value>
<option name="EFFECT_COLOR" value="ff0000" />
<option name="EFFECT_TYPE" value="2" />
</value>
</option>
<option name="RUBY_COMMA">
<value />
</option>
<option name="RUBY_COMMENT">
<value>
<option name="FOREGROUND" value="bc9458" />
<option name="FONT_TYPE" value="2" />
</value>
</option>
<option name="RUBY_CONSTANT">
<value>
<option name="FOREGROUND" value="da4939" />
</value>
</option>
<option name="RUBY_CONSTANT_DEF_ID">
<value>
<option name="FOREGROUND" value="9f0e9b" />
<option name="FONT_TYPE" value="3" />
</value>
</option>
<option name="RUBY_CVAR">
<value>
<option name="FOREGROUND" value="d0d0ff" />
</value>
</option>
<option name="RUBY_ESCAPE_SEQUENCE">
<value>
<option name="FOREGROUND" value="519f50" />
</value>
</option>
<option name="RUBY_EXPR_IN_STRING">
<value />
</option>
<option name="RUBY_GVAR">
<value>
<option name="FOREGROUND" value="d0d0ff" />
</value>
</option>
<option name="RUBY_HASH_ASSOC">
<value />
</option>
<option name="RUBY_HEREDOC_CONTENT">
<value>
<option name="FOREGROUND" value="a5c261" />
</value>
</option>
<option name="RUBY_HEREDOC_ID">
<value>
<option name="FOREGROUND" value="a5c261" />
<option name="EFFECT_TYPE" value="1" />
</value>
</option>
<option name="RUBY_IMPORT_CALL">
<value>
<option name="FOREGROUND" value="cc7833" />
</value>
</option>
<option name="RUBY_INTERPOLATED_STRING">
<value>
<option name="FOREGROUND" value="52a12e" />
<option name="FONT_TYPE" value="1" />
</value>
</option>
<option name="RUBY_INVALID_ESCAPE_SEQUENCE">
<value>
<option name="FOREGROUND" value="519f50" />
<option name="EFFECT_COLOR" value="ff0000" />
<option name="EFFECT_TYPE" value="2" />
</value>
</option>
<option name="RUBY_IVAR">
<value>
<option name="FOREGROUND" value="d0d0ff" />
</value>
</option>
<option name="RUBY_KEYWORD">
<value>
<option name="FOREGROUND" value="cc7833" />
</value>
</option>
<option name="RUBY_LINE_CONTINUATION">
<value />
</option>
<option name="RUBY_LOCAL_VAR_ID">
<value>
<option name="FOREGROUND" value="78b4" />
</value>
</option>
<option name="RUBY_METHOD_NAME">
<value>
<option name="FOREGROUND" value="ffc66d" />
</value>
</option>
<option name="RUBY_NTH_REF">
<value>
<option name="FOREGROUND" value="d0d0ff" />
</value>
</option>
<option name="RUBY_NUMBER">
<value>
<option name="FOREGROUND" value="a5c261" />
<option name="EFFECT_TYPE" value="1" />
</value>
</option>
<option name="RUBY_OPERATION_SIGN">
<value>
<option name="FOREGROUND" value="cc7833" />
</value>
</option>
<option name="RUBY_PARAMETER_ID">
<value>
<option name="FOREGROUND" value="c37522" />
<option name="EFFECT_TYPE" value="2" />
</value>
</option>
<option name="RUBY_PRIVATE_CALL">
<value>
<option name="FONT_TYPE" value="1" />
</value>
</option>
<option name="RUBY_PROTECTED_CALL">
<value>
<option name="FONT_TYPE" value="1" />
</value>
</option>
<option name="RUBY_PUBLIC_CALL">
<value>
<option name="FOREGROUND" value="cc7833" />
</value>
</option>
<option name="RUBY_REGEXP">
<value>
<option name="FOREGROUND" value="a5c261" />
</value>
</option>
<option name="RUBY_REQUIRE_ARG_CALL">
<value>
<option name="FONT_TYPE" value="3" />
</value>
</option>
<option name="RUBY_REQUIRE_CALL">
<value>
<option name="FOREGROUND" value="cc7833" />
<option name="EFFECT_TYPE" value="2" />
</value>
</option>
<option name="RUBY_SEMICOLON">
<value />
</option>
<option name="RUBY_SPECIFIC_CALL">
<value>
<option name="FOREGROUND" value="da4939" />
</value>
</option>
<option name="RUBY_SYMBOL">
<value>
<option name="FOREGROUND" value="6e9cbe" />
</value>
</option>
<option name="SASS_ATTRIBUTE">
<value>
<option name="FOREGROUND" value="6d9cbe" />
@@ -1704,7 +1518,7 @@
</option>
<option name="TODO_DEFAULT_ATTRIBUTES">
<value>
<option name="FOREGROUND" value="bc9458" />
<option name="FOREGROUND" value="a8c023" />
<option name="FONT_TYPE" value="2" />
</value>
</option>
@@ -1801,7 +1615,7 @@
</option>
<option name="XML_ATTRIBUTE_NAME">
<value>
<option name="FOREGROUND" value="d0d0ff" />
<option name="FOREGROUND" value="bababa" />
</value>
</option>
<option name="XML_ATTRIBUTE_VALUE">
@@ -73,13 +73,14 @@ public final class CompiledClassPropertiesProvider implements PropertiesProvider
final Method readMethod = descriptor.getReadMethod();
final Method writeMethod = descriptor.getWriteMethod();
if (writeMethod == null || readMethod == null) {
final Class propertyType = descriptor.getPropertyType();
if (writeMethod == null || readMethod == null || propertyType == null) {
continue;
}
final String name = descriptor.getName();
final LwIntrospectedProperty property = propertyFromClass(descriptor.getPropertyType(), name);
final LwIntrospectedProperty property = propertyFromClass(propertyType, name);
if (property != null) {
property.setDeclaringClassName(descriptor.getReadMethod().getDeclaringClass().getName());
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.compiler.options.CompilerUIConfigurable">
<grid id="1663f" binding="myPanel" layout-manager="GridLayoutManager" row-count="10" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="1663f" binding="myPanel" layout-manager="GridLayoutManager" row-count="11" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="28" y="24" width="883" height="379"/>
@@ -10,7 +10,7 @@
<children>
<vspacer id="67edf">
<constraints>
<grid row="9" column="0" row-span="1" col-span="3" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
<grid row="10" column="0" row-span="1" col-span="3" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<grid id="b341d" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="1">
@@ -95,7 +95,7 @@
</component>
<component id="17126" class="javax.swing.JLabel" binding="myHeapSizeLabel">
<constraints>
<grid row="7" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="2" use-parent-layout="false"/>
<grid row="8" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="2" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Compiler process heap size (Mbytes):"/>
@@ -103,7 +103,7 @@
</component>
<component id="a28b8" class="javax.swing.JTextField" binding="myHeapSizeField">
<constraints>
<grid row="7" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="0" indent="0" use-parent-layout="false">
<grid row="8" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="0" indent="0" use-parent-layout="false">
<preferred-size width="50" height="-1"/>
</grid>
</constraints>
@@ -111,7 +111,7 @@
</component>
<component id="5b86a" class="javax.swing.JLabel" binding="myVMOptionsLabel">
<constraints>
<grid row="8" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="2" use-parent-layout="false"/>
<grid row="9" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="2" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Additional compiler process VM options:"/>
@@ -119,7 +119,7 @@
</component>
<component id="b5547" class="javax.swing.JTextField" binding="myVMOptionsField">
<constraints>
<grid row="8" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<grid row="9" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
@@ -149,6 +149,14 @@
<text value="(only works while not running / debugging)"/>
</properties>
</component>
<component id="4b44" class="javax.swing.JCheckBox" binding="myCbRebuildOnDependencyChange" default-binding="true">
<constraints>
<grid row="7" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="2" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Rebuild module on dependency change"/>
</properties>
</component>
</children>
</grid>
</form>
@@ -55,6 +55,7 @@ public class CompilerUIConfigurable implements SearchableConfigurable, Configura
private JTextField myVMOptionsField;
private JLabel myHeapSizeLabel;
private JLabel myVMOptionsLabel;
private JCheckBox myCbRebuildOnDependencyChange;
public CompilerUIConfigurable(final Project project) {
myProject = project;
@@ -84,6 +85,7 @@ public class CompilerUIConfigurable implements SearchableConfigurable, Configura
myCbUseExternalBuild.setSelected(workspaceConfiguration.USE_COMPILE_SERVER);
myCbEnableAutomake.setSelected(workspaceConfiguration.MAKE_PROJECT_ON_SAVE);
myCbParallelCompilation.setSelected(workspaceConfiguration.PARALLEL_COMPILATION);
myCbRebuildOnDependencyChange.setSelected(workspaceConfiguration.REBUILD_ON_DEPENDENCY_CHANGE);
myHeapSizeField.setText(String.valueOf(workspaceConfiguration.COMPILER_PROCESS_HEAP_SIZE));
final String options = workspaceConfiguration.COMPILER_PROCESS_ADDITIONAL_VM_OPTIONS;
myVMOptionsField.setText(options == null? "" : options.trim());
@@ -115,6 +117,7 @@ public class CompilerUIConfigurable implements SearchableConfigurable, Configura
workspaceConfiguration.USE_COMPILE_SERVER = myCbUseExternalBuild.isSelected();
workspaceConfiguration.MAKE_PROJECT_ON_SAVE = myCbEnableAutomake.isSelected();
workspaceConfiguration.PARALLEL_COMPILATION = myCbParallelCompilation.isSelected();
workspaceConfiguration.REBUILD_ON_DEPENDENCY_CHANGE = myCbRebuildOnDependencyChange.isSelected();
try {
workspaceConfiguration.COMPILER_PROCESS_HEAP_SIZE = Integer.parseInt(myHeapSizeField.getText().trim());
}
@@ -173,6 +176,7 @@ public class CompilerUIConfigurable implements SearchableConfigurable, Configura
isModified |= ComparingUtils.isModified(myCbUseExternalBuild, workspaceConfiguration.USE_COMPILE_SERVER);
isModified |= ComparingUtils.isModified(myCbEnableAutomake, workspaceConfiguration.MAKE_PROJECT_ON_SAVE);
isModified |= ComparingUtils.isModified(myCbParallelCompilation, workspaceConfiguration.PARALLEL_COMPILATION);
isModified |= ComparingUtils.isModified(myCbRebuildOnDependencyChange, workspaceConfiguration.REBUILD_ON_DEPENDENCY_CHANGE);
isModified |= ComparingUtils.isModified(myHeapSizeField, workspaceConfiguration.COMPILER_PROCESS_HEAP_SIZE);
isModified |= ComparingUtils.isModified(myVMOptionsField, workspaceConfiguration.COMPILER_PROCESS_ADDITIONAL_VM_OPTIONS);
@@ -211,6 +215,7 @@ public class CompilerUIConfigurable implements SearchableConfigurable, Configura
private void updateExternalMakeOptionControls(boolean enabled) {
myCbEnableAutomake.setEnabled(enabled);
myCbParallelCompilation.setEnabled(enabled);
myCbRebuildOnDependencyChange.setEnabled(enabled);
myHeapSizeField.setEnabled(enabled);
myVMOptionsField.setEnabled(enabled);
myHeapSizeLabel.setEnabled(enabled);
@@ -41,7 +41,6 @@ import com.intellij.openapi.project.DumbModeAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerListener;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
@@ -210,20 +209,6 @@ public class CompilerTask extends Task.Backgroundable {
closeUI();
}
stopAppIconProgress();
Runnable runnable = new Runnable() {
public void run() {
if (myProject == null || myProject.isDisposed())
return;
NotificationInfo notificationInfo = getNotificationInfo();
if (notificationInfo != null && !myMessagesAutoActivated && (myErrorCount > 0 || (myWarningCount > 0 && !ErrorTreeViewConfiguration.getInstance(myProject).isHideWarnings()))) {
MessageType messageType = myErrorCount > 0 ? MessageType.ERROR : myWarningCount > 0 ? MessageType.WARNING : MessageType.INFO;
ToolWindowManager.getInstance(myProject).notifyByBalloon(ToolWindowId.MESSAGES_WINDOW, messageType,
getNotificationInfo().getNotificationText(), null, null);
}
}
};
ApplicationManager.getApplication().invokeLater(runnable);
}
private void stopAppIconProgress() {
@@ -334,6 +319,7 @@ public class CompilerTask extends Task.Backgroundable {
(CompilerMessageCategory.WARNING.equals(category) && !ErrorTreeViewConfiguration.getInstance(myProject).isHideWarnings())
);
if (shouldAutoActivate) {
myMessagesAutoActivated = true;
activateMessageView();
}
}
@@ -458,7 +444,7 @@ public class CompilerTask extends Task.Backgroundable {
if (myErrorTreeView != null) {
final ToolWindow tw = ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.MESSAGES_WINDOW);
if (tw != null) {
myMessagesAutoActivated = tw.activate(null, false, false, false);
tw.activate(null, false);
}
}
}
@@ -29,7 +29,10 @@ import com.intellij.execution.process.*;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.ide.PowerSaveMode;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.*;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.diagnostic.Logger;
@@ -123,7 +126,8 @@ public class BuildManager implements ApplicationComponent{
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.server.BuildManager");
private static final String COMPILER_PROCESS_JDK_PROPERTY = "compiler.process.jdk";
private static final String SYSTEM_ROOT = "compile-server";
public static final String SYSTEM_ROOT = "compile-server";
public static final String TEMP_DIR_NAME = "_temp_";
private static final String LOGGER_CONFIG = "log.xml";
private static final String DEFAULT_LOGGER_CONFIG = "defaultLogConfig.xml";
private static final int MAKE_TRIGGER_DELAY = 300 /*300 ms*/;
@@ -211,6 +215,7 @@ public class BuildManager implements ApplicationComponent{
private final BuildMessageDispatcher myMessageDispatcher = new BuildMessageDispatcher();
private volatile int myListenPort = -1;
private volatile CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings myGlobals;
private int myGlobalsStamp = -1;
@Nullable
private final Charset mySystemCharset;
@@ -533,11 +538,7 @@ public class BuildManager implements ApplicationComponent{
return;
}
CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globals = myGlobals;
if (globals == null) {
globals = buildGlobalSettings();
myGlobals = globals;
}
final CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globals = buildGlobalSettings();
CmdlineRemoteProto.Message.ControllerMessage.FSEvent currentFSChanges;
final SequentialTaskExecutor projectTaskQueue;
synchronized (myProjectDataMap) {
@@ -686,14 +687,22 @@ public class BuildManager implements ApplicationComponent{
return "com.intellij.compiler.server.BuildManager";
}
private static CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings buildGlobalSettings() {
private CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings buildGlobalSettings() {
final PathMacrosImpl pathVars = PathMacrosImpl.getInstanceEx();
final CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings cached = myGlobals;
if (cached != null && myGlobalsStamp == pathVars.getModificationStamp()) {
return cached;
}
myGlobals = null; // ensure the cache is cleared and stamp is current
myGlobalsStamp = pathVars.getModificationStamp();
final Map<String, String> data = new HashMap<String, String>();
for (Map.Entry<String, String> entry : PathMacrosImpl.getGlobalSystemMacros().entrySet()) {
data.put(entry.getKey(), FileUtil.toSystemIndependentName(entry.getValue()));
}
final PathMacros pathVars = PathMacros.getInstance();
for (String name : pathVars.getAllMacroNames()) {
final String path = pathVars.getValue(name);
if (path != null) {
@@ -716,7 +725,7 @@ public class BuildManager implements ApplicationComponent{
}
}
return cmdBuilder.build();
return myGlobals = cmdBuilder.build();
}
private OSProcessHandler launchBuildProcess(Project project, final int port, final UUID sessionId) throws ExecutionException {
@@ -827,6 +836,7 @@ public class BuildManager implements ApplicationComponent{
cmdLine.addParameter("-D"+ GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION +"=" + shouldGenerateIndex);
}
cmdLine.addParameter("-D"+ GlobalOptions.COMPILE_PARALLEL_OPTION +"=" + Boolean.toString(config.PARALLEL_COMPILATION));
cmdLine.addParameter("-D"+ GlobalOptions.REBUILD_ON_DEPENDENCY_CHANGE_OPTION + "=" + Boolean.toString(config.REBUILD_ON_DEPENDENCY_CHANGE));
if (Boolean.TRUE.equals(Boolean.valueOf(System.getProperty("java.net.preferIPv4Stack", "false")))) {
cmdLine.addParameter("-Djava.net.preferIPv4Stack=true");
@@ -876,7 +886,7 @@ public class BuildManager implements ApplicationComponent{
workDirectory.mkdirs();
ensureLogConfigExists(workDirectory);
cmdLine.addParameter("-Djava.io.tmpdir=" + FileUtil.toSystemIndependentName(workDirectory.getPath()) + "/_temp_");
cmdLine.addParameter("-Djava.io.tmpdir=" + FileUtil.toSystemIndependentName(workDirectory.getPath()) + "/" + TEMP_DIR_NAME);
final List<String> cp = ClasspathBootstrap.getBuildProcessApplicationClasspath();
cp.add(compilerPath);
@@ -42,6 +42,7 @@ public class CompilerWorkspaceConfiguration implements PersistentStateComponent<
public boolean PARALLEL_COMPILATION = false;
public int COMPILER_PROCESS_HEAP_SIZE = DEFAULT_COMPILE_PROCESS_HEAP_SIZE;
public String COMPILER_PROCESS_ADDITIONAL_VM_OPTIONS = DEFAULT_COMPILE_PROCESS_VM_OPTIONS;
public boolean REBUILD_ON_DEPENDENCY_CHANGE = true;
public static CompilerWorkspaceConfiguration getInstance(Project project) {
return ServiceManager.getService(project, CompilerWorkspaceConfiguration.class);
@@ -249,21 +249,34 @@ public abstract class Breakpoint extends FilteredRequestor implements ClassPrepa
}
}
if (REMOVE_AFTER_HIT) {
debugProcess.addDebugProcessListener(new DebugProcessAdapter() {
@Override
public void resumed(SuspendContext suspendContext) {
DebuggerUIUtil.invokeOnEventDispatch(new Runnable() {
@Override
public void run() {
DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().removeBreakpoint(Breakpoint.this);
}
});
debugProcess.removeDebugProcessListener(this);
}
});
handleTemporaryBreakpointHit(debugProcess);
}
}
private void handleTemporaryBreakpointHit(final DebugProcessImpl debugProcess) {
debugProcess.addDebugProcessListener(new DebugProcessAdapter() {
@Override
public void resumed(SuspendContext suspendContext) {
removeBreakpoint();
}
@Override
public void processDetached(DebugProcess process, boolean closedByUser) {
removeBreakpoint();
}
private void removeBreakpoint() {
DebuggerUIUtil.invokeOnEventDispatch(new Runnable() {
@Override
public void run() {
DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().removeBreakpoint(Breakpoint.this);
}
});
debugProcess.removeDebugProcessListener(this);
}
});
}
public final void updateUI() {
updateUI(EmptyRunnable.getInstance());
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -616,6 +616,11 @@ public abstract class BreakpointWithHighlighter extends Breakpoint {
return myDescription;
}
@Override
public Alignment getAlignment() {
return Alignment.RIGHT;
}
@Override
public AnAction getClickAction() {
return new AnAction() {
@@ -122,9 +122,9 @@ public class OrderEntryAppearanceServiceImpl extends OrderEntryAppearanceService
String name = jdk.getName();
CompositeAppearance appearance = new CompositeAppearance();
appearance.setIcon(((SdkType) jdk.getSdkType()).getIcon());
VirtualFile homeDirectory = jdk.getHomeDirectory();
SimpleTextAttributes attributes = getTextAttributes(homeDirectory != null && homeDirectory.isValid(), selected);
SdkType sdkType = (SdkType)jdk.getSdkType();
appearance.setIcon(sdkType.getIcon());
SimpleTextAttributes attributes = getTextAttributes(sdkType.sdkHasValidPath(jdk), selected);
CompositeAppearance.DequeEnd ending = appearance.getEnding();
ending.addText(name, attributes);
@@ -147,4 +147,8 @@ public class LocalArchivedTemplate extends ArchivedProjectTemplate {
public ZipInputStream getStream() throws IOException {
return new ZipInputStream(myArchivePath.openStream());
}
public URL getArchivePath() {
return myArchivePath;
}
}
@@ -21,17 +21,22 @@ import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.platform.ProjectTemplate;
import com.intellij.platform.ProjectTemplatesFactory;
import com.intellij.ui.*;
import com.intellij.ui.CollectionListModel;
import com.intellij.ui.ColoredListCellRenderer;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.ToolbarDecorator;
import com.intellij.ui.components.JBList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Arrays;
/**
@@ -49,7 +54,21 @@ class ManageProjectTemplatesDialog extends DialogWrapper {
setTitle("Manage Project Templates");
final ProjectTemplate[] templates =
new ArchivedTemplatesFactory().createTemplates(ProjectTemplatesFactory.CUSTOM_GROUP, new WizardContext(null));
final CollectionListModel<ProjectTemplate> model = new CollectionListModel<ProjectTemplate>(Arrays.asList(templates));
final CollectionListModel<ProjectTemplate> model = new CollectionListModel<ProjectTemplate>(Arrays.asList(templates)) {
@Override
public void remove(int index) {
ProjectTemplate template = getElementAt(index);
super.remove(index);
if (template instanceof LocalArchivedTemplate) {
URL path = ((LocalArchivedTemplate)template).getArchivePath();
try {
new File(path.toURI()).delete();
}
catch (URISyntaxException ignore) {
}
}
}
};
myTemplatesList = new JBList(model);
myTemplatesList.setEmptyText("No user-defined project templates");
myTemplatesList.setPreferredSize(new Dimension(300, 100));
@@ -66,12 +85,6 @@ class ManageProjectTemplatesDialog extends DialogWrapper {
myDescriptionPane.setText(template == null ? null : template.getDescription());
}
});
model.addListDataListener(new ListDataAdapter() {
@Override
public void intervalRemoved(ListDataEvent e) {
ArchivedTemplatesFactory.getTemplateFile(templates[e.getIndex0()].getName()).delete();
}
});
myPanel = new JPanel(new BorderLayout(0, 5));
myPanel.add(ToolbarDecorator.createDecorator(myTemplatesList).disableUpDownActions().createPanel());
@@ -3,7 +3,7 @@
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="3" 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="20" y="20" width="500" height="269"/>
<xy x="20" y="20" width="500" height="171"/>
</constraints>
<properties/>
<border type="none"/>
@@ -24,7 +24,7 @@
<text resource-bundle="messages/ProjectBundle" key="project.new.wizard.import.title"/>
</properties>
</component>
<grid id="b4cdc" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="b4cdc" layout-manager="GridLayoutManager" row-count="1" 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>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -49,11 +49,6 @@
</component>
</children>
</scrollpane>
<vspacer id="65df7">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
</children>
</grid>
</children>
@@ -32,6 +32,7 @@ import com.intellij.ui.DoubleClickListener;
import com.intellij.ui.components.JBList;
import com.intellij.ui.components.JBRadioButton;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
@@ -50,6 +51,7 @@ public class ImportChooserStep extends ProjectImportWizardStep {
private final ProjectImportProvider[] myProviders;
private final StepSequence mySequence;
@Nullable
private ProjectImportProvider myFromSourcesProvider;
private JBList myList;
private JPanel myPanel;
@@ -73,7 +75,9 @@ public class ImportChooserStep extends ProjectImportWizardStep {
model.addElement(provider);
}
}
if (myFromSourcesProvider == null) {
myCreateFromSources.setVisible(false);
}
myList.setModel(model);
myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
myList.setCellRenderer(new DefaultListCellRenderer() {
@@ -121,7 +125,7 @@ public class ImportChooserStep extends ProjectImportWizardStep {
if (myList.getSelectedValue() != null) return;
final String id = PropertiesComponent.getInstance().getValue(PREFERRED);
if (id == null || id.equals(myFromSourcesProvider.getId())) {
if (id == null || myFromSourcesProvider != null && id.equals(myFromSourcesProvider.getId())) {
myCreateFromSources.setSelected(true);
}
else {
@@ -0,0 +1,239 @@
/*
* Copyright 2000-2013 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.codeInsight;
import com.intellij.openapi.components.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiMethod;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:johnnyclark@gmail.com">Johnny Clark</a>
* Creation Date: 8/3/12
*/
@State(
name = "ConditionCheckManager",
storages = {@Storage(id = "dir", file = StoragePathMacros.PROJECT_CONFIG_DIR + "/checker.xml", scheme = StorageScheme.DIRECTORY_BASED)}
)
public class ConditionCheckManager implements PersistentStateComponent<ConditionCheckManager.State> {
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) private State state;
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.ConditionCheckManager");
private List<ConditionChecker> myIsNullCheckMethods = new ArrayList<ConditionChecker>();
private List<ConditionChecker> myIsNotNullCheckMethods = new ArrayList<ConditionChecker>();
private List<ConditionChecker> myAssertIsNullMethods = new ArrayList<ConditionChecker>();
private List<ConditionChecker> myAssertIsNotNullMethods = new ArrayList<ConditionChecker>();
private List<ConditionChecker> myAssertTrueMethods = new ArrayList<ConditionChecker>();
private List<ConditionChecker> myAssertFalseMethods = new ArrayList<ConditionChecker>();
public static ConditionCheckManager getInstance(Project project) {
return ServiceManager.getService(project, ConditionCheckManager.class);
}
public void setIsNullCheckMethods(List<ConditionChecker> methodConditionChecks) {
myIsNullCheckMethods.clear();
myIsNullCheckMethods.addAll(methodConditionChecks);
}
public void setIsNotNullCheckMethods(List<ConditionChecker> methodConditionChecks) {
myIsNotNullCheckMethods.clear();
myIsNotNullCheckMethods.addAll(methodConditionChecks);
}
public void setAssertIsNullMethods(List<ConditionChecker> methodConditionChecks) {
myAssertIsNullMethods.clear();
myAssertIsNullMethods.addAll(methodConditionChecks);
}
public void setAssertIsNotNullMethods(List<ConditionChecker> methodConditionChecks) {
myAssertIsNotNullMethods.clear();
myAssertIsNotNullMethods.addAll(methodConditionChecks);
}
public void setAssertTrueMethods(List<ConditionChecker> psiMethodWrappers) {
myAssertTrueMethods.clear();
myAssertTrueMethods.addAll(psiMethodWrappers);
}
public void setAssertFalseMethods(List<ConditionChecker> psiMethodWrappers) {
myAssertFalseMethods.clear();
myAssertFalseMethods.addAll(psiMethodWrappers);
}
public List<ConditionChecker> getIsNullCheckMethods() {
return myIsNullCheckMethods;
}
public List<ConditionChecker> getIsNotNullCheckMethods() {
return myIsNotNullCheckMethods;
}
public List<ConditionChecker> getAssertIsNullMethods() {
return myAssertIsNullMethods;
}
public List<ConditionChecker> getAssertIsNotNullMethods() {
return myAssertIsNotNullMethods;
}
public List<ConditionChecker> getAssertFalseMethods() {
return myAssertFalseMethods;
}
public List<ConditionChecker> getAssertTrueMethods() {
return myAssertTrueMethods;
}
public static class State {
public List<String> myIsNullCheckMethods = new ArrayList<String>();
public List<String> myIsNotNullCheckMethods = new ArrayList<String>();
public List<String> myAssertIsNullMethods = new ArrayList<String>();
public List<String> myAssertIsNotNullMethods = new ArrayList<String>();
public List<String> myAssertTrueMethods = new ArrayList<String>();
public List<String> myAssertFalseMethods = new ArrayList<String>();
}
@Override
public State getState() {
State state = new State();
loadMethodChecksToState(state.myIsNullCheckMethods, myIsNullCheckMethods);
loadMethodChecksToState(state.myIsNotNullCheckMethods, myIsNotNullCheckMethods);
loadMethodChecksToState(state.myAssertIsNullMethods, myAssertIsNullMethods);
loadMethodChecksToState(state.myAssertIsNotNullMethods, myAssertIsNotNullMethods);
loadMethodChecksToState(state.myAssertTrueMethods, myAssertTrueMethods);
loadMethodChecksToState(state.myAssertFalseMethods, myAssertFalseMethods);
return state;
}
private static void loadMethodChecksToState(List<String> listToLoadTo, List<ConditionChecker> listToLoadFrom) {
for (ConditionChecker checker : listToLoadFrom) {
listToLoadTo.add(checker.toString());
}
}
@Override
public void loadState(State state) {
this.state = state;
loadMethods(myIsNullCheckMethods, state.myIsNullCheckMethods, ConditionChecker.Type.IS_NULL_METHOD);
loadMethods(myIsNotNullCheckMethods, state.myIsNotNullCheckMethods, ConditionChecker.Type.IS_NOT_NULL_METHOD);
loadMethods(myAssertIsNullMethods, state.myAssertIsNullMethods, ConditionChecker.Type.ASSERT_IS_NULL_METHOD);
loadMethods(myAssertIsNotNullMethods, state.myAssertIsNotNullMethods, ConditionChecker.Type.ASSERT_IS_NOT_NULL_METHOD);
loadMethods(myAssertTrueMethods, state.myAssertTrueMethods, ConditionChecker.Type.ASSERT_TRUE_METHOD);
loadMethods(myAssertFalseMethods, state.myAssertFalseMethods, ConditionChecker.Type.ASSERT_FALSE_METHOD);
}
public void loadMethods(List<ConditionChecker> listToLoadTo, List<String> listToLoadFrom, ConditionChecker.Type type){
listToLoadTo.clear();
for (String setting : listToLoadFrom) {
try {
listToLoadTo.add(new ConditionChecker.FromConfigBuilder(setting, type).build());
} catch (Exception e) {
LOG.error("Problem occurred while attempting to load Condition Check from configuration file. " + e.getMessage());
}
}
}
public static boolean isMethod(@NotNull PsiMethod psiMethod, List<ConditionChecker> checkers) {
for (ConditionChecker checker : checkers) {
if (checker.matchesPsiMethod(psiMethod)) {
return true;
}
}
return false;
}
public static boolean isCheck(PsiMethod psiMethod) {
ConditionCheckManager manager = getInstance(psiMethod.getProject());
return isMethod(psiMethod, manager.getIsNullCheckMethods()) ||
isMethod(psiMethod, manager.getIsNotNullCheckMethods()) ||
isMethod(psiMethod, manager.getAssertIsNullMethods()) ||
isMethod(psiMethod, manager.getAssertIsNotNullMethods()) ||
isAssertTrueCheckMethod(psiMethod) ||
isAssertFalseCheckMethod(psiMethod);
}
public static boolean isNullCheckMethod(PsiMethod psiMethod) {
return methodMatches(psiMethod, getInstance(psiMethod.getProject()).getIsNullCheckMethods());
}
public static boolean isNotNullCheckMethod(PsiMethod psiMethod) {
return methodMatches(psiMethod, getInstance(psiMethod.getProject()).getIsNotNullCheckMethods());
}
public static boolean isAssertIsNullCheckMethod(PsiMethod psiMethod) {
return methodMatches(psiMethod, getInstance(psiMethod.getProject()).getAssertIsNullMethods());
}
public static boolean isAssertIsNotNullCheckMethod(PsiMethod psiMethod) {
return methodMatches(psiMethod, getInstance(psiMethod.getProject()).getAssertIsNotNullMethods());
}
public static boolean isAssertTrueCheckMethod(PsiMethod psiMethod) {
return methodMatches(psiMethod, getInstance(psiMethod.getProject()).getAssertTrueMethods());
}
public static boolean isAssertFalseCheckMethod(PsiMethod psiMethod) {
return methodMatches(psiMethod, getInstance(psiMethod.getProject()).getAssertFalseMethods());
}
public static boolean isNullCheckMethod(PsiMethod psiMethod, int paramIndex) {
return methodMatches(psiMethod, paramIndex, getInstance(psiMethod.getProject()).getIsNullCheckMethods());
}
public static boolean isNotNullCheckMethod(PsiMethod psiMethod, int paramIndex) {
return methodMatches(psiMethod, paramIndex, getInstance(psiMethod.getProject()).getIsNotNullCheckMethods());
}
public static boolean isAssertIsNullCheckMethod(PsiMethod psiMethod, int paramIndex) {
return methodMatches(psiMethod, paramIndex, getInstance(psiMethod.getProject()).getAssertIsNullMethods());
}
public static boolean isAssertIsNotNullCheckMethod(PsiMethod psiMethod, int paramIndex) {
return methodMatches(psiMethod, paramIndex, getInstance(psiMethod.getProject()).getAssertIsNotNullMethods());
}
public static boolean isAssertTrueCheckMethod(PsiMethod psiMethod, int paramIndex) {
return methodMatches(psiMethod, paramIndex, getInstance(psiMethod.getProject()).getAssertTrueMethods());
}
public static boolean isAssertFalseCheckMethod(PsiMethod psiMethod, int paramIndex) {
return methodMatches(psiMethod, paramIndex, getInstance(psiMethod.getProject()).getAssertFalseMethods());
}
public static boolean methodMatches(PsiMethod psiMethod, List<ConditionChecker> checkers) {
for (ConditionChecker checker : checkers) {
if (checker.matchesPsiMethod(psiMethod))
return true;
}
return false;
}
public static boolean methodMatches(PsiMethod psiMethod, int paramIndex, List<ConditionChecker> checkers) {
for (ConditionChecker checker : checkers) {
if (checker.matchesPsiMethod(psiMethod, paramIndex))
return true;
}
return false;
}
}
@@ -0,0 +1,431 @@
/*
* Copyright 2000-2013 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.codeInsight;
import com.intellij.openapi.diagnostic.*;
import com.intellij.psi.*;
import org.jetbrains.annotations.*;
import java.io.*;
import java.util.*;
/**
* Used by Constant Condition Inspection to identify methods which perform some type of Validation on the parameters passed into them.
* For example given the following method
* <pre>
* {@code
* class Foo {
* static boolean validateNotNull(Object o) {
* if (o == null) return false;
* else return true;
* }
* }
* }
*
* The corresponding ConditionCheck would be <p/>
* myConditionCheckType=Type.IS_NOT_NULL_METHOD
* myClassName=Foo
* myMethodName=validateNotNull
* myPsiParameter=o
*
* The following block of code would produce a Inspection Warning that o is always true
*
* <pre>
* {@code
* if (Value.isNotNull(o)) {
* if(o != null) {}
* }
* }
* </pre>
*
* @author <a href="mailto:johnnyclark@gmail.com">Johnny Clark</a>
* Creation Date: 8/14/12
*/
public class ConditionChecker implements Serializable {
private final @NotNull Type myConditionCheckType;
public enum Type {
IS_NULL_METHOD("IsNull Method"),
IS_NOT_NULL_METHOD("IsNotNull Method"),
ASSERT_IS_NULL_METHOD("Assert IsNull Method"),
ASSERT_IS_NOT_NULL_METHOD("Assert IsNotNull Method"),
ASSERT_TRUE_METHOD("Assert True Method"),
ASSERT_FALSE_METHOD("Assert False Method");
private final String myStringRepresentation;
Type(String stringRepresentation) {
myStringRepresentation = stringRepresentation;
}
@Override
public String toString() {
return myStringRepresentation;
}
}
private final @NotNull String myClassName;
private final @NotNull String myMethodName;
private final @NotNull List<String> myParameterClassList;
private final int myCheckedParameterIndex;
private final String myFullName;
private ConditionChecker(@NotNull String className,
@NotNull String methodName,
@NotNull List<String> parameterClassList,
int checkedParameterIndex,
@NotNull Type type,
@NotNull String fullName) {
checkState(!className.isEmpty(), "Class Name is blank");
checkState(!methodName.isEmpty(), "Method Name is blank");
checkState(!parameterClassList.isEmpty(), "Parameter Class List is empty");
checkState(checkedParameterIndex >= 0, "CheckedParameterIndex must be greater than or equal to zero");
checkState(parameterClassList.size() >= checkedParameterIndex, "CheckedParameterIndex is greater than Parameter Class List's size");
checkState(!fullName.isEmpty(), "Method Name is blank");
myConditionCheckType = type;
myClassName = className;
myMethodName = methodName;
myParameterClassList = parameterClassList;
myCheckedParameterIndex = checkedParameterIndex;
myFullName = fullName;
}
private static void checkState(boolean condition, String errorMsg) {
if (!condition) throw new IllegalArgumentException(errorMsg);
}
public static String getFullyQualifiedName(PsiParameter psiParameter) {
PsiTypeElement typeElement = psiParameter.getTypeElement();
if (typeElement == null) throw new RuntimeException("Parameter has null typeElement " + psiParameter.getName());
PsiType psiType = typeElement.getType();
return psiType.getCanonicalText();
}
public boolean matchesPsiMethod(PsiMethod psiMethod) {
if (!myMethodName.equals(psiMethod.getName())) return false;
PsiClass containingClass = psiMethod.getContainingClass();
if (containingClass == null) return false;
String qualifiedName = containingClass.getQualifiedName();
if (qualifiedName == null) return false;
if (!myClassName.equals(qualifiedName)) return false;
PsiParameterList psiParameterList = psiMethod.getParameterList();
if (myParameterClassList.size() != psiParameterList.getParameters().length) return false;
for (int i = 0; i < psiParameterList.getParameters().length; i++) {
PsiParameter psiParameter = psiParameterList.getParameters()[i];
PsiTypeElement psiTypeElement = psiParameter.getTypeElement();
if (psiTypeElement == null) return false;
PsiType psiType = psiTypeElement.getType();
String parameterCanonicalText = psiType.getCanonicalText();
String myParameterCanonicalText = myParameterClassList.get(i);
if (!myParameterCanonicalText.equals(parameterCanonicalText)) return false;
}
return true;
}
public boolean matchesPsiMethod(PsiMethod psiMethod, int paramIndex) {
if (matchesPsiMethod(psiMethod) && paramIndex == myCheckedParameterIndex) return true;
return false;
}
public boolean overlaps(ConditionChecker otherChecker) {
if (myClassName.equals(otherChecker.myClassName) &&
myMethodName.equals(otherChecker.myMethodName) &&
myParameterClassList.equals(otherChecker.myParameterClassList) &&
myCheckedParameterIndex == otherChecker.myCheckedParameterIndex) {
return true;
}
return false;
}
@NotNull
public Type getConditionCheckType() {
return myConditionCheckType;
}
@NotNull
public String getClassName() {
return myClassName;
}
@NotNull
public String getMethodName() {
return myMethodName;
}
public int getCheckedParameterIndex() {
return myCheckedParameterIndex;
}
public String getFullName() {
return myFullName;
}
/**
* In addition to normal duties, this controls the manner in which the ConditionCheck appears in the ConditionCheckDialog.MethodsPanel
*/
@Override
public String toString() {
return myFullName;
}
private static class Builder {
static String initFullName(String className,
String methodName,
List<String> parameterClasses,
List<String> parameterNames,
int checkedParameterIndex) {
String s = className + "." + methodName + "(";
int index = 0;
for (String parameterClass : parameterClasses) {
String parameterClassAndName = parameterClass + " " + parameterNames.get(index);
if (index == checkedParameterIndex) parameterClassAndName = "*" + parameterClassAndName + "*";
s += parameterClassAndName + ", ";
index++;
}
s = s.substring(0, s.length() - 2);
s += ")";
return s;
}
}
static class FromConfigBuilder extends Builder {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.ConditionCheck.FromConfigBuilder");
private final @NotNull String serializedRepresentation;
private final @NotNull Type type;
FromConfigBuilder(@NotNull String serializedRepresentation, @NotNull Type type) {
this.serializedRepresentation = serializedRepresentation;
this.type = type;
}
private String parseClassAndMethodName() {
if (!serializedRepresentation.contains("(")) {
throw new IllegalArgumentException("Name should contain a opening parenthesis. " + serializedRepresentation);
}
else if (!serializedRepresentation.contains(")")) {
throw new IllegalArgumentException("Name should contain a closing parenthesis. " + serializedRepresentation);
}
else if (serializedRepresentation.indexOf("(", serializedRepresentation.indexOf("(") + 1) > -1) {
throw new IllegalArgumentException("Name should only contain one opening parenthesis. " + serializedRepresentation);
}
else if (serializedRepresentation.indexOf(")", serializedRepresentation.indexOf(")") + 1) > -1) {
throw new IllegalArgumentException("Name should only contain one closing parenthesis. " + serializedRepresentation);
}
else if (serializedRepresentation.indexOf(")") < serializedRepresentation.indexOf("(")) {
throw new IllegalArgumentException("Opening parenthesis should precede closing parenthesis. " + serializedRepresentation);
}
String classAndMethodName = serializedRepresentation.substring(0, serializedRepresentation.indexOf("("));
if (!classAndMethodName.contains(".")) {
throw new IllegalArgumentException(
"Name should contain a dot between the class name and method name (before the opening parenthesis). " +
serializedRepresentation);
}
return classAndMethodName;
}
@Nullable
public ConditionChecker build() {
try {
String classAndMethodName = parseClassAndMethodName();
String className = classAndMethodName.substring(0, classAndMethodName.lastIndexOf("."));
String methodName = classAndMethodName.substring(classAndMethodName.lastIndexOf(".") + 1);
String allParametersSubString =
serializedRepresentation.substring(serializedRepresentation.indexOf("(") + 1, serializedRepresentation.lastIndexOf(")")).trim();
if (allParametersSubString.isEmpty()) {
throw new IllegalArgumentException(
"Name should contain 1+ parameter (between opening and closing parenthesis). " + serializedRepresentation);
}
else if (allParametersSubString.contains("*") && allParametersSubString.indexOf("*") == allParametersSubString.lastIndexOf("*")) {
throw new IllegalArgumentException("Selected Parameter should be surrounded by asterisks. " + serializedRepresentation);
}
List<String> parameterClasses = new ArrayList<String>();
List<String> parameterNames = new ArrayList<String>();
int checkParameterIndex = -1;
int index = 0;
for (String parameterClassAndName : allParametersSubString.split(",")) {
parameterClassAndName = parameterClassAndName.trim();
if (parameterClassAndName.startsWith("*") && parameterClassAndName.endsWith("*")) {
checkParameterIndex = index;
parameterClassAndName = parameterClassAndName.substring(1, parameterClassAndName.length() - 1);
}
String[] parameterClassAndNameSplit = parameterClassAndName.split(" ");
String parameterClass = parameterClassAndNameSplit[0];
String parameterName = parameterClassAndNameSplit[1];
parameterClasses.add(parameterClass);
parameterNames.add(parameterName);
index++;
}
String fullName = initFullName(className, methodName, parameterClasses, parameterNames, checkParameterIndex);
return new ConditionChecker(className, methodName, parameterClasses, checkParameterIndex, type, fullName);
}
catch (Exception e) {
LOG.error("An Exception occurred while attempting to build ConditionCheck for Serialized String '" +
serializedRepresentation +
"' and Type '" +
type +
"'", e);
return null;
}
}
}
public static class FromPsiBuilder extends Builder {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.ConditionCheck.FromPsiBuilder");
private final @NotNull PsiMethod psiMethod;
private final @NotNull PsiParameter psiParameter;
private final @NotNull Type type;
public FromPsiBuilder(@NotNull PsiMethod psiMethod, @NotNull PsiParameter psiParameter, @NotNull Type type) {
this.psiMethod = psiMethod;
this.psiParameter = psiParameter;
this.type = type;
}
private static void validatePsiMethodHasContainingClass(PsiMethod psiMethod) {
PsiElement psiElement = psiMethod.getContainingClass();
if (!(psiElement instanceof PsiClass)) {
throw new IllegalArgumentException("PsiMethod " + psiMethod + " can not have a null containing class.");
}
}
private static void validatePsiMethodReturnTypeForNonAsserts(PsiMethod psiMethod, Type type) {
PsiType returnType = psiMethod.getReturnType();
if (isAssert(type)) return;
if (returnType == null) throw new IllegalArgumentException("PsiMethod " + psiMethod + " has a null return type PsiType.");
if (returnType != PsiType.BOOLEAN && !returnType.getCanonicalText().equals(Boolean.class.toString())) {
throw new IllegalArgumentException("PsiMethod " + psiMethod + " must have a null return type PsiType of boolean or Boolean.");
}
}
private static void validatePsiParameterExistsInPsiMethod(PsiMethod psiMethod, PsiParameter psiParameter) {
boolean parameterFound = false;
PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
for (PsiParameter parameter : parameters) {
if (psiParameter.equals(parameter)) {
parameterFound = true;
break;
}
}
if (!parameterFound) {
throw new IllegalArgumentException("PsiMethod " + psiMethod + " must have parameter " + getFullyQualifiedName(psiParameter));
}
}
private static boolean isAssert(Type type) {
return type == Type.ASSERT_IS_NULL_METHOD ||
type == Type.ASSERT_IS_NOT_NULL_METHOD ||
type == Type.ASSERT_TRUE_METHOD ||
type == Type.ASSERT_FALSE_METHOD;
}
private static String initClassNameFromPsiMethod(PsiMethod psiMethod) {
PsiElement psiElement = psiMethod.getContainingClass();
PsiClass psiClass = (PsiClass)psiElement;
if (psiClass == null) throw new IllegalStateException("PsiClass is null");
String qualifiedName = psiClass.getQualifiedName();
if (qualifiedName == null || qualifiedName.isEmpty()) throw new IllegalStateException("Qualified Name is Blank");
return qualifiedName;
}
private static String initMethodNameFromPsiMethod(PsiMethod psiMethod) {
return psiMethod.getName();
}
private static List<String> initParameterClassListFromPsiMethod(PsiMethod psiMethod) {
List<String> parameterClasses = new ArrayList<String>();
PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
for (PsiParameter param : parameters) {
PsiTypeElement typeElement = param.getTypeElement();
if (typeElement == null) throw new RuntimeException("Parameter has null typeElement " + param.getName());
PsiType psiType = typeElement.getType();
parameterClasses.add(psiType.getCanonicalText());
}
return parameterClasses;
}
private static List<String> initParameterNameListFromPsiMethod(PsiMethod psiMethod) {
List<String> parameterNames = new ArrayList<String>();
PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
for (PsiParameter param : parameters) {
parameterNames.add(param.getName());
}
return parameterNames;
}
private static int initCheckedParameterIndex(PsiMethod psiMethod, PsiParameter psiParameterToFind) {
PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
for (int i = 0; i < parameters.length; i++) {
PsiParameter param = parameters[i];
if (param.equals(psiParameterToFind)) return i;
}
throw new IllegalStateException();
}
private void validateConstructorArgs(PsiMethod psiMethod, PsiParameter psiParameter) {
validatePsiMethodHasContainingClass(psiMethod);
validatePsiMethodReturnTypeForNonAsserts(psiMethod, type);
validatePsiParameterExistsInPsiMethod(psiMethod, psiParameter);
}
@Nullable
public ConditionChecker build() {
try {
validateConstructorArgs(psiMethod, psiParameter);
String className = initClassNameFromPsiMethod(psiMethod);
String methodName = initMethodNameFromPsiMethod(psiMethod);
List<String> parameterClassList = initParameterClassListFromPsiMethod(psiMethod);
List<String> parameterNameList = initParameterNameListFromPsiMethod(psiMethod);
int checkedParameterIndex = initCheckedParameterIndex(psiMethod, psiParameter);
String fullName = initFullName(className, methodName, parameterClassList, parameterNameList, checkedParameterIndex);
return new ConditionChecker(className, methodName, parameterClassList, checkedParameterIndex, type, fullName);
}
catch (Exception e) {
LOG.error("An Exception occurred while attempting to build ConditionCheck for PsiMethod '" + psiMethod +
"' PsiParameter='" + psiParameter + "' " +
"' and Type '" +
type +
"'", e);
return null;
}
}
}
}
@@ -118,24 +118,10 @@ public class TailTypes {
return styleSettings.SPACE_WITHIN_IF_PARENTHESES;
}
};
public static final TailType FINALLY_LBRACE = new BracesTailType() {
@Override
protected boolean isSpaceBeforeLBrace(final CommonCodeStyleSettings styleSettings, final Editor editor, final int tailOffset) {
return styleSettings.SPACE_BEFORE_FINALLY_LBRACE;
}
};
public static final TailType TRY_LBRACE = new BracesTailType() {
@Override
protected boolean isSpaceBeforeLBrace(CommonCodeStyleSettings styleSettings, Editor editor, int tailOffset) {
return styleSettings.SPACE_BEFORE_TRY_LBRACE;
}
};
public static final TailType DO_LBRACE = new BracesTailType() {
@Override
protected boolean isSpaceBeforeLBrace(CommonCodeStyleSettings styleSettings, Editor editor, int tailOffset) {
return styleSettings.SPACE_BEFORE_DO_LBRACE;
}
};
private static final TailType BRACES = new BracesTailType();
public static final TailType FINALLY_LBRACE = BRACES;
public static final TailType TRY_LBRACE = BRACES;
public static final TailType DO_LBRACE = BRACES;
@@ -15,10 +15,7 @@
*/
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementDecorator;
import com.intellij.codeInsight.lookup.LookupElementPresentation;
import com.intellij.codeInsight.lookup.TypedLookupItem;
import com.intellij.codeInsight.lookup.*;
import com.intellij.diagnostic.LogMessageEx;
import com.intellij.diagnostic.errordialog.Attachment;
import com.intellij.openapi.diagnostic.Logger;
@@ -97,8 +94,9 @@ public class JavaChainLookupElement extends LookupElementDecorator<LookupElement
final String qualifierText = myQualifier.as(CastingLookupElementDecorator.CLASS_CONDITION_KEY) != null ? "(" + name + ")" : name;
presentation.setItemText(qualifierText + "." + presentation.getItemText());
if (getQualifierObject() instanceof PsiClass) {
presentation.setTailText(StringUtil.notNullize(presentation.getTailText()) + qualifierPresentation.getTailText());
if (myQualifier instanceof LookupItem && getQualifierObject() instanceof PsiClass) {
String locationString = JavaPsiClassReferenceElement.getLocationString((LookupItem)myQualifier);
presentation.setTailText(StringUtil.notNullize(presentation.getTailText()) + locationString);
}
}
@@ -24,7 +24,6 @@ import com.intellij.patterns.ElementPattern;
import com.intellij.patterns.PsiJavaPatterns;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.SuggestedNameInfo;
import com.intellij.psi.codeStyle.VariableKind;
@@ -366,46 +365,36 @@ public class JavaMemberNameCompletionContributor extends CompletionContributor {
final boolean staticContext,
final PsiType varType,
final PsiElement element) {
class Change implements Runnable {
private String[] result;
final List<String> propertyHandlers = new ArrayList<String>();
@Override
public void run() {
final List<String> propertyHandlers = new ArrayList<String>();
final PsiField[] fields = psiClass.getFields();
for (final PsiField field : psiClass.getFields()) {
if (field == element) continue;
for (final PsiField field : fields) {
if (field == element) continue;
assert field.isValid() : "invalid field: " + field;
PsiType fieldType = field.getType();
assert fieldType.isValid() : "invalid field type: " + field + "; " + fieldType + " of " + fieldType.getClass();
assert field.isValid() : "invalid field: " + field;
PsiType fieldType = field.getType();
assert fieldType.isValid() : "invalid field type: " + field + "; " + fieldType + " of " + fieldType.getClass();
final PsiModifierList modifierList = field.getModifierList();
if (staticContext && (modifierList != null && !modifierList.hasModifierProperty(PsiModifier.STATIC))) continue;
final PsiModifierList modifierList = field.getModifierList();
if (staticContext && (modifierList != null && !modifierList.hasModifierProperty(PsiModifier.STATIC))) continue;
if (fieldType.equals(varType)) {
final String getterName = PropertyUtil.suggestGetterName(field.getProject(), field);
if ((psiClass.findMethodsByName(getterName, true).length == 0 ||
psiClass.findMethodBySignature(PropertyUtil.generateGetterPrototype(field), true) == null)) {
propertyHandlers.add(getterName);
}
}
if (fieldType.equals(varType)) {
final String getterName = PropertyUtil.suggestGetterName(field.getProject(), field);
if ((psiClass.findMethodsByName(getterName, true).length == 0 ||
psiClass.findMethodBySignature(PropertyUtil.generateGetterPrototype(field), true) == null)) {
propertyHandlers.add(getterName);
}
}
if (PsiType.VOID.equals(varType)) {
final String setterName = PropertyUtil.suggestSetterName(field.getProject(), field);
if ((psiClass.findMethodsByName(setterName, true).length == 0 ||
psiClass.findMethodBySignature(PropertyUtil.generateSetterPrototype(field), true) == null)) {
propertyHandlers.add(setterName);
}
}
if (PsiType.VOID.equals(varType)) {
final String setterName = PropertyUtil.suggestSetterName(field.getProject(), field);
if ((psiClass.findMethodsByName(setterName, true).length == 0 ||
psiClass.findMethodBySignature(PropertyUtil.generateSetterPrototype(field), true) == null)) {
propertyHandlers.add(setterName);
}
result = ArrayUtil.toStringArray(propertyHandlers);
}
}
final Change result = new Change();
CodeStyleManager.getInstance(element.getProject()).performActionWithFormatterDisabled(result);
return result.result;
return ArrayUtil.toStringArray(propertyHandlers);
}
private static void addLookupItems(Set<LookupElement> lookupElements, @Nullable final SuggestedNameInfo callback, PrefixMatcher matcher, Project project, String... strings) {
@@ -152,7 +152,7 @@ public class JavaPsiClassReferenceElement extends LookupItem<Object> {
presentation.setStrikeout(strikeout);
presentation.setItemTextBold(bold);
String tailText = StringUtil.notNullize((String) item.getAttribute(LookupItem.TAIL_TEXT_ATTR));
String tailText = getLocationString(item);
PsiSubstitutor substitutor = (PsiSubstitutor)item.getAttribute(LookupItem.SUBSTITUTOR);
if (item instanceof PsiTypeLookupItem) {
@@ -173,6 +173,10 @@ public class JavaPsiClassReferenceElement extends LookupItem<Object> {
presentation.setTailText(tailText, true);
}
public static String getLocationString(LookupItem item) {
return StringUtil.notNullize((String)item.getAttribute(LookupItem.TAIL_TEXT_ATTR));
}
private static String getName(final PsiClass psiClass, final LookupItem<?> item, boolean diamond) {
if (item instanceof JavaPsiClassReferenceElement) {
String forced = ((JavaPsiClassReferenceElement)item).getForcedPresentableName();
@@ -23,22 +23,31 @@ import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.util.text.CharArrayUtil;
/**
* @author peter
*/
public abstract class BracesTailType extends TailType {
protected abstract boolean isSpaceBeforeLBrace(CommonCodeStyleSettings styleSettings, Editor editor, final int tailOffset);
public class BracesTailType extends TailType {
@Override
public int processTail(final Editor editor, int tailOffset) {
final CommonCodeStyleSettings styleSettings = getLocalCodeStyleSettings(editor, tailOffset);
if (isSpaceBeforeLBrace(styleSettings, editor, tailOffset)) {
tailOffset = insertChar(editor, tailOffset, ' ');
int startOffset = tailOffset;
CharSequence seq = editor.getDocument().getCharsSequence();
int nextNonWs = CharArrayUtil.shiftForward(seq, tailOffset, " \t");
if (nextNonWs < seq.length() && seq.charAt(nextNonWs) == '{') {
tailOffset = nextNonWs + 1;
} else {
tailOffset = insertChar(editor, startOffset, '{');
}
tailOffset = insertChar(editor, tailOffset, '{');
tailOffset = reformatBrace(editor, tailOffset, startOffset);
if (EnterAfterUnmatchedBraceHandler.isAfterUnmatchedLBrace(editor, tailOffset, getFileType(editor))) {
new EnterHandler(EditorActionManager.getInstance().getActionHandler(IdeActions.ACTION_EDITOR_ENTER))
.executeWriteAction(editor, DataManager.getInstance().getDataContext(editor.getContentComponent()));
@@ -47,4 +56,16 @@ public abstract class BracesTailType extends TailType {
return tailOffset;
}
private static int reformatBrace(Editor editor, int tailOffset, int startOffset) {
Project project = editor.getProject();
if (project != null) {
PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
if (psiFile != null) {
editor.getCaretModel().moveToOffset(tailOffset);
CodeStyleManager.getInstance(project).reformatText(psiFile, startOffset, tailOffset);
tailOffset = editor.getCaretModel().getOffset();
}
}
return tailOffset;
}
}
@@ -20,6 +20,7 @@ import com.intellij.openapi.editor.ElementColorProvider;
import com.intellij.psi.*;
import com.intellij.psi.impl.JavaConstantExpressionEvaluator;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.ui.ColorUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -147,7 +148,7 @@ public class JavaColorProvider implements ElementColorProvider {
private static void replaceInt(PsiExpression expr, int newValue, boolean hex) {
PsiElementFactory factory = JavaPsiFacade.getElementFactory(expr.getProject());
if (getInt(expr) != newValue) {
String text = hex ? "0x" + Integer.toHexString(newValue & 0x00ffffff).toUpperCase() : Integer.toString(newValue);
String text = hex ? "0x" + ColorUtil.toHex(new Color(newValue)).toUpperCase() : Integer.toString(newValue);
expr.replace(factory.createExpressionFromText(text, null));
}
}
@@ -1040,7 +1040,8 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (myRefCountHolder != null) {
myRefCountHolder.registerReference(expression, result);
}
if (result.getElement() != null && !result.isAccessible()) {
final PsiElement method = result.getElement();
if (method != null && !result.isAccessible()) {
final String accessProblem = HighlightUtil.buildProblemWithAccessDescription(expression, result);
HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(accessProblem).create();
myHolder.add(info);
@@ -1075,6 +1076,17 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (!myHolder.hasErrorResults()) {
myHolder.add(HighlightUtil.checkUnhandledExceptions(expression, expression.getTextRange()));
}
if (!myHolder.hasErrorResults()) {
if (method instanceof PsiMethod && ((PsiMethod)method).hasModifierProperty(PsiModifier.ABSTRACT)) {
final PsiElement qualifier = expression.getQualifier();
if (qualifier instanceof PsiSuperExpression) {
myHolder.add(HighlightInfo
.newHighlightInfo(HighlightInfoType.ERROR)
.range(expression.getReferenceNameElement())
.descriptionAndTooltip("Abstract method '" + ((PsiMethod)method).getName() + "' cannot be accessed directly").create());
}
}
}
}
@Override
@@ -23,6 +23,7 @@ import com.intellij.ide.util.DirectoryChooserUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
@@ -43,6 +44,7 @@ import java.util.*;
* @author peter
*/
public class CreateClassOrPackageFix extends LocalQuickFixAndIntentionActionOnPsiElement {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.quickFix.CreateClassOrPackageFix");
private final List<PsiDirectory> myWritableDirectoryList;
private final String myPresentation;
@@ -233,9 +235,15 @@ public class CreateClassOrPackageFix extends LocalQuickFixAndIntentionActionOnPs
public static List<PsiDirectory> getWritableDirectoryListDefault(@Nullable final PsiPackage context,
final GlobalSearchScope scope,
final PsiManager psiManager) {
if (LOG.isDebugEnabled()) {
LOG.debug("Getting writable directory list for package '" + (context == null ? null : context.getQualifiedName()) + "', scope=" + scope);
}
final List<PsiDirectory> writableDirectoryList = new ArrayList<PsiDirectory>();
if (context != null) {
for (PsiDirectory directory : context.getDirectories()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Package directory: " + directory);
}
if (directory.isWritable() && scope.contains(directory.getVirtualFile())) {
writableDirectoryList.add(directory);
}
@@ -244,11 +252,17 @@ public class CreateClassOrPackageFix extends LocalQuickFixAndIntentionActionOnPs
else {
for (VirtualFile root : ProjectRootManager.getInstance(psiManager.getProject()).getContentSourceRoots()) {
PsiDirectory directory = psiManager.findDirectory(root);
if (LOG.isDebugEnabled()) {
LOG.debug("Root: " + root + ", directory: " + directory);
}
if (directory != null && directory.isWritable() && scope.contains(directory.getVirtualFile())) {
writableDirectoryList.add(directory);
}
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("Result " + writableDirectoryList);
}
return writableDirectoryList;
}
}
@@ -431,7 +431,13 @@ public class MethodParameterInfoHandler implements ParameterInfoHandlerWithTabAc
public void updateUI(final Object p, final ParameterInfoUIContext context) {
if (p instanceof CandidateInfo) {
CandidateInfo info = (CandidateInfo)p;
updateMethodPresentation((PsiMethod)info.getElement(), getCandidateInfoSubstitutor(info), context);
PsiMethod method = (PsiMethod)info.getElement();
if (!method.isValid()) {
context.setUIComponentEnabled(false);
return;
}
updateMethodPresentation(method, getCandidateInfoSubstitutor(info), context);
}
else {
updateMethodPresentation((PsiMethod)p, null, context);
@@ -28,6 +28,7 @@ import com.intellij.psi.impl.DebugUtil;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.impl.source.PsiClassReferenceType;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -213,27 +214,29 @@ public class PsiTypeLookupItem extends LookupItem {
final PsiClass psiClass = classResolveResult.getElement();
if (psiClass != null) {
final PsiSubstitutor substitutor = classResolveResult.getSubstitutor();
String name = psiClass.getName();
if (name != null) {
final PsiSubstitutor substitutor = classResolveResult.getSubstitutor();
PsiClass resolved = JavaPsiFacade.getInstance(psiClass.getProject()).getResolveHelper().resolveReferencedClass(psiClass.getName(), context);
PsiClass resolved = JavaPsiFacade.getInstance(psiClass.getProject()).getResolveHelper().resolveReferencedClass(name, context);
Set<String> allStrings = new HashSet<String>();
String lookupString = psiClass.getName();
allStrings.add(lookupString);
if (!psiClass.getManager().areElementsEquivalent(resolved, psiClass) && !PsiUtil.isInnerClass(psiClass)) {
// inner class name should be shown qualified if its not accessible by single name
PsiClass aClass = psiClass.getContainingClass();
while (aClass != null && !PsiUtil.isInnerClass(aClass)) {
lookupString = aClass.getName() + '.' + lookupString;
allStrings.add(lookupString);
aClass = aClass.getContainingClass();
Set<String> allStrings = new HashSet<String>();
allStrings.add(name);
if (!psiClass.getManager().areElementsEquivalent(resolved, psiClass) && !PsiUtil.isInnerClass(psiClass)) {
// inner class name should be shown qualified if its not accessible by single name
PsiClass aClass = psiClass.getContainingClass();
while (aClass != null && !PsiUtil.isInnerClass(aClass)) {
name = aClass.getName() + '.' + name;
allStrings.add(name);
aClass = aClass.getContainingClass();
}
}
}
PsiTypeLookupItem item = new PsiTypeLookupItem(psiClass, lookupString, diamond, bracketsCount, importFixer);
item.addLookupStrings(allStrings.toArray(new String[allStrings.size()]));
item.setAttribute(SUBSTITUTOR, substitutor);
return item;
PsiTypeLookupItem item = new PsiTypeLookupItem(psiClass, name, diamond, bracketsCount, importFixer);
item.addLookupStrings(ArrayUtil.toStringArray(allStrings));
item.setAttribute(SUBSTITUTOR, substitutor);
return item;
}
}
}
@@ -76,7 +76,7 @@ public class AnnotateMethodFix implements LocalQuickFix {
if (annotateOverriddenMethods()) {
PsiMethod[] methods = OverridingMethodsSearch.search(method, GlobalSearchScope.allScope(project), true).toArray(PsiMethod.EMPTY_ARRAY);
for (PsiMethod psiMethod : methods) {
if (!AnnotationUtil.isAnnotated(psiMethod, myAnnotation, false, false) && psiMethod.getManager().isInProject(psiMethod)) {
if (AnnotationUtil.isAnnotatingApplicable(psiMethod, myAnnotation) && !AnnotationUtil.isAnnotated(psiMethod, myAnnotation, false, false) && psiMethod.getManager().isInProject(psiMethod)) {
toAnnotate.add(psiMethod);
}
}
@@ -0,0 +1,288 @@
/*
* Copyright 2000-2013 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.dataFlow;
import com.intellij.codeInsight.*;
import com.intellij.codeInspection.*;
import com.intellij.openapi.project.*;
import com.intellij.openapi.ui.*;
import com.intellij.ui.*;
import com.intellij.ui.components.*;
import org.jetbrains.annotations.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
/**
* Dialog that appears when user clicks the "Configure IsNull/IsNotNull/True/False Check/Assertion Methods"
* on the Errors dialog for the Constant Conditions Inspection. It is divided into 6 parts
* <ol>
* <li>Is Null Check MethodsPanel</li>
* <li>Is Not Null Check MethodsPanel</li>
* <li>Assert Is Null MethodsPanel</li>
* <li>Assert Is Not Null MethodsPanel</li>
* <li>Assert True MethodsPanel</li>
* <li>Assert False MethodsPanel</li>
* </ol>
*
* @author <a href="mailto:johnnyclark@gmail.com">Johnny Clark</a>
* Creation Date: 8/3/12
*/
public class ConditionCheckDialog extends DialogWrapper {
private final Project myProject;
private final @NotNull Splitter mainSplitter;
private final @NotNull MethodsPanel myIsNullCheckMethodPanel;
private final @NotNull MethodsPanel myIsNotNullCheckMethodPanel;
private final @NotNull MethodsPanel myAssertIsNullMethodPanel;
private final @NotNull MethodsPanel myAssertIsNotNullMethodPanel;
private final @NotNull MethodsPanel myAssertTrueMethodPanel;
private final @NotNull MethodsPanel myAssertFalseMethodPanel;
public ConditionCheckDialog(Project project, String mainDialogTitle) {
super(project, true);
myProject = project;
final ConditionCheckManager manager = ConditionCheckManager.getInstance(myProject);
mainSplitter = new Splitter(true, 0.3f);
final Splitter topThirdSplitter = new Splitter(false);
final Splitter bottomTwoThirdsSplitter = new Splitter(true);
final Splitter isNullIsNotNullCheckMethodSplitter = new Splitter(false);
final Splitter assertTrueFalseMethodSplitter = new Splitter(false);
List<ConditionChecker> isNullCheckMethods = new ArrayList<ConditionChecker>(manager.getIsNullCheckMethods());
List<ConditionChecker> isNotNullCheckMethods = new ArrayList<ConditionChecker>(manager.getIsNotNullCheckMethods());
List<ConditionChecker> assertIsNullMethods = new ArrayList<ConditionChecker>(manager.getAssertIsNullMethods());
List<ConditionChecker> assertIsNotNullMethods = new ArrayList<ConditionChecker>(manager.getAssertIsNotNullMethods());
List<ConditionChecker> assertTrueMethods = new ArrayList<ConditionChecker>(manager.getAssertTrueMethods());
List<ConditionChecker> assertFalseMethods = new ArrayList<ConditionChecker>(manager.getAssertFalseMethods());
myAssertIsNullMethodPanel = new MethodsPanel(assertIsNullMethods, ConditionChecker.Type.ASSERT_IS_NULL_METHOD, myProject);
myAssertIsNotNullMethodPanel = new MethodsPanel(assertIsNotNullMethods, ConditionChecker.Type.ASSERT_IS_NOT_NULL_METHOD, myProject);
myIsNullCheckMethodPanel = new MethodsPanel(isNullCheckMethods, ConditionChecker.Type.IS_NULL_METHOD, myProject);
myIsNotNullCheckMethodPanel = new MethodsPanel(isNotNullCheckMethods, ConditionChecker.Type.IS_NOT_NULL_METHOD, myProject);
myAssertTrueMethodPanel = new MethodsPanel(assertTrueMethods, ConditionChecker.Type.ASSERT_TRUE_METHOD, myProject);
myAssertFalseMethodPanel = new MethodsPanel(assertFalseMethods, ConditionChecker.Type.ASSERT_FALSE_METHOD, myProject);
isNullIsNotNullCheckMethodSplitter.setFirstComponent(myIsNullCheckMethodPanel.getComponent());
isNullIsNotNullCheckMethodSplitter.setSecondComponent(myIsNotNullCheckMethodPanel.getComponent());
assertTrueFalseMethodSplitter.setFirstComponent(myAssertTrueMethodPanel.getComponent());
assertTrueFalseMethodSplitter.setSecondComponent(myAssertFalseMethodPanel.getComponent());
topThirdSplitter.setFirstComponent(myAssertIsNullMethodPanel.getComponent());
topThirdSplitter.setSecondComponent(myAssertIsNotNullMethodPanel.getComponent());
bottomTwoThirdsSplitter.setFirstComponent(isNullIsNotNullCheckMethodSplitter);
bottomTwoThirdsSplitter.setSecondComponent(assertTrueFalseMethodSplitter);
mainSplitter.setFirstComponent(topThirdSplitter);
mainSplitter.setSecondComponent(bottomTwoThirdsSplitter);
topThirdSplitter.setPreferredSize(new Dimension(600, 150));
bottomTwoThirdsSplitter.setPreferredSize(new Dimension(600, 300));
myAssertIsNullMethodPanel
.setOtherMethodsPanels(myAssertIsNotNullMethodPanel, myIsNullCheckMethodPanel, myIsNotNullCheckMethodPanel, myAssertTrueMethodPanel,
myAssertFalseMethodPanel);
myAssertIsNotNullMethodPanel
.setOtherMethodsPanels(myAssertIsNullMethodPanel, myIsNullCheckMethodPanel, myIsNotNullCheckMethodPanel, myAssertTrueMethodPanel,
myAssertFalseMethodPanel);
myIsNullCheckMethodPanel
.setOtherMethodsPanels(myAssertIsNullMethodPanel, myAssertIsNotNullMethodPanel, myIsNotNullCheckMethodPanel, myAssertTrueMethodPanel,
myAssertFalseMethodPanel);
myIsNotNullCheckMethodPanel
.setOtherMethodsPanels(myAssertIsNullMethodPanel, myAssertIsNotNullMethodPanel, myIsNullCheckMethodPanel, myAssertTrueMethodPanel,
myAssertFalseMethodPanel);
myAssertTrueMethodPanel
.setOtherMethodsPanels(myAssertIsNullMethodPanel, myAssertIsNotNullMethodPanel, myIsNotNullCheckMethodPanel, myIsNullCheckMethodPanel,
myAssertFalseMethodPanel);
myAssertFalseMethodPanel
.setOtherMethodsPanels(myAssertIsNullMethodPanel, myAssertIsNotNullMethodPanel, myIsNotNullCheckMethodPanel, myIsNullCheckMethodPanel,
myAssertTrueMethodPanel);
init();
setTitle(mainDialogTitle);
}
@Override
protected JComponent createCenterPanel() {
return mainSplitter;
}
@Override
protected void doOKAction() {
final ConditionCheckManager manager = ConditionCheckManager.getInstance(myProject);
manager.setIsNotNullCheckMethods(myIsNotNullCheckMethodPanel.getConditionChecker());
manager.setIsNullCheckMethods(myIsNullCheckMethodPanel.getConditionChecker());
manager.setAssertIsNotNullMethods(myAssertIsNotNullMethodPanel.getConditionChecker());
manager.setAssertIsNullMethods(myAssertIsNullMethodPanel.getConditionChecker());
manager.setAssertTrueMethods(myAssertTrueMethodPanel.getConditionChecker());
manager.setAssertFalseMethods(myAssertFalseMethodPanel.getConditionChecker());
super.doOKAction();
}
/**
* Is Null, Is Not Null, Assert True and Assert False Method Panel at the top of the main Dialog.
*/
class MethodsPanel {
private final @NotNull JBList myList;
private final @NotNull JPanel myPanel;
private final @NotNull Project myProject;
private Set<MethodsPanel> otherPanels;
public MethodsPanel(final List<ConditionChecker> checkers, final ConditionChecker.Type type, final @NotNull Project myProject) {
this.myProject = myProject;
myList = new JBList(new CollectionListModel<ConditionChecker>(checkers));
myPanel = new JPanel(new BorderLayout());
myPanel.setBorder(IdeBorderFactory.createTitledBorder(initTitle(type), false, new Insets(10, 0, 0, 0)));
myPanel.setPreferredSize(new Dimension(400, 150));
myList.setCellRenderer(new ColoredListCellRenderer() {
@Override
protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) {
String s = value.toString();
if (s.contains("*")) {
int indexOfAsterix1 = s.indexOf("*");
int indexOfAsterix2 = s.lastIndexOf("*");
if (indexOfAsterix1 >= 0 &&
indexOfAsterix1 < s.length() &&
indexOfAsterix2 >= 0 &&
indexOfAsterix2 < s.length() &&
indexOfAsterix1 < indexOfAsterix2) {
append(s.substring(0, indexOfAsterix1), SimpleTextAttributes.REGULAR_ATTRIBUTES);
append(s.substring(indexOfAsterix1 + 1, indexOfAsterix2), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
append(s.substring(indexOfAsterix2 + 1), SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
else {
append(s, SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
}
}
});
final ToolbarDecorator toolbarDecorator =
ToolbarDecorator.createDecorator(myList).disableUpDownActions().setAddAction(new AnActionButtonRunnable() {
@Override
public void run(AnActionButton anActionButton) {
chooseMethod(null, type, myList.getModel().getSize());
}
}).setRemoveAction(new AnActionButtonRunnable() {
@Override
public void run(AnActionButton anActionButton) {
CollectionListModel model = getCollectionListModel();
if (myList.getSelectedIndex() >= 0 && myList.getSelectedIndex() < model.getSize()) {
model.remove(myList.getSelectedIndex());
}
}
});
myList.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
int index = myList.locationToIndex(e.getPoint());
CollectionListModel<ConditionChecker> model = getCollectionListModel();
if (index >= 0 && model.getSize() > index) {
chooseMethod(model.getElementAt(index), type, index);
}
}
}
});
final JPanel panel = toolbarDecorator.createPanel();
myPanel.add(panel);
myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
private String initTitle(@NotNull ConditionChecker.Type type) {
if (type.equals(ConditionChecker.Type.IS_NULL_METHOD)) {
return InspectionsBundle.message("configure.checker.option.isNull.method.panel.title");
}
else if (type.equals(ConditionChecker.Type.IS_NOT_NULL_METHOD)) {
return InspectionsBundle.message("configure.checker.option.isNotNull.method.panel.title");
}
else if (type.equals(ConditionChecker.Type.ASSERT_IS_NULL_METHOD)) {
return InspectionsBundle.message("configure.checker.option.assert.isNull.method.panel.title");
}
else if (type.equals(ConditionChecker.Type.ASSERT_IS_NOT_NULL_METHOD)) {
return InspectionsBundle.message("configure.checker.option.assert.isNotNull.method.panel.title");
}
else if (type.equals(ConditionChecker.Type.ASSERT_TRUE_METHOD)) {
return InspectionsBundle.message("configure.checker.option.assert.true.method.panel.title");
}
else if (type.equals(ConditionChecker.Type.ASSERT_FALSE_METHOD)) {
return InspectionsBundle.message("configure.checker.option.assert.false.method.panel.title");
}
else {
throw new IllegalArgumentException("MethodCheckerDetailsDialog does not support type " + type);
}
}
private void chooseMethod(@Nullable ConditionChecker checker, ConditionChecker.Type type, int index) {
MethodCheckerDetailsDialog pickMethodPanel =
new MethodCheckerDetailsDialog(checker, type, myProject, myPanel, getConditionCheckers(), getOtherCheckers());
pickMethodPanel.show();
ConditionChecker chk = pickMethodPanel.getConditionChecker();
if (chk != null) {
CollectionListModel<ConditionChecker> model = getCollectionListModel();
if (model.getSize() <= index) {
model.add(chk);
}
else {
model.setElementAt(chk, index);
}
}
}
private CollectionListModel<ConditionChecker> getCollectionListModel() {
//noinspection unchecked
return (CollectionListModel<ConditionChecker>)myList.getModel();
}
@NotNull
public JPanel getComponent() {
return myPanel;
}
public List<ConditionChecker> getConditionChecker() {
CollectionListModel<ConditionChecker> model = getCollectionListModel();
return new ArrayList<ConditionChecker>(model.getItems());
}
public Set<ConditionChecker> getConditionCheckers() {
Set<ConditionChecker> set = new HashSet<ConditionChecker>();
set.addAll(getConditionChecker());
return set;
}
public void setOtherMethodsPanels(MethodsPanel p1, MethodsPanel p2, MethodsPanel p3, MethodsPanel p4, MethodsPanel p5) {
otherPanels = new HashSet<MethodsPanel>();
otherPanels.add(p1);
otherPanels.add(p2);
otherPanels.add(p3);
otherPanels.add(p4);
otherPanels.add(p5);
}
public Set<ConditionChecker> getOtherCheckers() {
Set<ConditionChecker> otherCheckers = new HashSet<ConditionChecker>();
for (MethodsPanel otherPanel : otherPanels) {
otherCheckers.addAll(otherPanel.getConditionCheckers());
}
return otherCheckers;
}
}
}
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInspection.dataFlow;
import com.intellij.codeInsight.ConditionCheckManager;
import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.codeInspection.dataFlow.instructions.*;
import com.intellij.codeInspection.dataFlow.value.*;
@@ -1218,7 +1219,7 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
ConditionalGotoInstruction cond = new ConditionalGotoInstruction(NOT_FOUND, false, null);
addInstruction(cond);
addInstruction(new EmptyStackInstruction());
addInstruction(new PushInstruction(myFactory.getTypeFactory().create(ref), null));
addInstruction(new PushInstruction(myFactory.getNotNullFactory().create(ref), null));
addThrowCode(ref);
cond.setOffset(myCurrentFlow.getInstructionCount());
}
@@ -1305,7 +1306,8 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
return true;
}
}
else if ("junit.framework.Assert".equals(className) || "org.junit.Assert".equals(className) || "org.testng.Assert".equals(className)) {
else if ("junit.framework.Assert".equals(className) || "org.junit.Assert".equals(className) ||
"junit.framework.TestCase".equals(className) || "org.testng.Assert".equals(className)) {
boolean testng = "org.testng.Assert".equals(className);
if ("fail".equals(methodName)) {
pushParameters(params, false, !testng);
@@ -1342,6 +1344,82 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
}
}
if (ConditionCheckManager.isCheck(resolved)) {
if (ConditionCheckManager.isAssertIsNullCheckMethod(resolved)) {
int paramIndex = 0;
for (PsiExpression param : params) {
param.accept(this);
if (ConditionCheckManager.isAssertIsNullCheckMethod(resolved, paramIndex++)) {
addInstruction(new PushInstruction(myFactory.getConstFactory().getNull(), null));
addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, expression.getProject()));
conditionalExit(exitPoint, false); // Exit if Equal NULL is True
} else {
addInstruction(new PopInstruction());
}
}
return true;
} else if (ConditionCheckManager.isAssertIsNotNullCheckMethod(resolved)) {
int paramIndex = 0;
for (PsiExpression param : params) {
param.accept(this);
if (ConditionCheckManager.isAssertIsNotNullCheckMethod(resolved, paramIndex++)) {
addInstruction(new PushInstruction(myFactory.getConstFactory().getNull(), null));
addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, expression.getProject()));
conditionalExit(exitPoint, true); // Exit if NotEqual NULL is True
} else {
addInstruction(new PopInstruction());
}
}
return true;
} else if (ConditionCheckManager.isNullCheckMethod(resolved)) {
int paramIndex = 0;
for (PsiExpression param : params) {
param.accept(this);
if (ConditionCheckManager.isNullCheckMethod(resolved, paramIndex++)) {
addInstruction(new PushInstruction(myFactory.getConstFactory().getNull(), null));
addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, expression.getProject()));
} else {
addInstruction(new PopInstruction());
}
}
return true;
} else if (ConditionCheckManager.isNotNullCheckMethod(resolved)) {
int paramIndex = 0;
for (PsiExpression param : params) {
param.accept(this);
if (ConditionCheckManager.isNotNullCheckMethod(resolved, paramIndex++)) {
addInstruction(new PushInstruction(myFactory.getConstFactory().getNull(), null));
addInstruction(new BinopInstruction(JavaTokenType.NE, null, expression.getProject()));
} else {
addInstruction(new PopInstruction());
}
}
return true;
} else if (ConditionCheckManager.isAssertTrueCheckMethod(resolved)) {
int paramIndex = 0;
for (PsiExpression param : params) {
param.accept(this);
if (ConditionCheckManager.isAssertTrueCheckMethod(resolved, paramIndex++)) {
conditionalExit(exitPoint, false);
} else {
addInstruction(new PopInstruction());
}
}
return true;
} else if (ConditionCheckManager.isAssertFalseCheckMethod(resolved)) {
int paramIndex = 0;
for (PsiExpression param : params) {
param.accept(this);
if (ConditionCheckManager.isAssertFalseCheckMethod(resolved, paramIndex++)) {
conditionalExit(exitPoint, true);
} else {
addInstruction(new PopInstruction());
}
}
return true;
}
}
// Idea project only.
if (qualifierExpression != null) {
if (qualifierExpression.textMatches("LOG")) {
@@ -587,6 +587,24 @@ public class DataFlowInspection extends BaseLocalInspectionTool {
gc.insets.bottom = 15;
add(configureAnnotations, gc);
final JButton configureCheckAnnotations = new JButton(InspectionsBundle.message("configure.checker.option.button"));
configureCheckAnnotations.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Project project = PlatformDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(OptionsPanel.this));
if (project == null) project = ProjectManager.getInstance().getDefaultProject();
final ConditionCheckDialog dialog = new ConditionCheckDialog(project,
InspectionsBundle.message("configure.checker.option.main.dialog.title")
);
dialog.show();
}
});
gc.gridy++;
gc.fill = GridBagConstraints.NONE;
gc.insets.left = 20;
gc.insets.bottom = 15;
add(configureCheckAnnotations, gc);
gc.fill = GridBagConstraints.HORIZONTAL;
gc.weighty = 1;
gc.insets.left = 0;
@@ -46,7 +46,7 @@ import java.util.*;
public class DataFlowRunner {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.dataFlow.DataFlowRunner");
private static final Key<Integer> TOO_EXPENSIVE_SIZE = Key.create("TOO_EXPENSIVE_SIZE");
private static final Key<Integer> TOO_EXPENSIVE_HASH = Key.create("TOO_EXPENSIVE_HASH");
public static final long ourTimeLimit = 1000 * 1000 * 1000; //1 sec in nanoseconds
private Instruction[] myInstructions;
@@ -103,14 +103,16 @@ public class DataFlowRunner {
myFields = flow.getFields();
if (LOG.isDebugEnabled()) {
LOG.debug("Analyzing code block: " + psiBlock.getText());
for (int i = 0; i < myInstructions.length; i++) {
Instruction instruction = myInstructions[i];
LOG.debug(i + ": " + instruction.toString());
}
}
Integer tooExpensiveSize = psiBlock.getUserData(TOO_EXPENSIVE_SIZE);
if (tooExpensiveSize != null && tooExpensiveSize == psiBlock.getText().hashCode()) {
Integer tooExpensiveHash = psiBlock.getUserData(TOO_EXPENSIVE_HASH);
if (tooExpensiveHash != null && tooExpensiveHash == psiBlock.getText().hashCode()) {
LOG.debug("Too complex because hasn't changed since being too complex already");
return RunnerResult.TOO_COMPLEX;
}
@@ -125,7 +127,8 @@ public class DataFlowRunner {
int count = 0;
while (!queue.isEmpty()) {
if (count % 50 == 0 && !unitTestMode && measurer.isTimeOver()) {
psiBlock.putUserData(TOO_EXPENSIVE_SIZE, psiBlock.getText().hashCode());
LOG.debug("Too complex because the analysis took too long");
psiBlock.putUserData(TOO_EXPENSIVE_HASH, psiBlock.getText().hashCode());
return RunnerResult.TOO_COMPLEX;
}
ProgressManager.checkCanceled();
@@ -140,11 +143,14 @@ public class DataFlowRunner {
if (instruction instanceof BranchingInstruction) {
if (!instruction.setMemoryStateProcessed(instructionState.getMemoryState().createCopy())) {
LOG.debug("Too complex because too many different possible states");
return RunnerResult.TOO_COMPLEX; // Too complex :(
}
}
//System.out.println(instructionState);
if (LOG.isDebugEnabled()) {
LOG.debug(instructionState.toString());
}
DfaInstructionState[] after = instruction.accept(this, instructionState.getMemoryState(), visitor);
if (after != null) {
@@ -160,15 +166,18 @@ public class DataFlowRunner {
count++;
}
psiBlock.putUserData(TOO_EXPENSIVE_SIZE, null);
psiBlock.putUserData(TOO_EXPENSIVE_HASH, null);
LOG.debug("Analysis ok");
return RunnerResult.OK;
}
catch (ArrayIndexOutOfBoundsException e) {
LOG.error(psiBlock.getText(), e); /* TODO[max] !!! hack (of 18186). Please fix in better times. */
LOG.error(psiBlock.getText(), e); // TODO fix in better times
return RunnerResult.ABORTED;
}
catch (EmptyStackException e) {
//LOG.error(psiBlock.getText(), e); /* TODO[max] !!! hack (of 18186). Please fix in better times. */
if (LOG.isDebugEnabled()) {
LOG.error(e); // TODO fix in better times
}
return RunnerResult.ABORTED;
}
}
@@ -0,0 +1,708 @@
/*
* Copyright 2000-2013 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.dataFlow;
import com.intellij.codeInsight.*;
import com.intellij.codeInspection.*;
import com.intellij.ide.util.*;
import com.intellij.openapi.editor.event.*;
import com.intellij.openapi.project.*;
import com.intellij.openapi.ui.*;
import com.intellij.psi.*;
import com.intellij.psi.search.*;
import com.intellij.ui.*;
import org.jetbrains.annotations.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.util.*;
import java.util.List;
import static com.intellij.codeInsight.ConditionChecker.Type.*;
/**
* Dialog that appears when the user clicks the Add Button or double clicks a row item in a MethodsPanel. The MethodsPanel is accessed from the ConditionCheckDialog
*/
class MethodCheckerDetailsDialog extends DialogWrapper implements PropertyChangeListener, ItemListener {
private final @NotNull ConditionChecker.Type myType;
private final @NotNull Project myProject;
private final @NotNull ParameterDropDown parameterDropDown;
private final @NotNull MethodDropDown methodDropDown;
private final @NotNull ClassField classField;
private final @NotNull Set<ConditionChecker> myOtherCheckers;
private final @Nullable ConditionChecker myPreviouslySelectedChecker;
/**
* Set by the OK and/or Cancel actions so that the caller can retrieve it via a call to getMethodIsNullIsNotNullChecker
*/
private @Nullable ConditionChecker mySelectedChecker;
MethodCheckerDetailsDialog(@Nullable ConditionChecker previouslySelectedChecker,
@NotNull ConditionChecker.Type type,
@NotNull Project project,
@NotNull Component component,
@NotNull Set<ConditionChecker> otherCheckersSameType,
@NotNull Set<ConditionChecker> otherCheckers) {
super(component, true);
if (!isSupported(type)) throw new IllegalArgumentException("Type is invalid " + type);
myProject = project;
myType = type;
myOtherCheckers = new HashSet<ConditionChecker>(otherCheckersSameType);
myOtherCheckers.addAll(otherCheckers);
myPreviouslySelectedChecker = previouslySelectedChecker;
if (myPreviouslySelectedChecker != null) myOtherCheckers.remove(myPreviouslySelectedChecker);
PsiClass psiClass = null;
PsiMethod psiMethod = null;
PsiParameter psiParameter = null;
if (previouslySelectedChecker != null) {
psiClass =
JavaPsiFacade.getInstance(myProject).findClass(previouslySelectedChecker.getClassName(), GlobalSearchScope.allScope(myProject));
if (psiClass != null) {
for (PsiMethod method : psiClass.findMethodsByName(previouslySelectedChecker.getMethodName(), true)) {
if (previouslySelectedChecker.equals(buildParameterClassListFromPsiMethod(method))) {
psiMethod = method;
break;
}
}
}
if (psiMethod != null) {
PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
if (parameters.length - 1 >= previouslySelectedChecker.getCheckedParameterIndex()) {
psiParameter = parameters[previouslySelectedChecker.getCheckedParameterIndex()];
}
}
}
if (psiClass == null || psiMethod == null || psiParameter == null) {
psiClass = null;
psiMethod = null;
psiParameter = null;
}
classField = new ClassField(myProject, psiClass);
methodDropDown = new MethodDropDown(psiClass, psiMethod, myType, MethodDropDown.buildModel());
parameterDropDown = new ParameterDropDown(psiMethod, psiParameter, ParameterDropDown.buildModel(), myType);
classField.addPropertyChangeListener(methodDropDown);
classField.addPropertyChangeListener(parameterDropDown);
classField.addPropertyChangeListener(this);
methodDropDown.addItemListener(parameterDropDown);
methodDropDown.addItemListener(this);
parameterDropDown.addItemListener(this);
init();
checkOkActionEnable();
setTitle(initTitle(type));
}
private static boolean isSupported(ConditionChecker.Type type) {
return type == IS_NULL_METHOD || type == IS_NOT_NULL_METHOD ||
type == ASSERT_IS_NULL_METHOD || type == ASSERT_IS_NOT_NULL_METHOD ||
type == ASSERT_TRUE_METHOD || type == ASSERT_FALSE_METHOD;
}
private static List<String> buildParameterClassListFromPsiMethod(PsiMethod psiMethod) {
List<String> parameterClasses = new ArrayList<String>();
PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
for (PsiParameter param : parameters) {
PsiTypeElement typeElement = param.getTypeElement();
if (typeElement == null) return new ArrayList<String>();
PsiType psiType = typeElement.getType();
parameterClasses.add(psiType.getCanonicalText());
}
return parameterClasses;
}
private static String initTitle(@NotNull ConditionChecker.Type type) {
if (type.equals(IS_NULL_METHOD)) {
return InspectionsBundle.message("configure.checker.option.isNull.add.method.checker.dialog.title");
}
else if (type.equals(IS_NOT_NULL_METHOD)) {
return InspectionsBundle.message("configure.checker.option.isNotNull.add.method.checker.dialog.title");
}
else if (type.equals(ASSERT_IS_NULL_METHOD)) {
return InspectionsBundle.message("configure.checker.option.assert.isNull.add.method.checker.dialog.title");
}
else if (type.equals(ASSERT_IS_NOT_NULL_METHOD)) {
return InspectionsBundle.message("configure.checker.option.assert.isNotNull.add.method.checker.dialog.title");
}
else if (type.equals(ASSERT_TRUE_METHOD)) {
return InspectionsBundle.message("configure.checker.option.assert.true.add.method.checker.dialog.title");
}
else if (type.equals(ASSERT_FALSE_METHOD)) {
return InspectionsBundle.message("configure.checker.option.assert.false.add.method.checker.dialog.title");
}
else {
throw new IllegalArgumentException("MethodCheckerDetailsDialog does not support type " + type);
}
}
@Override
protected JComponent createCenterPanel() {
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
final LabeledComponent<ClassField> classComponent = new LabeledComponent<ClassField>();
final LabeledComponent<MethodDropDown> methodComponent = new LabeledComponent<MethodDropDown>();
final LabeledComponent<ParameterDropDown> parameterComponent = new LabeledComponent<ParameterDropDown>();
classComponent.setText("Class");
methodComponent.setText("Method");
parameterComponent.setText("Parameter");
classComponent.setComponent(classField);
methodComponent.setComponent(methodDropDown);
parameterComponent.setComponent(parameterDropDown);
panel.add(classComponent);
panel.add(methodComponent);
panel.add(parameterComponent);
return panel;
}
@Nullable
ConditionChecker getConditionChecker() {
return mySelectedChecker;
}
@Nullable
private ConditionChecker buildConditionChecker() {
PsiClass psiClass = classField.getPsiClass();
PsiMethod psiMethod = methodDropDown.getSelectedPsiMethod();
PsiParameter psiParameter = parameterDropDown.getSelectedPsiParameter();
if (psiClass != null && psiMethod != null && psiParameter != null) {
return new ConditionChecker.FromPsiBuilder(psiMethod, psiParameter, myType).build();
}
else {
return null;
}
}
private boolean overlaps(ConditionChecker thisChecker) {
for (ConditionChecker overlappingChecker : myOtherCheckers) {
if (thisChecker.overlaps(overlappingChecker)) {
Messages.showMessageDialog(myProject, InspectionsBundle.message("configure.checker.option.overlap.error.msg") +
" " +
overlappingChecker.getConditionCheckType() + " " + overlappingChecker.toString(),
InspectionsBundle.message("configure.checker.option.overlap.error.title"), Messages.getErrorIcon());
return true;
}
}
return false;
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
checkOkActionEnable();
}
@Override
public void itemStateChanged(ItemEvent e) {
checkOkActionEnable();
}
private void checkOkActionEnable() {
if (classField.getPsiClass() == null ||
methodDropDown.getSelectedPsiMethod() == null ||
parameterDropDown.getSelectedPsiParameter() == null) {
setOKActionEnabled(false);
}
else {
setOKActionEnabled(true);
}
}
@Override
protected void doOKAction() {
ConditionChecker checker = buildConditionChecker();
if (checker != null && !overlaps(checker)) {
if (checker.equals(myPreviouslySelectedChecker)) {
mySelectedChecker = myPreviouslySelectedChecker;
}
else {
mySelectedChecker = checker;
}
super.doOKAction();
}
}
public boolean isOKActionEnabled() {
if (!myOKAction.isEnabled()) return false;
PsiClass psiClass = classField.getPsiClass();
PsiMethod psiMethod = methodDropDown.getSelectedPsiMethod();
PsiParameter psiParameter = parameterDropDown.getSelectedPsiParameter();
if (psiClass == null || psiMethod == null || psiParameter == null) {
return false;
}
else {
return true;
}
}
/**
* Input Text Field for Class Name
*/
static class ClassField extends EditorTextFieldWithBrowseButton implements ActionListener, DocumentListener {
public static final String PROPERTY_PSICLASS = "ClassField.myPsiClass";
private final @NotNull Project myProject;
private @Nullable PsiClass myPsiClass;
public ClassField(@NotNull Project project, @Nullable PsiClass psiClass) {
super(project, true, buildVisibilityChecker());
myProject = project;
myPsiClass = psiClass;
setPreferredSize(new Dimension(500, (int)getPreferredSize().getHeight()));
if (myPsiClass != null) { //noinspection ConstantConditions
setText(myPsiClass.getQualifiedName());
}
addActionListener(this);
getChildComponent().addDocumentListener(this);
}
private static JavaCodeFragment.VisibilityChecker buildVisibilityChecker() {
return new JavaCodeFragment.VisibilityChecker() {
@Override
public Visibility isDeclarationVisible(PsiElement declaration, PsiElement place) {
return Visibility.VISIBLE;
}
};
}
@Override
public void actionPerformed(ActionEvent e) {
final TreeClassChooser chooser = TreeClassChooserFactory.getInstance(myProject)
.createNoInnerClassesScopeChooser("Choose Class", GlobalSearchScope.allScope(myProject), new ClassFilter() {
@Override
public boolean isAccepted(PsiClass aClass) {
return !aClass.isAnnotationType();
}
}, null);
chooser.showDialog();
PsiClass psiClass = chooser.getSelected();
if (psiClass != null) { //noinspection ConstantConditions
setText(chooser.getSelected().getQualifiedName());
}
}
@Nullable
public PsiClass getPsiClass() {
return myPsiClass;
}
@Override
public void beforeDocumentChange(DocumentEvent event) {
}
@Override
public void documentChanged(DocumentEvent event) {
String className = event.getDocument().getText();
PsiClass psiClass = null;
if (className != null) {
psiClass = JavaPsiFacade.getInstance(myProject).findClass(className, GlobalSearchScope.allScope(myProject));
}
if (psiClass != null && myPsiClass != null) {
if (!psiClass.equals(myPsiClass)) {
firePropertyChange(PROPERTY_PSICLASS, myPsiClass, psiClass);
myPsiClass = psiClass;
}
}
else if (psiClass != null) {
firePropertyChange(PROPERTY_PSICLASS, myPsiClass, psiClass);
myPsiClass = psiClass;
}
else if (myPsiClass != null) {
firePropertyChange(PROPERTY_PSICLASS, myPsiClass, psiClass);
myPsiClass = null;
}
}
}
/**
* Drop Down for picking Method Name
*/
static class MethodDropDown extends JComboBox implements PropertyChangeListener {
private final @NotNull ConditionChecker.Type myType;
private final @NotNull SortedComboBoxModel<MethodWrapper> myModel;
private @Nullable PsiClass myPsiClass;
MethodDropDown(@Nullable PsiClass psiClass,
@Nullable PsiMethod psiMethod,
@NotNull ConditionChecker.Type type,
@NotNull SortedComboBoxModel<MethodWrapper> model) {
super(model);
if (!isSupported(type)) throw new IllegalArgumentException("Type is invalid " + type);
myPsiClass = psiClass;
myType = type;
myModel = model;
setEnabled(myPsiClass != null);
initValues();
if (psiMethod != null) {
for (Iterator<MethodWrapper> iterator = myModel.iterator(); iterator.hasNext(); ) {
MethodWrapper methodWrapper = iterator.next();
if (methodWrapper.getPsiMethod().equals(psiMethod)) {
setSelectedItem(methodWrapper);
}
}
}
}
private static boolean isMethodFromJavaLangObject(PsiMethod method) {
if (method == null) return false;
PsiClass containingClass = method.getContainingClass();
if (containingClass == null) return false;
String name = containingClass.getQualifiedName();
if (name == null) return false;
if (CommonClassNames.JAVA_LANG_OBJECT.equals(name)) return true;
return false;
}
@NotNull
public static SortedComboBoxModel<MethodWrapper> buildModel() {
return new SortedComboBoxModel<MethodWrapper>(new Comparator<MethodWrapper>() {
@Override
public int compare(MethodWrapper o1, MethodWrapper o2) {
return o1.compareTo(o2);
}
});
}
private void initValues() {
if (myPsiClass != null) {
myModel.clear();
myModel.setSelectedItem(null);
PsiMethod[] allMethods = myPsiClass.getAllMethods();
for (PsiMethod method : allMethods) {
MethodWrapper methodWrapper = new MethodWrapper(method);
if (qualifies(method) && !myModel.getItems().contains(methodWrapper)) myModel.add(methodWrapper);
}
}
}
public boolean qualifies(PsiMethod psiMethod) {
if (isMethodFromJavaLangObject(psiMethod)) {
return false;
}
final PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
if (parameters.length < 1) {
return false;
}
if (myType == IS_NULL_METHOD || myType == IS_NOT_NULL_METHOD) {
PsiType returnType = psiMethod.getReturnType();
if (returnType != PsiType.BOOLEAN && (returnType == null || !returnType.getCanonicalText().equals(Boolean.class.toString()))) {
return false;
}
}
else if (myType == ASSERT_TRUE_METHOD || myType == ASSERT_FALSE_METHOD) {
boolean booleanParamExists = false;
for (PsiParameter psiParameter : parameters) {
PsiType type = psiParameter.getType();
if (type.equals(PsiType.BOOLEAN) || type.getCanonicalText().equals(Boolean.class.toString())) {
booleanParamExists = true;
break;
}
}
if (!booleanParamExists) {
return false;
}
}
// Else it's ASSERT_IS_NULL_METHOD or ASSERT_IS_NOT_NULL_METHOD.
// In that case there is no additional validation
return true;
}
/**
* Called when ClassField is set and when user selects entry in the MethodDropDown
*/
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(ClassField.PROPERTY_PSICLASS)) {
if (evt.getNewValue() == null) {
clear();
}
else {
setEnabled(true);
if (myPsiClass == null || !myPsiClass.equals(evt.getNewValue())) { // ClassChanged so refresh list
myPsiClass = (PsiClass)evt.getNewValue();
initValues();
}
}
}
}
public void clear() {
myModel.clear();
myModel.setSelectedItem(null);
setEnabled(false);
myPsiClass = null;
}
@Nullable
public PsiMethod getSelectedPsiMethod() {
MethodWrapper methodWrapper = myModel.getSelectedItem();
if (methodWrapper == null) return null;
return methodWrapper.getPsiMethod();
}
}
/**
* Drop Down for picking Parameter Name
*/
static class ParameterDropDown extends JComboBox implements PropertyChangeListener, ItemListener {
private final @NotNull SortedComboBoxModel<ParameterWrapper> myModel;
private final @NotNull ConditionChecker.Type myType;
private @Nullable PsiMethod myPsiMethod;
public ParameterDropDown(@Nullable PsiMethod psiMethod,
@Nullable PsiParameter psiParameter,
@NotNull SortedComboBoxModel<ParameterWrapper> model,
@NotNull ConditionChecker.Type type) {
super(model);
if (!isSupported(type)) throw new IllegalArgumentException("Type is invalid " + type);
myPsiMethod = psiMethod;
myModel = model;
myType = type;
if (myPsiMethod != null) {
setEnabled(true);
myModel.addAll(getParameterWrappers());
if (psiParameter != null) {
for (Iterator iterator = myModel.iterator(); iterator.hasNext(); ) {
ParameterWrapper wrapper = (ParameterWrapper)iterator.next();
if (wrapper.getPsiParameter().equals(psiParameter)) setSelectedItem(wrapper);
}
}
}
else {
setEnabled(false);
}
}
public static SortedComboBoxModel<ParameterWrapper> buildModel() {
return new SortedComboBoxModel<ParameterWrapper>(new Comparator<ParameterWrapper>() {
@Override
public int compare(ParameterWrapper o1, ParameterWrapper o2) {
return o1.compareTo(o2);
}
});
}
List<ParameterWrapper> getParameterWrappers() {
List<ParameterWrapper> wrappers = new ArrayList<ParameterWrapper>();
if (myPsiMethod != null) {
PsiParameterList parameterList = myPsiMethod.getParameterList();
for (int i = 0; i < parameterList.getParameters().length; i++) {
PsiParameter psiParameter = parameterList.getParameters()[i];
if (myType == ASSERT_TRUE_METHOD || myType == ASSERT_FALSE_METHOD) {
PsiType type = psiParameter.getType();
if (type.equals(PsiType.BOOLEAN) || type.getCanonicalText().equals(Boolean.class.toString())) {
wrappers.add(new ParameterWrapper(psiParameter, i));
}
}
else {
wrappers.add(new ParameterWrapper(psiParameter, i));
}
}
}
return wrappers;
}
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getSource() instanceof MethodDropDown) { // The MethodDropDown has changed.
MethodDropDown methodDropDown = (MethodDropDown)e.getSource();
if (methodDropDown.getSelectedPsiMethod() != null) {
setEnabled(true);
if (myPsiMethod == null || !myPsiMethod.equals(methodDropDown.getSelectedPsiMethod())) {
myPsiMethod = methodDropDown.getSelectedPsiMethod();
myModel.clear();
myModel.addAll(getParameterWrappers());
myModel.setSelectedItem(null);
}
}
else {
myPsiMethod = null;
myModel.clear();
myModel.setSelectedItem(null);
setEnabled(false);
}
}
else {
throw new RuntimeException("Unexpected Configuration ParameterDropDown is only expected to receive events from MethodDropDown.");
}
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(ClassField.PROPERTY_PSICLASS)) {
if (evt.getNewValue() == null) {
setEnabled(false);
}
}
}
@Nullable
public PsiParameter getSelectedPsiParameter() {
ParameterWrapper parameterWrapper = myModel.getSelectedItem();
if (parameterWrapper == null) return null;
return parameterWrapper.getPsiParameter();
}
class ParameterWrapper implements Comparable<ParameterWrapper> {
private final @NotNull String id;
private final @NotNull PsiParameter psiParameter;
private final int index;
ParameterWrapper(@NotNull PsiParameter psiParameter, int index) {
this.psiParameter = psiParameter;
this.index = index;
String typeName;
PsiTypeElement typeElement = psiParameter.getTypeElement();
if (typeElement == null) {
typeName = "";
}
else {
if (typeElement.getType() instanceof PsiPrimitiveType) {
typeName = ((PsiPrimitiveType)typeElement.getType()).getBoxedTypeName();
}
else {
typeName = typeElement.getType().getCanonicalText();
}
}
id = typeName + " " + psiParameter.getName();
}
@Override
public int compareTo(ParameterWrapper o) {
return index - o.index;
}
@Override
public String toString() {
return id;
}
@NotNull
public PsiParameter getPsiParameter() {
return psiParameter;
}
}
}
static class MethodWrapper implements Comparable<MethodWrapper> {
private final @NotNull PsiMethod myPsiMethod;
private final @NotNull String myId;
MethodWrapper(@NotNull PsiMethod psiMethod) {
this.myPsiMethod = psiMethod;
List<String> parameterClassNames = new ArrayList<String>();
PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
for (PsiParameter psiParameter : parameters) {
parameterClassNames.add(getParameterQualifiedName(psiParameter));
}
myId = initId(psiMethod.getName(), parameterClassNames);
}
private static String getParameterQualifiedName(PsiParameter psiParameter) {
PsiTypeElement typeElement = psiParameter.getTypeElement();
if (typeElement == null) {
return "";
}
if (typeElement.getType() instanceof PsiPrimitiveType) {
return ((PsiPrimitiveType)typeElement.getType()).getBoxedTypeName();
}
return typeElement.getType().getCanonicalText();
}
private static String initId(String methodName, List<String> parameterNames) {
String shortName = methodName + "(";
for (String parameterName : parameterNames) {
if (parameterNames.lastIndexOf(".") > -1) {
shortName += parameterName.substring(parameterName.lastIndexOf(".") + 1) + ", ";
}
else {
shortName += parameterName + ", ";
}
}
if (parameterNames.size() > 0) shortName = shortName.substring(0, shortName.lastIndexOf(", "));
shortName += ")";
return shortName;
}
@NotNull
public PsiMethod getPsiMethod() {
return myPsiMethod;
}
@NotNull
public String getId() {
return myId;
}
@Override
public String toString() {
return myId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MethodWrapper that = (MethodWrapper)o;
if (!myId.equals(that.myId)) return false;
return true;
}
@Override
public int hashCode() {
return myId.hashCode();
}
@Override
public int compareTo(MethodWrapper o) {
return myId.compareTo(o.myId);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -33,7 +33,6 @@ import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.reference.SoftReference;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.PatchedSoftReference;
import com.intellij.util.containers.ConcurrentHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -82,7 +81,7 @@ public class MethodBodyChecker {
SoftReference<Map<String, PsiMethod>> ref = aClass.getUserData(CACHE_KEY);
Map<String, PsiMethod> cache = ref == null ? null : ref.get();
if (cache == null) {
aClass.putUserData(CACHE_KEY, new PatchedSoftReference<Map<String, PsiMethod>>(cache = new ConcurrentHashMap<String, PsiMethod>()));
aClass.putUserData(CACHE_KEY, new SoftReference<Map<String, PsiMethod>>(cache = new ConcurrentHashMap<String, PsiMethod>()));
}
return cache;
}
@@ -107,7 +106,7 @@ public class MethodBodyChecker {
if (PsiEquivalenceUtil.areElementsEquivalent(body, templateBody, new Comparator<PsiElement>(){
public int compare(final PsiElement element1, final PsiElement element2) {
// templates may be different on super method name
// templates may be different on super method name
if (element1 == superMethod && (element2 == templateMethod || element2 == null)) return 0;
return 1;
}
@@ -1,67 +0,0 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInspection.deprecation;
import com.intellij.codeInspection.*;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PsiModifierListImpl;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
// todo[r.sh] drop this after transition period finished
public class DeprecatedDefenderSyntaxInspection extends BaseJavaLocalInspectionTool {
private final LocalQuickFix myQuickFix = new MyQuickFix();
@Nullable
@Override
public ProblemDescriptor[] checkMethod(@NotNull PsiMethod method, @NotNull InspectionManager manager, boolean isOnTheFly) {
final PsiJavaToken marker = PsiModifierListImpl.findExtensionMethodMarker(method);
return marker == null ? null : new ProblemDescriptor[]{
manager.createProblemDescriptor(marker, getDisplayName(), myQuickFix, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly)
};
}
private static class MyQuickFix implements LocalQuickFix {
@NotNull
@Override
public String getName() {
return InspectionsBundle.message("deprecated.defender.syntax.fix");
}
@NotNull
@Override
public String getFamilyName() {
return "";
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement marker = descriptor.getPsiElement();
if (marker != null && PsiUtil.isJavaToken(marker, JavaTokenType.DEFAULT_KEYWORD)) {
final PsiElement parent = marker.getParent();
if (parent instanceof PsiMethod) {
marker.delete();
final PsiMethod method = (PsiMethod)parent;
if (!method.hasModifierProperty(PsiModifier.DEFAULT)) {
PsiUtil.setModifierProperty(method, PsiModifier.DEFAULT, true);
}
}
}
}
}
}
@@ -81,7 +81,9 @@ public class AnnotateOverriddenMethodParameterFix implements LocalQuickFix {
for (PsiParameter psiParam : toAnnotate) {
try {
assert psiParam != null : toAnnotate;
new AddAnnotationFix(myAnnotation, psiParam, myAnnosToRemove).invoke(project, null, psiParam.getContainingFile());
if (AnnotationUtil.isAnnotatingApplicable(psiParam, myAnnotation)) {
new AddAnnotationFix(myAnnotation, psiParam, myAnnosToRemove).invoke(project, null, psiParam.getContainingFile());
}
}
catch (IncorrectOperationException e) {
LOG.error(e);
@@ -0,0 +1,66 @@
/*
* Copyright 2000-2013 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.nullable;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiAnnotation;
import org.jetbrains.annotations.NotNull;
/**
* User: anna
* Date: 2/22/13
*/
class ChangeNullableDefaultsFix implements LocalQuickFix {
private final NullableNotNullManager myManager;
private final String myNotNullName;
private final String myNullableName;
public ChangeNullableDefaultsFix(PsiAnnotation notNull, PsiAnnotation nullable, NullableNotNullManager manager) {
myNotNullName = notNull != null ? notNull.getQualifiedName() : null;
myNullableName = nullable != null ? nullable.getQualifiedName() : null;
myManager = manager;
}
ChangeNullableDefaultsFix(String notNull, String nullable, NullableNotNullManager manager) {
myManager = manager;
myNotNullName = notNull;
myNullableName = nullable;
}
@NotNull
@Override
public String getName() {
return "Make \"" + (myNotNullName != null ? myNotNullName : myNullableName) + "\" default annotation";
}
@NotNull
@Override
public String getFamilyName() {
return getName();
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
if (myNotNullName != null) {
myManager.setDefaultNotNull(myNotNullName);
} else {
myManager.setDefaultNullable(myNullableName);
}
}
}
@@ -85,6 +85,14 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
final String anno = annotated.isDeclaredNotNull ? manager.getDefaultNotNull() : manager.getDefaultNullable();
final List<String> annoToRemove = annotated.isDeclaredNotNull ? manager.getNullables() : manager.getNotNulls();
if (!AnnotationUtil.isAnnotatingApplicable(field, anno)) {
final PsiAnnotation notNull = AnnotationUtil.findAnnotation(field, manager.getNotNulls());
final PsiAnnotation nullable = AnnotationUtil.findAnnotation(field, manager.getNullables());
holder.registerProblem(field.getNameIdentifier(), "Nullable/NotNull defaults are not accessible in current context",
new ChangeNullableDefaultsFix(notNull, nullable, manager));
return;
}
String propName = JavaCodeStyleManager.getInstance(project).variableNameToPropertyName(field.getName(), VariableKind.FIELD);
final boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC);
final PsiMethod getter = PropertyUtil.findPropertyGetter(field.getContainingClass(), propName, isStatic, false);
@@ -289,9 +297,13 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
reported_not_annotated_method_overrides_notnull = true;
final String defaultNotNull = nullableManager.getDefaultNotNull();
final String[] annotationsToRemove = ArrayUtil.toStringArray(nullableManager.getNullables());
final LocalQuickFix fix = AnnotationUtil.isAnnotatingApplicable(method, defaultNotNull)
? createAnnotateMethodFix(defaultNotNull, annotationsToRemove)
: createChangeDefaultNotNullFix(nullableManager, superMethod);
holder.registerProblem(method.getNameIdentifier(),
InspectionsBundle.message("inspection.nullable.problems.method.overrides.NotNull"),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, createAnnotateMethodFix(defaultNotNull, annotationsToRemove));
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
wrapFix(fix));
}
if (REPORT_NOTNULL_PARAMETER_OVERRIDES_NULLABLE || REPORT_NOT_ANNOTATED_METHOD_OVERRIDES_NOTNULL) {
PsiParameter[] superParameters = superMethod.getParameterList().getParameters();
@@ -313,10 +325,13 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
if (!AnnotationUtil.isAnnotated(parameter, nullableManager.getAllAnnotations(), false, false) &&
nullableManager.isNotNull(superParameter, false)) {
reported_not_annotated_parameter_overrides_notnull[i] = true;
final LocalQuickFix fix = AnnotationUtil.isAnnotatingApplicable(parameter, nullableManager.getDefaultNotNull())
? new AddNotNullAnnotationFix(parameter)
: createChangeDefaultNotNullFix(nullableManager, superParameter);
holder.registerProblem(parameter.getNameIdentifier(),
InspectionsBundle.message("inspection.nullable.problems.parameter.overrides.NotNull"),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
new AddNotNullAnnotationFix(parameter));
wrapFix(fix));
}
}
}
@@ -334,22 +349,34 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
}
if (hasAnnotatedParameter || annotated.isDeclaredNotNull) {
PsiManager manager = method.getManager();
final String defaultNotNull = nullableManager.getDefaultNotNull();
final boolean superMethodApplicable = AnnotationUtil.isAnnotatingApplicable(method, defaultNotNull);
PsiMethod[] overridings =
OverridingMethodsSearch.search(method, GlobalSearchScope.allScope(manager.getProject()), true).toArray(PsiMethod.EMPTY_ARRAY);
boolean methodQuickFixSuggested = false;
for (PsiMethod overriding : overridings) {
if (!manager.isInProject(overriding)) continue;
final boolean applicable = AnnotationUtil.isAnnotatingApplicable(overriding, defaultNotNull);
if (!methodQuickFixSuggested
&& annotated.isDeclaredNotNull
&& !nullableManager.isNotNull(overriding, false)
&& (nullableManager.isNullable(overriding, false) || !nullableManager.isNullable(overriding, true))) {
method.getNameIdentifier(); //load tree
PsiAnnotation annotation = AnnotationUtil.findAnnotation(method, nullableManager.getNotNulls());
final String defaultNotNull = nullableManager.getDefaultNotNull();
PsiAnnotation annotation = AnnotationUtil.findAnnotation(method, nullableManager.getNotNulls());
final String[] annotationsToRemove = ArrayUtil.toStringArray(nullableManager.getNullables());
final LocalQuickFix fix;
if (applicable) {
fix = new MyAnnotateMethodFix(defaultNotNull, annotationsToRemove);
}
else {
fix = superMethodApplicable ? null : createChangeDefaultNotNullFix(nullableManager, method);
}
holder.registerProblem(annotation, InspectionsBundle.message("nullable.stuff.problems.overridden.methods.are.not.annotated"),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
new MyAnnotateMethodFix(defaultNotNull, annotationsToRemove));
wrapFix(fix));
methodQuickFixSuggested = true;
}
if (hasAnnotatedParameter) {
@@ -363,7 +390,7 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
holder.registerProblem(annotation,
InspectionsBundle.message("nullable.stuff.problems.overridden.method.parameters.are.not.annotated"),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
new AnnotateOverriddenMethodParameterFix(nullableManager.getDefaultNotNull(), nullableManager.getDefaultNullable()));
wrapFix(!applicable ? createChangeDefaultNotNullFix(nullableManager, parameters[i]) : new AnnotateOverriddenMethodParameterFix(defaultNotNull, nullableManager.getDefaultNullable())));
parameterQuickFixSuggested[i] = true;
}
}
@@ -373,6 +400,19 @@ public class NullableStuffInspection extends BaseLocalInspectionTool {
}
}
private static LocalQuickFix[] wrapFix(LocalQuickFix fix) {
if (fix == null) return LocalQuickFix.EMPTY_ARRAY;
return new LocalQuickFix[]{fix};
}
private static LocalQuickFix createChangeDefaultNotNullFix(NullableNotNullManager nullableManager, PsiModifierListOwner modifierListOwner) {
final PsiAnnotation annotation = AnnotationUtil.findAnnotation(modifierListOwner, nullableManager.getNotNulls());
if (annotation != null) {
return new ChangeNullableDefaultsFix(annotation.getQualifiedName(), null, nullableManager);
}
return null;
}
protected AnnotateMethodFix createAnnotateMethodFix(final String defaultNotNull, final String[] annotationsToRemove) {
return new AnnotateMethodFix(defaultNotNull, annotationsToRemove);
}
@@ -210,7 +210,7 @@ public class PackageUtil {
}
if (psiDirectory == null) {
if (!checkSourceRootsConfigured(module)) return null;
if (!checkSourceRootsConfigured(module, askUserToCreate)) return null;
final VirtualFile[] sourceRoots = ModuleRootManager.getInstance(module).getSourceRoots();
List<PsiDirectory> directoryList = new ArrayList<PsiDirectory>();
for (VirtualFile sourceRoot : sourceRoots) {
@@ -355,15 +355,22 @@ public class PackageUtil {
}
public static boolean checkSourceRootsConfigured(final Module module) {
return checkSourceRootsConfigured(module, true);
}
public static boolean checkSourceRootsConfigured(final Module module, final boolean askUserToSetupSourceRoots) {
VirtualFile[] sourceRoots = ModuleRootManager.getInstance(module).getSourceRoots();
if (sourceRoots.length == 0) {
Messages.showErrorDialog(
module.getProject(),
ProjectBundle.message("module.source.roots.not.configured.error", module.getName()),
ProjectBundle.message("module.source.roots.not.configured.title")
);
if (!askUserToSetupSourceRoots) {
return false;
}
ProjectSettingsService.getInstance(module.getProject()).showModuleConfigurationDialog(module.getName(), CommonContentEntriesEditor.NAME);
Project project = module.getProject();
Messages.showErrorDialog(project,
ProjectBundle.message("module.source.roots.not.configured.error", module.getName()),
ProjectBundle.message("module.source.roots.not.configured.title"));
ProjectSettingsService.getInstance(project).showModuleConfigurationDialog(module.getName(), CommonContentEntriesEditor.NAME);
sourceRoots = ModuleRootManager.getInstance(module).getSourceRoots();
if (sourceRoots.length == 0) {
@@ -60,7 +60,7 @@ public class TreeJavaClassChooserDialog extends AbstractTreeClassChooserDialog<P
@Nullable ClassFilter classFilter,
PsiClass baseClass,
@Nullable PsiClass initialClass, boolean isShowMembers) {
super(title, project, scope, PsiClass.class, createFilter(classFilter), baseClass, initialClass, isShowMembers);
super(title, project, scope, PsiClass.class, createFilter(classFilter), baseClass, initialClass, isShowMembers, true);
}
@Override
@@ -60,7 +60,7 @@ public class BasePackageParameterFactory extends ProjectTemplateParameterFactory
@Override
public String getLabel() {
return "Base package:";
return "Base \u001Bpackage:";
}
@Override
@@ -195,11 +195,15 @@ public class JavaPsiImplementationHelperImpl extends JavaPsiImplementationHelper
if (anchor != null && anchor != aClass) {
anchor = anchor.getNextSibling();
while (anchor instanceof PsiJavaToken && (anchor.getText().equals(",") || anchor.getText().equals(";"))) {
final boolean afterComma = anchor.getText().equals(",");
anchor = anchor.getNextSibling();
if (afterComma) {
newAnchor = skipWhitespaces(aClass, anchor);
if (newAnchor != null) return newAnchor;
}
}
if (anchor != null) {
newAnchor = skipWhitespaces(aClass, anchor);
return newAnchor != null ? newAnchor : anchor;
return anchor;
}
}
@@ -78,63 +78,10 @@ public class ImportHelper{
}
});
int[] entryForName = ArrayUtil.newIntArray(names.size());
PackageEntry[] entries = mySettings.IMPORT_LAYOUT_TABLE.getEntries();
for(int i = 0; i < names.size(); i++){
Pair<String, Boolean> pair = names.get(i);
String packageName = pair.getFirst();
Boolean isStatic = pair.getSecond();
entryForName[i] = findEntryIndex(packageName, isStatic, entries);
}
List<Pair<String, Boolean>> resultList = new ArrayList<Pair<String, Boolean>>(names.size());
for(int i = 0; i < entries.length; i++){
for(int j = 0; j < names.size(); j++){
if (entryForName[j] == i){
resultList.add(names.get(j));
names.set(j, null);
}
}
}
for (Pair<String, Boolean> name : names) {
if (name != null) resultList.add(name);
}
TObjectIntHashMap<String> packageToCountMap = new TObjectIntHashMap<String>();
TObjectIntHashMap<String> classToCountMap = new TObjectIntHashMap<String>();
for (Pair<String, Boolean> pair : resultList) {
String name = pair.getFirst();
Boolean isStatic = pair.getSecond();
String packageOrClassName = getPackageOrClassName(name);
if (packageOrClassName.length() == 0) continue;
if (isStatic) {
int count = classToCountMap.get(packageOrClassName);
classToCountMap.put(packageOrClassName, count + 1);
}
else {
int count = packageToCountMap.get(packageOrClassName);
packageToCountMap.put(packageOrClassName, count + 1);
}
}
List<Pair<String, Boolean>> resultList = sortItemsAccordingToSettings(names, mySettings);
final Set<String> classesOrPackagesToImportOnDemand = new THashSet<String>();
class MyVisitorProcedure implements TObjectIntProcedure<String> {
private final boolean myIsVisitingPackages;
MyVisitorProcedure(boolean isVisitingPackages) {
myIsVisitingPackages = isVisitingPackages;
}
@Override
public boolean execute(final String packageOrClassName, final int count) {
if (isToUseImportOnDemand(packageOrClassName, count, !myIsVisitingPackages)){
classesOrPackagesToImportOnDemand.add(packageOrClassName);
}
return true;
}
}
classToCountMap.forEachEntry(new MyVisitorProcedure(false));
packageToCountMap.forEachEntry(new MyVisitorProcedure(true));
collectOnDemandImports(resultList, classesOrPackagesToImportOnDemand, ImportHelper.this.mySettings);
Set<String> classesToUseSingle = findSingleImports(file, resultList, classesOrPackagesToImportOnDemand);
Set<String> toReimport = new THashSet<String>();
@@ -176,6 +123,71 @@ public class ImportHelper{
}
}
public static void collectOnDemandImports(List<Pair<String, Boolean>> resultList,
final Set<String> classesOrPackagesToImportOnDemand,
final CodeStyleSettings settings) {
TObjectIntHashMap<String> packageToCountMap = new TObjectIntHashMap<String>();
TObjectIntHashMap<String> classToCountMap = new TObjectIntHashMap<String>();
for (Pair<String, Boolean> pair : resultList) {
String name = pair.getFirst();
Boolean isStatic = pair.getSecond();
String packageOrClassName = getPackageOrClassName(name);
if (packageOrClassName.length() == 0) continue;
if (isStatic) {
int count = classToCountMap.get(packageOrClassName);
classToCountMap.put(packageOrClassName, count + 1);
}
else {
int count = packageToCountMap.get(packageOrClassName);
packageToCountMap.put(packageOrClassName, count + 1);
}
}
class MyVisitorProcedure implements TObjectIntProcedure<String> {
private final boolean myIsVisitingPackages;
MyVisitorProcedure(boolean isVisitingPackages) {
myIsVisitingPackages = isVisitingPackages;
}
@Override
public boolean execute(final String packageOrClassName, final int count) {
if (isToUseImportOnDemand(packageOrClassName, count, !myIsVisitingPackages, settings)){
classesOrPackagesToImportOnDemand.add(packageOrClassName);
}
return true;
}
}
classToCountMap.forEachEntry(new MyVisitorProcedure(false));
packageToCountMap.forEachEntry(new MyVisitorProcedure(true));
}
public static List<Pair<String, Boolean>> sortItemsAccordingToSettings(List<Pair<String, Boolean>> names, final CodeStyleSettings settings) {
int[] entryForName = ArrayUtil.newIntArray(names.size());
PackageEntry[] entries = settings.IMPORT_LAYOUT_TABLE.getEntries();
for(int i = 0; i < names.size(); i++){
Pair<String, Boolean> pair = names.get(i);
String packageName = pair.getFirst();
Boolean isStatic = pair.getSecond();
entryForName[i] = findEntryIndex(packageName, isStatic, entries);
}
List<Pair<String, Boolean>> resultList = new ArrayList<Pair<String, Boolean>>(names.size());
for(int i = 0; i < entries.length; i++){
for(int j = 0; j < names.size(); j++){
if (entryForName[j] == i){
resultList.add(names.get(j));
names.set(j, null);
}
}
}
for (Pair<String, Boolean> name : names) {
if (name != null) resultList.add(name);
}
return resultList;
}
@NotNull
private static Set<String> findSingleImports(@NotNull final PsiJavaFile file,
@NotNull List<Pair<String,Boolean>> names,
@@ -620,13 +632,16 @@ public class ImportHelper{
return maxSpace;
}
private boolean isToUseImportOnDemand(@NotNull String packageName, int classCount, boolean isStaticImportNeeded){
if (!mySettings.USE_SINGLE_CLASS_IMPORTS) return true;
int limitCount = isStaticImportNeeded ? mySettings.NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND :
mySettings.CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND;
private static boolean isToUseImportOnDemand(@NotNull String packageName,
int classCount,
boolean isStaticImportNeeded,
final CodeStyleSettings settings){
if (!settings.USE_SINGLE_CLASS_IMPORTS) return true;
int limitCount = isStaticImportNeeded ? settings.NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND :
settings.CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND;
if (classCount >= limitCount) return true;
if (packageName.length() == 0) return false;
PackageEntryTable table = mySettings.PACKAGES_TO_USE_IMPORT_ON_DEMAND;
PackageEntryTable table = settings.PACKAGES_TO_USE_IMPORT_ON_DEMAND;
return table != null && table.contains(packageName);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 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,7 +29,7 @@ import com.intellij.openapi.util.Ref;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiJavaReference;
import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.impl.source.tree.SourceUtil;
import com.intellij.psi.impl.source.tree.AstBufferUtil;
import com.intellij.util.NullableFunction;
import com.intellij.util.PairProcessor;
import com.intellij.util.WalkingState;
@@ -60,8 +60,8 @@ public class SliceLeafAnalyzer {
elementToCompare = resolved;
}
}
return elementToCompare instanceof PsiNamedElement ?
((PsiNamedElement)elementToCompare).getName() : SourceUtil.getTextSkipWhiteSpaceAndComments(elementToCompare.getNode());
return elementToCompare instanceof PsiNamedElement ? ((PsiNamedElement)elementToCompare).getName()
: AstBufferUtil.getTextSkippingWhitespaceComments(elementToCompare.getNode());
}
});
return Comparing.hashcode(text);
@@ -293,9 +293,13 @@ public class AnnotationUtil {
}
public static boolean isAnnotatingApplicable(@NotNull PsiElement elt) {
return isAnnotatingApplicable(elt, NullableNotNullManager.getInstance(elt.getProject()).getDefaultNullable());
}
public static boolean isAnnotatingApplicable(@NotNull PsiElement elt, final String annotationFQN) {
final Project project = elt.getProject();
return PsiUtil.isLanguageLevel5OrHigher(elt) &&
JavaPsiFacade.getInstance(project).findClass(NullableNotNullManager.getInstance(project).getDefaultNullable(), elt.getResolveScope()) != null;
JavaPsiFacade.getInstance(project).findClass(annotationFQN, elt.getResolveScope()) != null;
}
public static boolean isJetbrainsAnnotation(@NonNls final String simpleName) {
@@ -29,9 +29,18 @@ import java.util.List;
public abstract class HierarchicalMethodSignature extends MethodSignatureBackedByPsiMethod {
public HierarchicalMethodSignature(@NotNull MethodSignatureBackedByPsiMethod signature) {
super(signature.getMethod(), signature.getSubstitutor(), signature.isRaw(),
signature.getParameterTypes(), signature.getTypeParameters());
getParameterTypes(signature.getMethod()), signature.getTypeParameters());
}
private static PsiType[] getParameterTypes(PsiMethod method) {
final PsiParameter[] parameters = method.getParameterList().getParameters();
final PsiType[] paramTypes = new PsiType[parameters.length];
for (int i = 0; i < paramTypes.length; i++) {
paramTypes[i] = parameters[i].getType();
}
return paramTypes;
}
/**
* Returns the list of super method signatures for the specified signature.
*
@@ -32,7 +32,12 @@ public class LambdaHighlightingUtil {
final List<MethodSignature> signatures = LambdaUtil.findFunctionCandidates(psiClass);
if (signatures == null) return "Target type of a lambda conversion must be an interface";
if (signatures.isEmpty()) return "No target method found";
return signatures.size() == 1 ? null : "Multiple non-overriding abstract methods found";
if (signatures.size() == 1) {
final MethodSignature functionalMethod = signatures.get(0);
if (functionalMethod.getTypeParameters().length > 0) return "Target method is generic";
return null;
}
return "Multiple non-overriding abstract methods found";
}
public static String checkReturnTypeCompatible(PsiLambdaExpression lambdaExpression, PsiType functionalInterfaceReturnType) {
@@ -636,22 +636,39 @@ public class LambdaUtil {
return result;
}
public static void checkMoreSpecificReturnType(List<CandidateInfo> conflicts, int functionalInterfaceIdx) {
public static void checkMoreSpecificReturnType(List<CandidateInfo> conflicts, PsiType[] actualParameterTypes) {
final CandidateInfo[] newConflictsArray = conflicts.toArray(new CandidateInfo[conflicts.size()]);
for (int i = 1; i < newConflictsArray.length; i++) {
final CandidateInfo method = newConflictsArray[i];
final PsiType interfaceReturnType = getReturnType(functionalInterfaceIdx, method);
for (int j = 0; j < i; j++) {
final CandidateInfo conflict = newConflictsArray[j];
assert conflict != method;
final PsiType interfaceReturnType1 = getReturnType(functionalInterfaceIdx, conflict);
if (interfaceReturnType != null && interfaceReturnType1 != null && !Comparing.equal(interfaceReturnType, interfaceReturnType1)) {
int moreSpecific = isMoreSpecific(interfaceReturnType, interfaceReturnType1);
if (moreSpecific > 0) {
int moreSpecific = 0;
final PsiMethod methodElement = (PsiMethod)method.getElement();
final PsiMethod conflictElement = (PsiMethod)conflict.getElement();
if (methodElement.isVarArgs() == conflictElement.isVarArgs()) {
for (int functionalInterfaceIdx = 0; functionalInterfaceIdx < actualParameterTypes.length; functionalInterfaceIdx++) {
final PsiType interfaceReturnType = getReturnType(functionalInterfaceIdx, method);
final PsiType interfaceReturnType1 = getReturnType(functionalInterfaceIdx, conflict);
if (actualParameterTypes[functionalInterfaceIdx] instanceof PsiLambdaExpressionType || actualParameterTypes[functionalInterfaceIdx] instanceof PsiMethodReferenceType) {
if (interfaceReturnType != null && interfaceReturnType1 != null && !Comparing.equal(interfaceReturnType, interfaceReturnType1)) {
int moreSpecific1 = isMoreSpecific(interfaceReturnType, interfaceReturnType1, actualParameterTypes[functionalInterfaceIdx]);
if (moreSpecific < 0 && moreSpecific1 > 0 || moreSpecific > 0 && moreSpecific1 < 0) {
moreSpecific = 0;
break;
}
moreSpecific = moreSpecific1;
}
} else if (interfaceReturnType != null && interfaceReturnType1 != null) {
moreSpecific = 0;
break;
}
}
if (moreSpecific > 0 && conflictElement.getParameterList().getParametersCount() <= actualParameterTypes.length) {
conflicts.remove(method);
break;
}
else if (moreSpecific < 0) {
else if (moreSpecific < 0 && methodElement.getParameterList().getParametersCount() <= actualParameterTypes.length) {
conflicts.remove(conflict);
}
}
@@ -659,22 +676,38 @@ public class LambdaUtil {
}
}
private static int isMoreSpecific(PsiType returnType, PsiType returnType1) {
enum TypeKind {
PRIMITIVE, REFERENCE, NONE_DETERMINED
}
private static int isMoreSpecific(PsiType returnType, PsiType returnType1, PsiType lambdaType) {
if (returnType == PsiType.VOID || returnType1 == PsiType.VOID) return 0;
if (returnType instanceof PsiPrimitiveType) {
if (!(returnType1 instanceof PsiPrimitiveType)) {
return -1;
} else {
return TypeConversionUtil.areTypesConvertible(returnType, returnType1) ? 1 : -1;
TypeKind typeKind = TypeKind.PRIMITIVE;
if (lambdaType instanceof PsiLambdaExpressionType) {
typeKind = areLambdaReturnExpressionsPrimitive((PsiLambdaExpressionType)lambdaType);
} else if (lambdaType instanceof PsiMethodReferenceType) {
final PsiElement referencedElement = ((PsiMethodReferenceType)lambdaType).getExpression().resolve();
if (referencedElement instanceof PsiMethod && !(((PsiMethod)referencedElement).getReturnType() instanceof PsiPrimitiveType)) {
typeKind = TypeKind.REFERENCE;
}
}
if (returnType1 instanceof PsiPrimitiveType) {
return 1;
if (typeKind != TypeKind.NONE_DETERMINED) {
if (returnType instanceof PsiPrimitiveType) {
final int moreSpecific = typeKind == TypeKind.PRIMITIVE ? 1 : -1;
if (!(returnType1 instanceof PsiPrimitiveType)) {
return -moreSpecific;
} else {
return TypeConversionUtil.isAssignable(returnType, returnType1) ? moreSpecific : -moreSpecific;
}
}
if (returnType1 instanceof PsiPrimitiveType) {
return typeKind == TypeKind.PRIMITIVE ? 1 : -1;
}
}
final PsiClassType.ClassResolveResult r = PsiUtil.resolveGenericsClassInType(returnType);
final PsiClassType.ClassResolveResult r = PsiUtil.resolveGenericsClassInType(GenericsUtil.eliminateWildcards(returnType));
final PsiClass rClass = r.getElement();
final PsiClassType.ClassResolveResult r1 = PsiUtil.resolveGenericsClassInType(returnType1);
final PsiClassType.ClassResolveResult r1 = PsiUtil.resolveGenericsClassInType(GenericsUtil.eliminateWildcards(returnType1));
final PsiClass rClass1 = r1.getElement();
if (rClass != null && rClass1 != null) {
if (rClass == rClass1) {
@@ -711,6 +744,28 @@ public class LambdaUtil {
return 0;
}
private static TypeKind areLambdaReturnExpressionsPrimitive(PsiLambdaExpressionType lambdaType) {
final List<PsiExpression> returnExpressions = getReturnExpressions(lambdaType.getExpression());
TypeKind typeKind = TypeKind.NONE_DETERMINED;
for (PsiExpression expression : returnExpressions) {
final PsiType returnExprType = expression.getType();
if (returnExprType instanceof PsiPrimitiveType) {
if (typeKind == TypeKind.REFERENCE) {
typeKind = TypeKind.NONE_DETERMINED;
break;
}
typeKind = TypeKind.PRIMITIVE;
} else {
if (typeKind == TypeKind.PRIMITIVE) {
typeKind = TypeKind.NONE_DETERMINED;
break;
}
typeKind = TypeKind.REFERENCE;
}
}
return typeKind;
}
@Nullable
private static PsiType getReturnType(int functionalTypeIdx, CandidateInfo method) {
final PsiParameter[] methodParameters = ((PsiMethod)method.getElement()).getParameterList().getParameters();
@@ -750,7 +805,7 @@ public class LambdaUtil {
public TypeParamsChecker(PsiElement expression, PsiClass aClass) {
myClass = aClass;
PsiElement parent = expression.getParent();
PsiElement parent = expression != null ? expression.getParent() : null;
while (parent instanceof PsiParenthesizedExpression) {
parent = parent.getParent();
}
@@ -16,11 +16,10 @@
package com.intellij.psi;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.MethodSignature;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.openapi.project.Project;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.util.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
@@ -77,12 +76,7 @@ public class PsiMethodReferenceUtil {
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
final PsiExpression expression = methodReferenceExpression.getQualifierExpression();
if (expression != null) {
final PsiType expressionType = expression.getType();
if (expressionType instanceof PsiArrayType) {
containingClass = JavaPsiFacade.getInstance(methodReferenceExpression.getProject())
.findClass(CommonClassNames.JAVA_LANG_OBJECT, methodReferenceExpression.getResolveScope());
return new QualifierResolveResult(containingClass, substitutor, false);
}
final PsiType expressionType = getExpandedType(expression.getType(), expression);
PsiClassType.ClassResolveResult result = PsiUtil.resolveGenericsClassInType(expressionType);
containingClass = result.getElement();
if (containingClass != null) {
@@ -101,7 +95,8 @@ public class PsiMethodReferenceUtil {
else {
final PsiTypeElement typeElement = methodReferenceExpression.getQualifierType();
if (typeElement != null) {
PsiClassType.ClassResolveResult result = PsiUtil.resolveGenericsClassInType(typeElement.getType());
PsiType type = getExpandedType(typeElement.getType(), typeElement);
PsiClassType.ClassResolveResult result = PsiUtil.resolveGenericsClassInType(type);
containingClass = result.getElement();
if (containingClass != null) {
substitutor = result.getSubstitutor();
@@ -149,7 +144,14 @@ public class PsiMethodReferenceUtil {
final MethodSignature signature2 = ((PsiMethod)resolve).getSignature(subst);
final PsiType interfaceReturnType = LambdaUtil.getFunctionalInterfaceReturnType(left);
PsiType methodReturnType = subst.substitute(((PsiMethod)resolve).getReturnType());
PsiType returnType = PsiTypesUtil.patchMethodGetClassReturnType(methodReferenceExpression, methodReferenceExpression,
(PsiMethod)resolve, null,
PsiUtil.getLanguageLevel(methodReferenceExpression));
if (returnType == null) {
returnType = ((PsiMethod)resolve).getReturnType();
}
PsiType methodReturnType = subst.substitute(returnType);
if (interfaceReturnType != null && interfaceReturnType != PsiType.VOID) {
if (methodReturnType == null) {
methodReturnType = JavaPsiFacade.getElementFactory(methodReferenceExpression.getProject()).createType(((PsiMethod)resolve).getContainingClass(), subst);
@@ -161,9 +163,18 @@ public class PsiMethodReferenceUtil {
final PsiType interfaceReturnType = LambdaUtil.getFunctionalInterfaceReturnType(left);
if (interfaceReturnType != null) {
if (interfaceReturnType == PsiType.VOID) return true;
final PsiParameter[] parameters = method.getParameterList().getParameters();
if (resolve == JavaPsiFacade.getElementFactory(resolve.getProject()).getArrayClass(PsiUtil.getLanguageLevel(resolve))) {
if (parameters.length != 1 || parameters[0].getType() != PsiType.INT) return false;
final PsiTypeParameter[] typeParameters = ((PsiClass)resolve).getTypeParameters();
if (typeParameters.length == 1) {
final PsiType arrayComponentType = result.getSubstitutor().substitute(typeParameters[0]);
return arrayComponentType != null && TypeConversionUtil.isAssignable(interfaceReturnType, arrayComponentType.createArrayType(), true);
}
return false;
}
final PsiClassType classType = JavaPsiFacade.getElementFactory(methodReferenceExpression.getProject()).createType((PsiClass)resolve, result.getSubstitutor());
if (TypeConversionUtil.isAssignable(interfaceReturnType, classType, !((PsiClass)resolve).hasTypeParameters())) {
final PsiParameter[] parameters = method.getParameterList().getParameters();
if (parameters.length == 0) return true;
if (parameters.length == 1) {
if (isReceiverType(resolveResult.getSubstitutor().substitute(parameters[0].getType()), qualifierResolveResult.getContainingClass(), qualifierResolveResult.getSubstitutor())) return true;
@@ -176,14 +187,13 @@ public class PsiMethodReferenceUtil {
}
private static boolean isReceiverType(@Nullable PsiClass aClass, @Nullable PsiClass containingClass) {
while (containingClass != null) {
if (InheritanceUtil.isInheritorOrSelf(aClass, containingClass, true)) return true;
containingClass = containingClass.getContainingClass();
}
return false;
return InheritanceUtil.isInheritorOrSelf(aClass, containingClass, true);
}
public static boolean isReceiverType(PsiType receiverType, @Nullable PsiClass containingClass, PsiSubstitutor psiSubstitutor) {
if (containingClass != null) {
receiverType = getExpandedType(receiverType, containingClass);
}
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(GenericsUtil.eliminateWildcards(receiverType));
final PsiClass receiverClass = resolveResult.getElement();
if (receiverClass != null && isReceiverType(receiverClass, containingClass)) {
@@ -264,14 +274,23 @@ public class PsiMethodReferenceUtil {
return true;
}
public static PsiLocalVariable createMethodReferenceExpressionAccording2Type(PsiMethodReferenceExpression methodReferenceExpression,
PsiType leftType) {
final String uniqueVarName =
JavaCodeStyleManager.getInstance(methodReferenceExpression.getProject())
.suggestUniqueVariableName("l", methodReferenceExpression, true);
final PsiStatement assignmentFromText = JavaPsiFacade.getElementFactory(methodReferenceExpression.getProject())
.createStatementFromText(leftType.getCanonicalText() + " " + uniqueVarName + " = " + methodReferenceExpression.getText(),
methodReferenceExpression);
return (PsiLocalVariable)((PsiDeclarationStatement)assignmentFromText).getDeclaredElements()[0];
public static boolean onArrayType(PsiClass containingClass, MethodSignature signature) {
if (signature.getParameterTypes().length == 1 && signature.getParameterTypes()[0] == PsiType.INT) {
if (containingClass != null) {
final Project project = containingClass.getProject();
final LanguageLevel level = PsiUtil.getLanguageLevel(containingClass);
return containingClass == JavaPsiFacade.getElementFactory(project).getArrayClass(level);
}
}
return false;
}
private static PsiType getExpandedType(PsiType type, @NotNull PsiElement typeElement) {
if (type instanceof PsiArrayType) {
type = JavaPsiFacade.getElementFactory(typeElement.getProject()).getArrayClassType(((PsiArrayType)type).getComponentType(),
PsiUtil.getLanguageLevel(typeElement));
}
return type;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -67,17 +67,12 @@ public abstract class PsiNameHelper {
@NotNull
public static String getShortClassName(@NotNull String referenceText) {
return getShortClassName(referenceText, true);
}
int lessPos = referenceText.length(), bracesBalance = 0, i;
private static String getShortClassName(String referenceText, boolean removeWhitespace) {
int lessPos = referenceText.length();
int bracesBalance = 0;
int i;
loop:
for (i = referenceText.length() - 1; i >= 0; i--) {
final char aChar = referenceText.charAt(i);
switch (aChar) {
char ch = referenceText.charAt(i);
switch (ch) {
case ')':
case '>':
bracesBalance++;
@@ -91,22 +86,25 @@ public abstract class PsiNameHelper {
case '@':
case '.':
if (bracesBalance == 0) break loop;
if (bracesBalance <= 0) break loop;
break;
default:
if (bracesBalance == 0 && removeWhitespace && !Character.isWhitespace(aChar) && !Character.isJavaIdentifierPart(aChar)) {
return getShortClassName(removeWhitespace(referenceText), false);
if (Character.isWhitespace(ch) && bracesBalance <= 0) {
for (int j = i + 1; j < lessPos; j++) {
if (!Character.isWhitespace(referenceText.charAt(j))) break loop;
}
lessPos = i;
}
}
}
String sub = referenceText.substring(i + 1, lessPos).trim();
return sub.length() == referenceText.length() ? sub : new String(sub);
}
public static String getPresentableText(PsiJavaCodeReferenceElement ref) {
final String referenceName = ref.getReferenceName();
PsiType[] typeParameters = ref.getTypeParameters();
return getPresentableText(referenceName, typeParameters);
}
@@ -167,7 +165,7 @@ public abstract class PsiNameHelper {
* <code>["List&lt;String&gt","Integer"]</code>
*
* @param referenceText the text of the reference to calculate type parameters for.
* @return the calculated array of type parameters.
* @return the calculated array of type parameters.
*/
public static String[] getClassParametersText(String referenceText) {
if (referenceText.indexOf('<') < 0) return ArrayUtil.EMPTY_STRING_ARRAY;
@@ -15,7 +15,13 @@
*/
package com.intellij.psi.util;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.containers.HashMap;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -47,6 +53,8 @@ public class PsiTypesUtil {
ourBoxedTypes.put("char", CommonClassNames.JAVA_LANG_CHARACTER);
}
@NonNls private static final String GET_CLASS_METHOD = "getClass";
private PsiTypesUtil() { }
public static String getDefaultValueOfType(PsiType type) {
@@ -135,4 +143,45 @@ public class PsiTypesUtil {
}
return null;
}
public static PsiType patchMethodGetClassReturnType(@NotNull PsiExpression call,
@NotNull PsiReferenceExpression methodExpression,
@NotNull PsiMethod method,
@Nullable Condition<IElementType> condition,
@NotNull LanguageLevel languageLevel) {
//JLS3 15.8.2
if (languageLevel.isAtLeast(LanguageLevel.JDK_1_5) &&
GET_CLASS_METHOD.equals(method.getName()) &&
CommonClassNames.JAVA_LANG_OBJECT.equals(method.getContainingClass().getQualifiedName())) {
PsiExpression qualifier = methodExpression.getQualifierExpression();
PsiType qualifierType = null;
final Project project = call.getProject();
if (qualifier != null) {
qualifierType = TypeConversionUtil.erasure(qualifier.getType());
}
else if (condition != null) {
ASTNode parent = call.getNode().getTreeParent();
while (parent != null && condition.value(parent.getElementType())) {
parent = parent.getTreeParent();
}
if (parent != null) {
qualifierType = JavaPsiFacade.getInstance(project).getElementFactory().createType((PsiClass)parent.getPsi());
}
}
if (qualifierType != null) {
PsiClass javaLangClass = JavaPsiFacade.getInstance(project).findClass(CommonClassNames.JAVA_LANG_CLASS, call.getResolveScope());
if (javaLangClass != null && javaLangClass.getTypeParameters().length == 1) {
Map<PsiTypeParameter, PsiType> map = new HashMap<PsiTypeParameter, PsiType>();
map.put(javaLangClass.getTypeParameters()[0], PsiWildcardType.createExtends(call.getManager(), qualifierType));
PsiSubstitutor substitutor = JavaPsiFacade.getInstance(project).getElementFactory().createSubstitutor(map);
final PsiClassType classType = JavaPsiFacade.getInstance(project).getElementFactory()
.createType(javaLangClass, substitutor, languageLevel);
final PsiElement parent = call.getParent();
return parent instanceof PsiReferenceExpression && parent.getParent() instanceof PsiMethodCallExpression
? PsiUtil.captureToplevelWildcards(classType, methodExpression) : classType;
}
}
}
return null;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -32,6 +32,7 @@ import com.intellij.psi.meta.PsiMetaData;
import com.intellij.psi.meta.PsiMetaOwner;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.EmptyIterable;
@@ -473,7 +474,7 @@ public final class PsiUtil extends PsiUtilCore {
PsiType argType = args[args.length - 1];
if (argType == null) return ApplicabilityLevel.NOT_APPLICABLE;
if (TypeConversionUtil.isAssignable(parmType, argType)) return ApplicabilityLevel.FIXED_ARITY;
if (isRaw) {
final PsiType erasedParamType = TypeConversionUtil.erasure(parmType);
final PsiType erasedArgType = TypeConversionUtil.erasure(argType);
@@ -550,7 +551,7 @@ public final class PsiUtil extends PsiUtilCore {
if (typeParameters1.length != typeParameters2.length) return false;
for (int i = 0; i < typeParameters1.length; i++) {
final PsiType substituted2 = s2.substitute(typeParameters2[i]);
if (!Comparing.equal(s1.substituteWithBoundsPromotion(typeParameters1[i]), substituted2) &&
if (!Comparing.equal(s1.substituteWithBoundsPromotion(typeParameters1[i]), substituted2) &&
!Comparing.equal(s1.substitute(typeParameters1[i]), substituted2)) return false;
}
if (aClass.hasModifierProperty(PsiModifier.STATIC)) return true;
@@ -858,7 +859,7 @@ public final class PsiUtil extends PsiUtilCore {
public static boolean hasDefaultConstructor(@NotNull PsiClass clazz) {
return hasDefaultConstructor(clazz, false);
}
public static boolean hasDefaultConstructor(@NotNull PsiClass clazz, boolean allowProtected) {
return hasDefaultConstructor(clazz, allowProtected, true);
}
@@ -949,10 +950,14 @@ public final class PsiUtil extends PsiUtilCore {
return parent instanceof PsiIfStatement && element == ((PsiIfStatement)parent).getElseBranch();
}
public static boolean isJavaToken(@Nullable final PsiElement element, final IElementType type) {
public static boolean isJavaToken(@Nullable PsiElement element, IElementType type) {
return element instanceof PsiJavaToken && ((PsiJavaToken)element).getTokenType() == type;
}
public static boolean isJavaToken(@Nullable PsiElement element, @NotNull TokenSet types) {
return element instanceof PsiJavaToken && types.contains(((PsiJavaToken)element).getTokenType());
}
public static boolean isCatchParameter(@Nullable final PsiElement element) {
return element instanceof PsiParameter && element.getParent() instanceof PsiCatchSection;
}
@@ -686,6 +686,9 @@ public class TypeConversionUtil {
final PsiType lType = lLambdaExpression.getFunctionalInterfaceType();
return Comparing.equal(rType, lType);
}
if (left instanceof PsiArrayType) {
return false;
}
return LambdaUtil.isAcceptable(rLambdaExpression, left, false);
}
@@ -815,21 +818,6 @@ public class TypeConversionUtil {
}
public static boolean boxingConversionApplicable(final PsiType left, final PsiType right) {
if (right instanceof PsiMethodReferenceType) {
final JavaResolveResult result = ((PsiMethodReferenceType)right).getExpression().advancedResolve(false);
PsiElement element = result.getElement();
final PsiClassType.ClassResolveResult functionalInterfaceResult = PsiUtil.resolveGenericsClassInType(left);
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceResult);
if (element instanceof PsiMethod && interfaceMethod != null) {
final PsiType[] parameterTypes = ((PsiMethod)element).getSignature(result.getSubstitutor()).getParameterTypes();
final PsiType[] argTypes = interfaceMethod.getSignature(functionalInterfaceResult.getSubstitutor()).getParameterTypes();
if (parameterTypes.length != argTypes.length) return false;
for (int i = 0; i < parameterTypes.length; i++) {
if (boxingConversionApplicable(parameterTypes[i], argTypes[i])) return true;
}
}
}
if (left instanceof PsiPrimitiveType && !PsiType.NULL.equals(left)) {
return right instanceof PsiClassType && isAssignable(left, right);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -402,29 +402,26 @@ public class DeclarationParser {
return Pair.create(modList, isEmpty);
}
private PsiBuilder.Marker parseMethodFromLeftParenth(final PsiBuilder builder, final PsiBuilder.Marker declaration,
final boolean anno, final boolean constructor) {
private PsiBuilder.Marker parseMethodFromLeftParenth(PsiBuilder builder, PsiBuilder.Marker declaration, boolean anno, boolean constructor) {
parseParameterList(builder);
eatBrackets(builder, constructor, "expected.semicolon");
myParser.getReferenceParser().parseReferenceList(builder, JavaTokenType.THROWS_KEYWORD, JavaElementType.THROWS_LIST, JavaTokenType.COMMA);
final boolean hasDefault = expect(builder, JavaTokenType.DEFAULT_KEYWORD);
if (hasDefault && anno) {
if (anno && expect(builder, JavaTokenType.DEFAULT_KEYWORD)) {
parseAnnotationValue(builder);
}
final IElementType tokenType = builder.getTokenType();
final boolean hasError = tokenType != JavaTokenType.SEMICOLON && tokenType != JavaTokenType.LBRACE;
if (hasError) {
final PsiBuilder.Marker error = builder.mark();
IElementType tokenType = builder.getTokenType();
if (tokenType != JavaTokenType.SEMICOLON && tokenType != JavaTokenType.LBRACE) {
PsiBuilder.Marker error = builder.mark();
// heuristic: going to next line obviously means method signature is over, starting new method (actually, another one completion hack)
final CharSequence text = builder.getOriginalText();
CharSequence text = builder.getOriginalText();
Loop:
while (true) {
for (int i = builder.getCurrentOffset() - 1; i >= 0; i--) {
final char ch = text.charAt(i);
char ch = text.charAt(i);
if (ch == '\n') break Loop;
else if (ch != ' ' && ch != '\t') break;
}
@@ -433,11 +430,10 @@ public class DeclarationParser {
error.error(JavaErrorMessages.message("expected.lbrace.or.semicolon"));
}
if (hasDefault && !anno && !hasError && builder.getTokenType() != JavaTokenType.LBRACE) {
error(builder, JavaErrorMessages.message("expected.lbrace"));
}
if (!expect(builder, JavaTokenType.SEMICOLON) && builder.getTokenType() == JavaTokenType.LBRACE) {
myParser.getStatementParser().parseCodeBlock(builder);
if (!expect(builder, JavaTokenType.SEMICOLON)) {
if (builder.getTokenType() == JavaTokenType.LBRACE) {
myParser.getStatementParser().parseCodeBlock(builder);
}
}
done(declaration, anno ? JavaElementType.ANNOTATION_METHOD : JavaElementType.METHOD);
@@ -15,6 +15,7 @@
*/
package com.intellij.psi.impl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
@@ -25,6 +26,7 @@ import java.util.Map;
* @author dsl
*/
public final class EmptySubstitutorImpl extends EmptySubstitutor {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.EmptySubstitutorImpl");
@Override
public PsiType substitute(@NotNull PsiTypeParameter typeParameter){
return JavaPsiFacade.getInstance(typeParameter.getProject()).getElementFactory().createType(typeParameter);
@@ -42,6 +44,9 @@ public final class EmptySubstitutorImpl extends EmptySubstitutor {
@Override
public PsiSubstitutor put(PsiTypeParameter classParameter, PsiType mapping){
if (mapping != null && !mapping.isValid()) {
LOG.error("Invalid type in substitutor: " + mapping);
}
return new PsiSubstitutorImpl(classParameter, mapping);
}
@@ -414,6 +414,9 @@ public class PsiSubstitutorImpl implements PsiSubstitutor {
@Override
public PsiSubstitutor put(@NotNull PsiTypeParameter typeParameter, PsiType mapping) {
PsiSubstitutorImpl ret = clone();
if (mapping != null && !mapping.isValid()) {
LOG.error("Invalid type in substitutor: " + mapping);
}
ret.mySubstitutionMap.put(typeParameter, mapping);
return ret;
}
@@ -425,7 +428,11 @@ public class PsiSubstitutorImpl implements PsiSubstitutor {
PsiTypeParameter param = params[i];
assert param != null;
if (mappings != null && mappings.length > i) {
mySubstitutionMap.put(param, mappings[i]);
PsiType mapping = mappings[i];
mySubstitutionMap.put(param, mapping);
if (mapping != null && !mapping.isValid()) {
LOG.error("Invalid type in substitutor: " + mapping);
}
}
else {
mySubstitutionMap.put(param, null);
@@ -18,9 +18,10 @@ package com.intellij.psi.impl.cache;
import com.intellij.lang.LighterAST;
import com.intellij.lang.LighterASTNode;
import com.intellij.lang.LighterASTTokenNode;
import com.intellij.psi.*;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.PsiModifierList;
import com.intellij.psi.impl.java.stubs.*;
import com.intellij.psi.impl.java.stubs.impl.PsiMethodStubImpl;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.impl.source.tree.LightTreeUtil;
import com.intellij.psi.stubs.PsiFileStub;
@@ -59,8 +60,8 @@ public class RecordUtil {
public static boolean isDeprecatedByDocComment(@NotNull LighterAST tree, @NotNull LighterASTNode comment) {
// todo[r.sh] parse doc comments, implement tree lookup
final String text = LightTreeUtil.toFilteredString(tree, comment, null);
return text != null && text.contains(DEPRECATED_TAG);
String text = LightTreeUtil.toFilteredString(tree, comment, null);
return text.contains(DEPRECATED_TAG);
}
public static int packModifierList(@NotNull LighterAST tree, @NotNull LighterASTNode modList, @NotNull StubElement parent) {
@@ -110,12 +111,7 @@ public class RecordUtil {
else if (parent instanceof PsiMethodStub) {
if (grandParent instanceof PsiClassStub && ((PsiClassStub)grandParent).isInterface()) {
packed |= ModifierFlags.PUBLIC_MASK;
if (parent instanceof PsiMethodStubImpl && ((PsiMethodStubImpl)parent).hasExtensionMethodMark()) {
packed |= ModifierFlags.DEFENDER_MASK;
}
else {
packed |= ModifierFlags.ABSTRACT_MASK;
}
packed |= ModifierFlags.ABSTRACT_MASK;
}
}
else if (parent instanceof PsiFieldStub) {
@@ -91,20 +91,42 @@ public class TypeInfo {
public final boolean isEllipsis;
private final List<PsiAnnotationStub> myAnnotationStubs;
public TypeInfo(StringRef text, byte arrayCount, boolean ellipsis, @NotNull List<PsiAnnotationStub> annotationStubs) {
this.text = text;
this.arrayCount = arrayCount;
public TypeInfo(StringRef _text, byte _arrayCount, boolean ellipsis, @NotNull List<PsiAnnotationStub> annotationStubs) {
text = _text;
arrayCount = _arrayCount;
isEllipsis = ellipsis;
myAnnotationStubs = annotationStubs;
}
public TypeInfo(@NotNull TypeInfo typeInfo) {
this.text = typeInfo.text;
this.arrayCount = typeInfo.arrayCount;
text = typeInfo.text;
arrayCount = typeInfo.arrayCount;
isEllipsis = typeInfo.isEllipsis;
myAnnotationStubs = new SmartList<PsiAnnotationStub>(typeInfo.myAnnotationStubs);
}
public void addAnnotation(PsiAnnotationStub annotation) {
myAnnotationStubs.add(annotation);
}
@NotNull
public String getShortTypeText() {
if (text == null) return "";
String name = PsiNameHelper.getShortClassName(text.getString());
if (arrayCount > 0) {
name += StringUtil.repeat("[]", arrayCount);
}
return name;
}
@Override
public String toString() {
String text = createTypeText(this);
return text != null ? text : "null";
}
/* factories and serialization */
@NotNull
public static TypeInfo createConstructorType() {
return NULL;
@@ -162,7 +184,7 @@ public class TypeInfo {
}
@NotNull
public static TypeInfo fromString(String typeText, boolean isEllipsis) {
public static TypeInfo fromString(@NotNull String typeText, boolean isEllipsis) {
assert !typeText.endsWith("...") : typeText;
byte arrayCount = 0;
@@ -277,15 +299,4 @@ public class TypeInfo {
return buf.toString();
}
public void addAnnotation(PsiAnnotationStub annotation) {
myAnnotationStubs.add(annotation);
}
@NotNull
public String getShortTypeText() {
if (text == null) return "";
String name = PsiNameHelper.getShortClassName(text.getString());
return arrayCount > 0 ? name + StringUtil.repeat("[]", arrayCount) : name;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 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,6 +18,7 @@ package com.intellij.psi.impl.java.stubs;
import com.intellij.lang.ASTNode;
import com.intellij.lang.LighterAST;
import com.intellij.lang.LighterASTNode;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiNameHelper;
import com.intellij.psi.PsiReferenceList;
import com.intellij.psi.impl.java.stubs.impl.PsiClassReferenceListStubImpl;
@@ -48,54 +49,29 @@ public abstract class JavaClassReferenceListElementType extends JavaStubElementT
}
@Override
public PsiReferenceList createPsi(@NotNull final PsiClassReferenceListStub stub) {
public PsiReferenceList createPsi(@NotNull PsiClassReferenceListStub stub) {
return getPsiFactory(stub).createClassReferenceList(stub);
}
@Override
public PsiReferenceList createPsi(@NotNull final ASTNode node) {
public PsiReferenceList createPsi(@NotNull ASTNode node) {
if (node.getElementType() == JavaStubElementTypes.EXTENDS_BOUND_LIST) {
return new PsiTypeParameterExtendsBoundsListImpl(node);
}
return new PsiReferenceListImpl(node);
else {
return new PsiReferenceListImpl(node);
}
}
@Override
public PsiClassReferenceListStub createStub(final LighterAST tree,
final LighterASTNode node,
final StubElement parentStub) {
final JavaClassReferenceListElementType type = (JavaClassReferenceListElementType)node.getTokenType();
public PsiClassReferenceListStub createStub(LighterAST tree, LighterASTNode node, StubElement parentStub) {
JavaClassReferenceListElementType type = (JavaClassReferenceListElementType)node.getTokenType();
return new PsiClassReferenceListStubImpl(type, parentStub, getTexts(tree, node), elementTypeToRole(type));
}
private static JavaClassReferenceListElementType roleToElementType(final PsiReferenceList.Role role) {
switch (role) {
case EXTENDS_BOUNDS_LIST:
return JavaStubElementTypes.EXTENDS_BOUND_LIST;
case EXTENDS_LIST:
return JavaStubElementTypes.EXTENDS_LIST;
case IMPLEMENTS_LIST:
return JavaStubElementTypes.IMPLEMENTS_LIST;
case THROWS_LIST:
return JavaStubElementTypes.THROWS_LIST;
}
throw new RuntimeException("Unknown role: " + role);
}
private static PsiReferenceList.Role elementTypeToRole(final IElementType type) {
if (type == JavaStubElementTypes.EXTENDS_BOUND_LIST) return PsiReferenceList.Role.EXTENDS_BOUNDS_LIST;
else if (type == JavaStubElementTypes.EXTENDS_LIST) return PsiReferenceList.Role.EXTENDS_LIST;
else if (type == JavaStubElementTypes.IMPLEMENTS_LIST) return PsiReferenceList.Role.IMPLEMENTS_LIST;
else if (type == JavaStubElementTypes.THROWS_LIST) return PsiReferenceList.Role.THROWS_LIST;
throw new RuntimeException("Unknown element type: " + type);
}
private static String[] getTexts(final LighterAST tree, final LighterASTNode node) {
final List<LighterASTNode> refs = LightTreeUtil.getChildrenOfType(tree, node, JavaElementType.JAVA_CODE_REFERENCE);
final String[] texts = ArrayUtil.newStringArray(refs.size());
private static String[] getTexts(LighterAST tree, LighterASTNode node) {
List<LighterASTNode> refs = LightTreeUtil.getChildrenOfType(tree, node, JavaElementType.JAVA_CODE_REFERENCE);
String[] texts = ArrayUtil.newStringArray(refs.size());
for (int i = 0; i < refs.size(); i++) {
texts[i] = LightTreeUtil.toFilteredString(tree, refs.get(i), null);
}
@@ -103,9 +79,11 @@ public abstract class JavaClassReferenceListElementType extends JavaStubElementT
}
@Override
public void serialize(final PsiClassReferenceListStub stub, final StubOutputStream dataStream) throws IOException {
dataStream.writeByte(encodeRole(stub.getRole()));
final String[] names = stub.getReferencedNames();
public void serialize(PsiClassReferenceListStub stub, StubOutputStream dataStream) throws IOException {
byte role = encodeRole(stub.getRole());
dataStream.writeByte(role);
String[] names = stub.getReferencedNames();
dataStream.writeVarInt(names.length);
for (String name : names) {
dataStream.writeName(name);
@@ -113,49 +91,29 @@ public abstract class JavaClassReferenceListElementType extends JavaStubElementT
}
@Override
public PsiClassReferenceListStub deserialize(final StubInputStream dataStream, final StubElement parentStub) throws IOException {
public PsiClassReferenceListStub deserialize(StubInputStream dataStream, StubElement parentStub) throws IOException {
byte role = dataStream.readByte();
int len = dataStream.readVarInt();
StringRef[] names = StringRef.createArray(len);
for (int i = 0; i < names.length; i++) {
names[i] = dataStream.readName();
}
final PsiReferenceList.Role decodedRole = decodeRole(role);
PsiReferenceList.Role decodedRole = decodeRole(role);
return new PsiClassReferenceListStubImpl(roleToElementType(decodedRole), parentStub, names, decodedRole);
}
private static PsiReferenceList.Role decodeRole(int code) {
switch (code) {
case 0: return PsiReferenceList.Role.EXTENDS_LIST;
case 1: return PsiReferenceList.Role.IMPLEMENTS_LIST;
case 2: return PsiReferenceList.Role.THROWS_LIST;
case 3: return PsiReferenceList.Role.EXTENDS_BOUNDS_LIST;
default:
throw new RuntimeException("Unknown role code: " + code);
}
}
private static byte encodeRole(PsiReferenceList.Role role) {
switch (role) {
case EXTENDS_LIST: return 0;
case IMPLEMENTS_LIST: return 1;
case THROWS_LIST: return 2;
case EXTENDS_BOUNDS_LIST: return 3;
default:
throw new RuntimeException("Unknown role code: " + role);
}
}
@Override
public void indexStub(final PsiClassReferenceListStub stub, final IndexSink sink) {
final PsiReferenceList.Role role = stub.getRole();
public void indexStub(PsiClassReferenceListStub stub, IndexSink sink) {
PsiReferenceList.Role role = stub.getRole();
if (role == PsiReferenceList.Role.EXTENDS_LIST || role == PsiReferenceList.Role.IMPLEMENTS_LIST) {
final String[] names = stub.getReferencedNames();
String[] names = stub.getReferencedNames();
for (String name : names) {
sink.occurrence(JavaStubIndexKeys.SUPER_CLASSES, PsiNameHelper.getShortClassName(name));
String shortName = PsiNameHelper.getShortClassName(name);
if (!StringUtil.isEmptyOrSpaces(shortName)) {
sink.occurrence(JavaStubIndexKeys.SUPER_CLASSES, shortName);
}
}
if (role == PsiReferenceList.Role.EXTENDS_LIST) {
@@ -165,7 +123,6 @@ public abstract class JavaClassReferenceListElementType extends JavaStubElementT
if (psiClassStub.isEnum()) {
sink.occurrence(JavaStubIndexKeys.SUPER_CLASSES, "Enum");
}
if (psiClassStub.isAnnotationType()) {
sink.occurrence(JavaStubIndexKeys.SUPER_CLASSES, "Annotation");
}
@@ -173,4 +130,42 @@ public abstract class JavaClassReferenceListElementType extends JavaStubElementT
}
}
}
private static PsiReferenceList.Role elementTypeToRole(IElementType type) {
if (type == JavaStubElementTypes.EXTENDS_BOUND_LIST) return PsiReferenceList.Role.EXTENDS_BOUNDS_LIST;
else if (type == JavaStubElementTypes.EXTENDS_LIST) return PsiReferenceList.Role.EXTENDS_LIST;
else if (type == JavaStubElementTypes.IMPLEMENTS_LIST) return PsiReferenceList.Role.IMPLEMENTS_LIST;
else if (type == JavaStubElementTypes.THROWS_LIST) return PsiReferenceList.Role.THROWS_LIST;
throw new RuntimeException("Unknown element type: " + type);
}
private static JavaClassReferenceListElementType roleToElementType(PsiReferenceList.Role role) {
switch (role) {
case EXTENDS_BOUNDS_LIST: return JavaStubElementTypes.EXTENDS_BOUND_LIST;
case EXTENDS_LIST: return JavaStubElementTypes.EXTENDS_LIST;
case IMPLEMENTS_LIST: return JavaStubElementTypes.IMPLEMENTS_LIST;
case THROWS_LIST: return JavaStubElementTypes.THROWS_LIST;
}
throw new RuntimeException("Unknown role: " + role);
}
private static byte encodeRole(PsiReferenceList.Role role) {
switch (role) {
case EXTENDS_LIST: return 0;
case IMPLEMENTS_LIST: return 1;
case THROWS_LIST: return 2;
case EXTENDS_BOUNDS_LIST: return 3;
}
throw new RuntimeException("Unknown role: " + role);
}
private static PsiReferenceList.Role decodeRole(byte code) {
switch (code) {
case 0: return PsiReferenceList.Role.EXTENDS_LIST;
case 1: return PsiReferenceList.Role.IMPLEMENTS_LIST;
case 2: return PsiReferenceList.Role.THROWS_LIST;
case 3: return PsiReferenceList.Role.EXTENDS_BOUNDS_LIST;
}
throw new RuntimeException("Unknown role code: " + code);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -61,23 +61,21 @@ public abstract class JavaImportStatementElementType extends JavaStubElementType
}
@Override
public PsiImportStatementStub createStub(final LighterAST tree,
final LighterASTNode node,
final StubElement parentStub) {
public PsiImportStatementStub createStub(LighterAST tree, LighterASTNode node, StubElement parentStub) {
boolean isOnDemand = false;
String refText = null;
for (final LighterASTNode child : tree.getChildren(node)) {
final IElementType type = child.getTokenType();
for (LighterASTNode child : tree.getChildren(node)) {
IElementType type = child.getTokenType();
if (type == JavaElementType.JAVA_CODE_REFERENCE || type == JavaElementType.IMPORT_STATIC_REFERENCE) {
refText = SourceUtil.getTextSkipWhiteSpaceAndComments(tree, child);
refText = SourceUtil.getReferenceText(tree, child);
}
else if (type == JavaTokenType.ASTERISK) {
isOnDemand = true;
}
}
final byte flags = PsiImportStatementStubImpl.packFlags(isOnDemand, node.getTokenType() == JavaElementType.IMPORT_STATIC_STATEMENT);
byte flags = PsiImportStatementStubImpl.packFlags(isOnDemand, node.getTokenType() == JavaElementType.IMPORT_STATIC_STATEMENT);
return new PsiImportStatementStubImpl(parentStub, refText, flags);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -73,7 +73,6 @@ public abstract class JavaMethodElementType extends JavaStubElementType<PsiMetho
boolean isVarArgs = false;
boolean isDeprecatedByComment = false;
boolean hasDeprecatedAnnotation = false;
boolean isExtension = false;
String defValueText = null;
boolean expectingDef = false;
@@ -103,24 +102,18 @@ public abstract class JavaMethodElementType extends JavaStubElementType<PsiMetho
else if (type == JavaTokenType.DEFAULT_KEYWORD) {
expectingDef = true;
}
else if (expectingDef && !ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(type) && type != JavaTokenType.SEMICOLON) {
if (type != JavaElementType.CODE_BLOCK) {
defValueText = LightTreeUtil.toFilteredString(tree, child, null);
}
else {
isExtension = true;
}
else if (expectingDef && !ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(type) &&
type != JavaTokenType.SEMICOLON && type != JavaElementType.CODE_BLOCK) {
defValueText = LightTreeUtil.toFilteredString(tree, child, null);
break;
}
}
final TypeInfo typeInfo = isConstructor ? TypeInfo.createConstructorType() : TypeInfo.create(tree, node, parentStub);
final boolean isAnno = (node.getTokenType() == JavaElementType.ANNOTATION_METHOD);
final byte flags = PsiMethodStubImpl.packFlags(isConstructor, isAnno, isVarArgs, isDeprecatedByComment, hasDeprecatedAnnotation);
TypeInfo typeInfo = isConstructor ? TypeInfo.createConstructorType() : TypeInfo.create(tree, node, parentStub);
boolean isAnno = (node.getTokenType() == JavaElementType.ANNOTATION_METHOD);
byte flags = PsiMethodStubImpl.packFlags(isConstructor, isAnno, isVarArgs, isDeprecatedByComment, hasDeprecatedAnnotation);
final PsiMethodStubImpl stub = new PsiMethodStubImpl(parentStub, StringRef.fromString(name), typeInfo, flags, StringRef.fromString(defValueText));
stub.setExtensionMethodMark(isExtension);
return stub;
return new PsiMethodStubImpl(parentStub, StringRef.fromString(name), typeInfo, flags, StringRef.fromString(defValueText));
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -24,8 +24,8 @@ import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.impl.java.stubs.PsiAnnotationStub;
import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement;
import com.intellij.reference.SoftReference;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.PatchedSoftReference;
import com.intellij.util.io.StringRef;
import org.jetbrains.annotations.Nullable;
@@ -38,7 +38,7 @@ public class PsiAnnotationStubImpl extends StubBase<PsiAnnotation> implements Ps
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.java.stubs.impl.PsiAnnotationStubImpl");
private final String myText;
private PatchedSoftReference<PsiAnnotation> myParsedFromRepository;
private SoftReference<PsiAnnotation> myParsedFromRepository;
public PsiAnnotationStubImpl(final StubElement parent, final String text) {
this(parent, text, null);
@@ -73,8 +73,7 @@ public class PsiAnnotationStubImpl extends StubBase<PsiAnnotation> implements Ps
try {
PsiJavaParserFacade facade = JavaPsiFacade.getInstance(getProject()).getParserFacade();
PsiAnnotation annotation = facade.createAnnotationFromText(text, getPsi());
myParsedFromRepository = new PatchedSoftReference<PsiAnnotation>(annotation);
assert annotation != null : text;
myParsedFromRepository = new SoftReference<PsiAnnotation>(annotation);
return annotation;
}
catch (IncorrectOperationException e) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -28,15 +28,15 @@ import com.intellij.psi.impl.java.stubs.PsiImportStatementStub;
import com.intellij.psi.impl.source.PsiJavaCodeReferenceElementImpl;
import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement;
import com.intellij.reference.SoftReference;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.PatchedSoftReference;
import com.intellij.util.io.StringRef;
import org.jetbrains.annotations.Nullable;
public class PsiImportStatementStubImpl extends StubBase<PsiImportStatementBase> implements PsiImportStatementStub {
private final byte myFlags;
private final StringRef myText;
private PatchedSoftReference<PsiJavaCodeReferenceElement> myReference = null;
private SoftReference<PsiJavaCodeReferenceElement> myReference = null;
private final static int ON_DEMAND = 0x01;
private final static int STATIC = 0x02;
@@ -80,7 +80,7 @@ public class PsiImportStatementStubImpl extends StubBase<PsiImportStatementBase>
PsiJavaCodeReferenceElement ref = myReference != null ? myReference.get() : null;
if (ref == null) {
ref = isStatic() ? getStaticReference() : getRegularReference();
myReference = new PatchedSoftReference<PsiJavaCodeReferenceElement>(ref);
myReference = new SoftReference<PsiJavaCodeReferenceElement>(ref);
}
return ref;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -37,8 +37,6 @@ public class PsiMethodStubImpl extends StubBase<PsiMethod> implements PsiMethodS
private final byte myFlags;
private final StringRef myName;
private StringRef myDefaultValueText;
// todo[r.sh] drop this after transition period finished
private boolean myHasExtMethodMark = false;
private static final int CONSTRUCTOR = 0x01;
private static final int VARARGS = 0x02;
@@ -74,14 +72,6 @@ public class PsiMethodStubImpl extends StubBase<PsiMethod> implements PsiMethodS
myReturnType = returnType;
}
public void setExtensionMethodMark(boolean hasExtMethodMark) {
myHasExtMethodMark = hasExtMethodMark;
}
public boolean hasExtensionMethodMark() {
return myHasExtMethodMark;
}
@Override
public boolean isConstructor() {
return (myFlags & CONSTRUCTOR) != 0;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -15,79 +15,133 @@
*/
package com.intellij.psi.impl.source;
import com.intellij.lang.ASTNode;
import com.intellij.lang.LighterAST;
import com.intellij.lang.LighterASTNode;
import com.intellij.lang.impl.ASTNodeBuilder;
import com.intellij.lang.LighterLazyParseableNode;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.impl.source.tree.LightTreeUtil;
import com.intellij.psi.impl.source.tree.SourceUtil;
import com.intellij.psi.impl.source.tree.*;
import com.intellij.psi.stubs.LightStubBuilder;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.util.io.StringRef;
import org.jetbrains.annotations.NotNull;
public class JavaLightStubBuilder extends LightStubBuilder {
@NotNull
@Override
protected StubElement createStubForFile(final PsiFile file, final LighterAST tree) {
if (!(file instanceof PsiJavaFile)) return super.createStubForFile(file, tree);
String refText = "";
final LighterASTNode pkg = LightTreeUtil.firstChildOfType(tree, tree.getRoot(), JavaElementType.PACKAGE_STATEMENT);
if (pkg != null) {
final LighterASTNode ref = LightTreeUtil.firstChildOfType(tree, pkg, JavaElementType.JAVA_CODE_REFERENCE);
if (ref != null) {
refText = SourceUtil.getTextSkipWhiteSpaceAndComments(tree, ref);
}
protected StubElement createStubForFile(@NotNull PsiFile file, @NotNull LighterAST tree) {
if (!(file instanceof PsiJavaFile)) {
return super.createStubForFile(file, tree);
}
String refText = "";
LighterASTNode pkg = LightTreeUtil.firstChildOfType(tree, tree.getRoot(), JavaElementType.PACKAGE_STATEMENT);
if (pkg != null) {
LighterASTNode ref = LightTreeUtil.firstChildOfType(tree, pkg, JavaElementType.JAVA_CODE_REFERENCE);
if (ref != null) {
refText = SourceUtil.getReferenceText(tree, ref);
}
}
return new PsiJavaFileStubImpl((PsiJavaFile)file, StringRef.fromString(refText), false);
}
@Override
public boolean skipChildProcessingWhenBuildingStubs(final IElementType nodeType, final IElementType childType) {
return childType == JavaElementType.PARAMETER && nodeType != JavaElementType.PARAMETER_LIST ||
childType == JavaElementType.PARAMETER_LIST && nodeType == JavaElementType.LAMBDA_EXPRESSION;
public boolean skipChildProcessingWhenBuildingStubs(@NotNull ASTNode parent, @NotNull ASTNode node) {
IElementType parentType = parent.getElementType();
IElementType nodeType = node.getElementType();
if (checkByTypes(parentType, nodeType)) return true;
if (nodeType == JavaElementType.CODE_BLOCK && node instanceof TreeElement) {
CodeBlockVisitor visitor = new CodeBlockVisitor();
((TreeElement)node).acceptTree(visitor);
return visitor.result;
}
return false;
}
@Override
public boolean skipChildProcessingWhenBuildingStubs(final LightStubBuilder builder,
final LighterAST tree,
final LighterASTNode parent,
final LighterASTNode child) {
if (child.getTokenType() == JavaElementType.CODE_BLOCK) {
if (child instanceof ASTNodeBuilder.ASTUnparsedNodeMarker) {
ASTNodeBuilder.ASTUnparsedNodeMarker nodeMarker = (ASTNodeBuilder.ASTUnparsedNodeMarker)child;
final ASTNodeBuilder nodeBuilder = nodeMarker.getBuilder();
final int endLexemeIndex = nodeMarker.getEndLexemeIndex();
boolean seenNew = false;
protected boolean skipChildProcessingWhenBuildingStubs(@NotNull LighterAST tree, @NotNull LighterASTNode parent, @NotNull LighterASTNode node) {
IElementType parentType = parent.getTokenType();
IElementType nodeType = node.getTokenType();
for (int i = nodeMarker.getStartLexemeIndex(); i < endLexemeIndex; ++i) {
final IElementType type = nodeBuilder.getElementType(i);
if (type == JavaTokenType.NEW_KEYWORD) {
seenNew = true;
}
else if (seenNew && type == JavaTokenType.LBRACE) {
return false;
}
else if (seenNew && type == JavaTokenType.SEMICOLON) {
seenNew = false;
}
else if (type == JavaTokenType.AT || // local vars can be annotated and we have them in stubs!
type == JavaTokenType.CLASS_KEYWORD || // local classes
type == JavaTokenType.INTERFACE_KEYWORD ||
type == JavaTokenType.ENUM_KEYWORD) {
return false;
}
}
if (checkByTypes(parentType, nodeType)) return true;
return true;
}
if (nodeType == JavaElementType.CODE_BLOCK && node instanceof LighterLazyParseableNode) {
CodeBlockVisitor visitor = new CodeBlockVisitor();
((LighterLazyParseableNode)node).accept(visitor);
return visitor.result;
}
return false;
}
}
private static boolean checkByTypes(IElementType parentType, IElementType nodeType) {
if (ElementType.IMPORT_STATEMENT_BASE_BIT_SET.contains(parentType)) {
return true;
}
if (nodeType == JavaElementType.PARAMETER && parentType != JavaElementType.PARAMETER_LIST) {
return true;
}
if (nodeType == JavaElementType.PARAMETER_LIST && parentType == JavaElementType.LAMBDA_EXPRESSION) {
return true;
}
return false;
}
private static class CodeBlockVisitor extends RecursiveTreeElementWalkingVisitor implements LighterLazyParseableNode.Visitor {
private static final TokenSet BLOCK_ELEMENTS = TokenSet.create(
JavaElementType.ANNOTATION, JavaElementType.CLASS, JavaElementType.ANONYMOUS_CLASS);
private boolean result = true;
@Override
protected void visitNode(TreeElement element) {
if (BLOCK_ELEMENTS.contains(element.getElementType())) {
result = false;
stopWalking();
return;
}
super.visitNode(element);
}
private IElementType last = null;
private boolean seenNew = false;
@Override
public boolean visit(IElementType type) {
if (ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(type)) {
return true;
}
// annotations
if (type == JavaTokenType.AT) {
return (result = false);
}
// anonymous classes
else if (type == JavaTokenType.NEW_KEYWORD) {
seenNew = true;
}
else if (seenNew && type == JavaTokenType.SEMICOLON) {
seenNew = false;
}
else if (seenNew && type == JavaTokenType.LBRACE && last != JavaTokenType.RBRACKET) {
return (result = false);
}
// local classes
else if (type == JavaTokenType.CLASS_KEYWORD && last != JavaTokenType.DOT) {
return (result = false);
}
last = type;
return true;
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -22,7 +22,7 @@ import com.intellij.psi.*;
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.impl.java.stubs.PsiMethodStub;
import com.intellij.psi.impl.source.tree.ChildRole;
import com.intellij.util.PatchedSoftReference;
import com.intellij.reference.SoftReference;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -30,7 +30,7 @@ import org.jetbrains.annotations.NotNull;
* @author ven
*/
public class PsiAnnotationMethodImpl extends PsiMethodImpl implements PsiAnnotationMethod {
private PatchedSoftReference<PsiAnnotationMemberValue> myCachedDefaultValue = null;
private SoftReference<PsiAnnotationMemberValue> myCachedDefaultValue = null;
public PsiAnnotationMethodImpl(final PsiMethodStub stub) {
super(stub, JavaStubElementTypes.ANNOTATION_METHOD);
@@ -68,7 +68,7 @@ public class PsiAnnotationMethodImpl extends PsiMethodImpl implements PsiAnnotat
final PsiFileFactory factory = PsiFileFactory.getInstance(getProject());
final PsiJavaFile file = (PsiJavaFile)factory.createFileFromText("a.java", JavaFileType.INSTANCE, annoText);
final PsiAnnotationMemberValue value = ((PsiAnnotationMethod)file.getClasses()[0].getMethods()[0]).getDefaultValue();
myCachedDefaultValue = new PatchedSoftReference<PsiAnnotationMemberValue>(value);
myCachedDefaultValue = new SoftReference<PsiAnnotationMemberValue>(value);
return value;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -22,12 +22,12 @@ import com.intellij.psi.impl.java.stubs.PsiClassStub;
import com.intellij.psi.impl.source.tree.ChildRole;
import com.intellij.psi.impl.source.tree.SharedImplUtil;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.reference.SoftReference;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.PatchedSoftReference;
import org.jetbrains.annotations.NotNull;
public class PsiAnonymousClassImpl extends PsiClassImpl implements PsiAnonymousClass {
private PatchedSoftReference<PsiClassType> myCachedBaseType = null;
private SoftReference<PsiClassType> myCachedBaseType = null;
public PsiAnonymousClassImpl(final PsiClassStub stub) {
super(stub, JavaStubElementTypes.ANONYMOUS_CLASS);
@@ -92,7 +92,7 @@ public class PsiAnonymousClassImpl extends PsiClassImpl implements PsiAnonymousC
type = PsiType.getJavaLangObject(getManager(), getResolveScope());
}
myCachedBaseType = new PatchedSoftReference<PsiClassType>(type);
myCachedBaseType = new SoftReference<PsiClassType>(type);
return type;
}
else {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -33,9 +33,9 @@ import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.reference.SoftReference;
import com.intellij.ui.RowIcon;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.PatchedSoftReference;
import com.intellij.util.PlatformIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -49,7 +49,7 @@ import java.util.Set;
public class PsiFieldImpl extends JavaStubPsiElement<PsiFieldStub> implements PsiField, PsiVariableEx, Queryable {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.PsiFieldImpl");
private volatile PatchedSoftReference<PsiType> myCachedType = null;
private volatile SoftReference<PsiType> myCachedType = null;
private volatile Object myCachedInitializerValue = null; // PsiExpression on constant value for literal
public PsiFieldImpl(final PsiFieldStub stub) {
@@ -129,7 +129,7 @@ public class PsiFieldImpl extends JavaStubPsiElement<PsiFieldStub> implements Ps
String typeText = TypeInfo.createTypeText(stub.getType(false));
try {
final PsiType type = JavaPsiFacade.getInstance(getProject()).getParserFacade().createTypeFromText(typeText, this);
myCachedType = new PatchedSoftReference<PsiType>(type);
myCachedType = new SoftReference<PsiType>(type);
return type;
}
catch (IncorrectOperationException e) {
@@ -148,7 +148,7 @@ public class PsiFieldImpl extends JavaStubPsiElement<PsiFieldStub> implements Ps
public PsiType getType(){
final PsiFieldStub stub = getStub();
if (stub != null) {
PatchedSoftReference<PsiType> cachedType = myCachedType;
SoftReference<PsiType> cachedType = myCachedType;
if (cachedType != null) {
PsiType type = cachedType.get();
if (type != null) return type;
@@ -157,7 +157,7 @@ public class PsiFieldImpl extends JavaStubPsiElement<PsiFieldStub> implements Ps
String typeText = TypeInfo.createTypeText(stub.getType(true));
try {
final PsiType type = JavaPsiFacade.getInstance(getProject()).getParserFacade().createTypeFromText(typeText, this);
myCachedType = new PatchedSoftReference<PsiType>(type);
myCachedType = new SoftReference<PsiType>(type);
return type;
}
catch (IncorrectOperationException e) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -20,8 +20,10 @@ import com.intellij.psi.*;
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.impl.java.stubs.PsiImportListStub;
import com.intellij.psi.impl.source.tree.ElementType;
import com.intellij.util.containers.HashMap;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.util.ArrayFactory;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
@@ -63,17 +65,19 @@ public class PsiImportListImpl extends JavaStubPsiElement<PsiImportListStub> imp
super.subtreeChanged();
}
private static final TokenSet IMPORT_STATEMENT_BIT_SET = TokenSet.create(JavaElementType.IMPORT_STATEMENT);
private static final TokenSet IMPORT_STATIC_STATEMENT_BIT_SET = TokenSet.create(JavaElementType.IMPORT_STATIC_STATEMENT);
@Override
@NotNull
public PsiImportStatement[] getImportStatements() {
return getStubOrPsiChildren(ElementType.IMPORT_STATEMENT_BIT_SET, PsiImportStatementImpl.ARRAY_FACTORY);
return getStubOrPsiChildren(IMPORT_STATEMENT_BIT_SET, PsiImportStatementImpl.ARRAY_FACTORY);
}
@Override
@NotNull
public PsiImportStaticStatement[] getImportStaticStatements() {
return getStubOrPsiChildren(ElementType.IMPORT_STATIC_STATEMENT_BIT_SET, PsiImportStaticStatementImpl.ARRAY_FACTORY);
return getStubOrPsiChildren(IMPORT_STATIC_STATEMENT_BIT_SET, PsiImportStaticStatementImpl.ARRAY_FACTORY);
}
@Override
@@ -686,7 +686,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
private String getTextSkipWhiteSpaceAndComments() {
String whiteSpaceAndComments = myCachedTextSkipWhiteSpaceAndComments;
if (whiteSpaceAndComments == null) {
myCachedTextSkipWhiteSpaceAndComments = whiteSpaceAndComments = SourceUtil.getTextSkipWhiteSpaceAndComments(this);
myCachedTextSkipWhiteSpaceAndComments = whiteSpaceAndComments = SourceUtil.getReferenceText(this);
}
return whiteSpaceAndComments;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -40,9 +40,9 @@ import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.util.MethodSignature;
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.reference.SoftReference;
import com.intellij.ui.RowIcon;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.PatchedSoftReference;
import com.intellij.util.PlatformIcons;
import org.jetbrains.annotations.NotNull;
@@ -53,7 +53,7 @@ import java.util.Map;
public class PsiMethodImpl extends JavaStubPsiElement<PsiMethodStub> implements PsiMethod, Queryable {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.PsiMethodImpl");
private PatchedSoftReference<PsiType> myCachedType = null;
private SoftReference<PsiType> myCachedType = null;
public PsiMethodImpl(final PsiMethodStub stub) {
this(stub, JavaStubElementTypes.METHOD);
@@ -220,7 +220,7 @@ public class PsiMethodImpl extends JavaStubPsiElement<PsiMethodStub> implements
final String typeText = TypeInfo.createTypeText(stub.getReturnTypeText(true));
if (typeText == null) return null;
PatchedSoftReference<PsiType> cachedType = myCachedType;
SoftReference<PsiType> cachedType = myCachedType;
if (cachedType != null) {
PsiType type = cachedType.get();
if (type != null) return type;
@@ -228,7 +228,7 @@ public class PsiMethodImpl extends JavaStubPsiElement<PsiMethodStub> implements
try {
final PsiType type = JavaPsiFacade.getInstance(getProject()).getElementFactory().createTypeFromText(typeText, this);
myCachedType = new PatchedSoftReference<PsiType>(type);
myCachedType = new SoftReference<PsiType>(type);
return type;
}
catch (IncorrectOperationException e) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -30,15 +30,12 @@ import com.intellij.psi.impl.source.tree.Factory;
import com.intellij.psi.impl.source.tree.TreeElement;
import com.intellij.psi.impl.source.tree.java.PsiAnnotationImpl;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
@@ -134,12 +131,9 @@ public class PsiModifierListImpl extends JavaStubPsiElement<PsiModifierListStub>
return false;
}
if (type == JavaTokenType.ABSTRACT_KEYWORD) {
return !(getNode().findChildByType(JavaTokenType.DEFAULT_KEYWORD) != null || findExtensionMethodMarker((PsiMethod)parent) != null);
return getNode().findChildByType(JavaTokenType.DEFAULT_KEYWORD) == null;
}
}
if (type == JavaTokenType.DEFAULT_KEYWORD && findExtensionMethodMarker((PsiMethod)parent) != null) {
return true;
}
}
else if (parent instanceof PsiField) {
if (parent instanceof PsiEnumConstant) {
@@ -179,16 +173,6 @@ public class PsiModifierListImpl extends JavaStubPsiElement<PsiModifierListStub>
return getNode().findChildByType(type) != null;
}
@Nullable
public static PsiJavaToken findExtensionMethodMarker(@Nullable PsiMethod method) {
// todo[r.sh] drop this after transition period finished
if (method == null) return null;
final PsiCodeBlock body = method.getBody();
if (body == null) return null;
final PsiElement previous = PsiTreeUtil.skipSiblingsBackward(body, PsiComment.class, PsiWhiteSpace.class);
return previous instanceof PsiJavaToken && PsiUtil.isJavaToken(previous, JavaTokenType.DEFAULT_KEYWORD) ? (PsiJavaToken)previous : null;
}
@Override
public boolean hasExplicitModifier(@NotNull String name) {
final CompositeElement tree = (CompositeElement)getNode();
@@ -234,7 +218,6 @@ public class PsiModifierListImpl extends JavaStubPsiElement<PsiModifierListStub>
}
else if (parent instanceof PsiMethod && grandParent instanceof PsiClass && ((PsiClass)grandParent).isInterface()) {
if (type == JavaTokenType.PUBLIC_KEYWORD || type == JavaTokenType.ABSTRACT_KEYWORD) return;
if (type == JavaTokenType.DEFAULT_KEYWORD && findExtensionMethodMarker((PsiMethod)parent) != null) return;
}
else if (parent instanceof PsiClass && grandParent instanceof PsiClass && ((PsiClass)grandParent).isInterface()) {
if (type == JavaTokenType.PUBLIC_KEYWORD) return;
@@ -257,13 +240,6 @@ public class PsiModifierListImpl extends JavaStubPsiElement<PsiModifierListStub>
if (child != null) {
SourceTreeToPsiMap.treeToPsiNotNull(child).delete();
}
if (type == JavaTokenType.DEFAULT_KEYWORD && parent instanceof PsiMethod) {
final PsiJavaToken marker = findExtensionMethodMarker((PsiMethod)parent);
if (marker != null) {
marker.delete();
}
}
}
}
@@ -32,9 +32,9 @@ import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.reference.SoftReference;
import com.intellij.ui.RowIcon;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.PatchedSoftReference;
import com.intellij.util.PlatformIcons;
import org.jetbrains.annotations.NotNull;
@@ -44,7 +44,7 @@ import java.util.Arrays;
public class PsiParameterImpl extends JavaStubPsiElement<PsiParameterStub> implements PsiParameter {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.PsiParameterImpl");
private volatile PatchedSoftReference<PsiType> myCachedType = null;
private volatile SoftReference<PsiType> myCachedType = null;
public PsiParameterImpl(@NotNull PsiParameterStub stub) {
this(stub, JavaStubElementTypes.PARAMETER);
@@ -116,7 +116,7 @@ public class PsiParameterImpl extends JavaStubPsiElement<PsiParameterStub> imple
public PsiType getType() {
PsiParameterStub stub = getStub();
if (stub != null) {
PatchedSoftReference<PsiType> cachedType = myCachedType;
SoftReference<PsiType> cachedType = myCachedType;
if (cachedType != null) {
PsiType type = cachedType.get();
if (type != null) return type;
@@ -126,7 +126,7 @@ public class PsiParameterImpl extends JavaStubPsiElement<PsiParameterStub> imple
assert typeText != null : stub;
try {
PsiType type = JavaPsiFacade.getInstance(getProject()).getParserFacade().createTypeFromText(typeText, this);
myCachedType = new PatchedSoftReference<PsiType>(type);
myCachedType = new SoftReference<PsiType>(type);
return type;
}
catch (IncorrectOperationException e) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -28,9 +28,9 @@ import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.reference.SoftReference;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.PatchedSoftReference;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
@@ -45,7 +45,7 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.PsiTypeElementImpl");
private volatile PsiType myCachedType = null;
private volatile PatchedSoftReference<PsiType> myCachedDetachedType = null;
private volatile SoftReference<PsiType> myCachedDetachedType = null;
@SuppressWarnings({"UnusedDeclaration"})
public PsiTypeElementImpl() {
@@ -110,8 +110,8 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl
final List<PsiType> types = ContainerUtil.map(typeElements, new Function<PsiTypeElement, PsiType>() {
@Override public PsiType fun(final PsiTypeElement psiTypeElement) { return psiTypeElement.getType(); }
});
cachedType = opElement instanceof PsiJavaToken && ((PsiJavaToken)opElement).getTokenType() == JavaTokenType.AND
? PsiIntersectionType.createIntersection(types.toArray(new PsiType[types.size()]))
cachedType = opElement instanceof PsiJavaToken && ((PsiJavaToken)opElement).getTokenType() == JavaTokenType.AND
? PsiIntersectionType.createIntersection(types.toArray(new PsiType[types.size()]))
: new PsiDisjunctionType(types, getManager());
}
}
@@ -168,14 +168,14 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl
}
public PsiType getDetachedType(@NotNull PsiElement context) {
PatchedSoftReference<PsiType> cached = myCachedDetachedType;
SoftReference<PsiType> cached = myCachedDetachedType;
PsiType type = cached == null ? null : cached.get();
if (type != null) return type;
try {
String combinedAnnotations = getCombinedAnnotationsText();
String text = combinedAnnotations.isEmpty() ? getText().trim() : combinedAnnotations + " " + getText().trim();
type = JavaPsiFacade.getInstance(getProject()).getElementFactory().createTypeFromText(text, context);
myCachedDetachedType = new PatchedSoftReference<PsiType>(type);
myCachedDetachedType = new SoftReference<PsiType>(type);
}
catch (IncorrectOperationException e) {
return getType();
@@ -19,6 +19,7 @@ import com.intellij.psi.*;
import com.intellij.psi.scope.MethodProcessorSetupFailedException;
import com.intellij.psi.scope.processor.MethodCandidatesProcessor;
import com.intellij.psi.scope.util.PsiScopesUtil;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;
import java.util.*;
@@ -99,8 +100,8 @@ public class GraphInferencePolicy extends ProcessCandidateParameterTypeInference
}
public static void forget(PsiElement parent) {
if (parent instanceof PsiCallExpression) {
final PsiElement gParent = parent.getParent();
if (parent instanceof PsiExpression) {
PsiElement gParent = PsiUtil.skipParenthesizedExprUp(parent.getParent());
if (gParent instanceof PsiExpressionList) {
final PsiElement ggParent = gParent.getParent();
if (ggParent instanceof PsiCallExpression) {
@@ -43,7 +43,11 @@ public class ProcessCandidateParameterTypeInferencePolicy extends DefaultParamet
PsiCallExpression contextCall,
PsiTypeParameter typeParameter) {
PsiExpression[] expressions = expressionList.getExpressions();
int i = ArrayUtil.find(expressions, innerMethodCall);
PsiElement parent = innerMethodCall;
while (parent.getParent() instanceof PsiParenthesizedExpression) {
parent = parent.getParent();
}
int i = ArrayUtil.find(expressions, parent);
if (i < 0) return null;
PsiMethod owner = (PsiMethod)typeParameter.getOwner();
if (owner == null) return null;
@@ -15,7 +15,9 @@
*/
package com.intellij.psi.impl.source.resolve;
import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
import com.intellij.openapi.projectRoots.JavaVersionService;
import com.intellij.openapi.util.Computable;
@@ -32,6 +34,7 @@ import com.intellij.psi.scope.processor.MethodCandidatesProcessor;
import com.intellij.psi.scope.processor.MethodResolverProcessor;
import com.intellij.psi.scope.util.PsiScopesUtil;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
@@ -205,6 +208,7 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
sortLambdaExpressionsLast(paramTypes, argTypes);
boolean rawType = false;
boolean nullPassed = false;
boolean lambdaRaw = false;
for (int j = 0; j < argTypes.length; j++) {
PsiType argumentType = argTypes[j];
if (argumentType == null) continue;
@@ -228,6 +232,12 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
if (currentSubstitution == FAILED_INFERENCE || (currentSubstitution == null && lowerBound == PsiType.NULL)) return RAW_INFERENCE;
}
if (nullPassed && currentSubstitution == null) return RAW_INFERENCE;
if (currentSubstitution != null && currentSubstitution.first == null) {
lambdaRaw = true;
}
if (currentSubstitution == null && lambdaRaw) {
return new Pair<PsiType, ConstraintType>(PsiType.getJavaLangObject(typeParameter.getManager(), typeParameter.getResolveScope()), ConstraintType.EQUALS);
}
} else if (argumentType instanceof PsiMethodReferenceType) {
final PsiMethodReferenceExpression referenceExpression = ((PsiMethodReferenceType)argumentType).getExpression();
currentSubstitution = inferConstraintFromFunctionalInterfaceMethod(typeParameter, referenceExpression, partialSubstitutor.substitute(parameterType), partialSubstitutor, policy);
@@ -998,7 +1008,7 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
return null;
}
private static Pair<PsiType, ConstraintType> inferMethodTypeParameterFromParent(PsiElement parent,
private static Pair<PsiType, ConstraintType> inferMethodTypeParameterFromParent(final PsiElement parent,
PsiExpression methodCall,
final PsiTypeParameter typeParameter,
PsiSubstitutor substitutor,
@@ -1065,15 +1075,28 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
}
}
} else if (parent instanceof PsiLambdaExpression) {
expectedType = LambdaUtil.getFunctionalInterfaceReturnType(((PsiLambdaExpression)parent).getFunctionalInterfaceType());
expectedType = ourGraphGuard.doPreventingRecursion(methodCall, true, new Computable<PsiType>() {
@Override
public PsiType compute() {
return LambdaUtil.getFunctionalInterfaceReturnType(((PsiLambdaExpression)parent).getFunctionalInterfaceType());
}
});
if (expectedType == null) {
return getFailedInferenceConstraint(typeParameter);
return null;
}
} else if (parent instanceof PsiTypeCastExpression) {
expectedType = ((PsiTypeCastExpression)parent).getType();
} else if (parent instanceof PsiConditionalExpression) {
if (PsiUtil.isLanguageLevel8OrHigher(parent)) {
return inferMethodTypeParameterFromParent(parent.getParent(), (PsiExpression)parent, typeParameter, substitutor, policy);
try {
final Pair<PsiType, ConstraintType> pair = inferFromConditionalExpression(parent, methodCall, typeParameter, substitutor, policy);
if (pair != null) {
return pair;
}
}
finally {
GraphInferencePolicy.forget(parent);
}
}
}
@@ -1127,6 +1150,10 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
}
return null;
}
final Pair<PsiType, ConstraintType> inferredExceptionTypeConstraint = inferExceptionConstrains(typeParameter, expression, method, resolveResult.getSubstitutor());
if (inferredExceptionTypeConstraint != null) {
return inferredExceptionTypeConstraint;
}
}
}
}
@@ -1170,6 +1197,91 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
return result;
}
private static Pair<PsiType, ConstraintType> inferExceptionConstrains(PsiTypeParameter typeParameter,
PsiExpression expression,
PsiMethod method,
PsiSubstitutor substitutor) {
final PsiClassType[] declaredExceptions = method.getThrowsList().getReferencedTypes();
for (PsiClassType exception : declaredExceptions) {
final PsiType substitute = substitutor.substitute(exception);
if (PsiUtil.resolveClassInType(substitute) == typeParameter) {
if (expression instanceof PsiLambdaExpression) {
final PsiElement body = ((PsiLambdaExpression)expression).getBody();
if (body != null) {
final List<PsiClassType> unhandledExceptions = ExceptionUtil.getUnhandledExceptions(body);
if (unhandledExceptions.isEmpty()) {
return inferUncheckedException(typeParameter, exception, method);
}
}
}
else if (expression instanceof PsiMethodReferenceExpression) {
final PsiElement resolve = ((PsiMethodReferenceExpression)expression).resolve();
if (resolve instanceof PsiMethod) {
final PsiClassType[] declaredThrowsList = ((PsiMethod)resolve).getThrowsList().getReferencedTypes();
for (PsiClassType psiClassType : declaredThrowsList) {
if (!ExceptionUtil.isUncheckedException(psiClassType)) return null;
}
return inferUncheckedException(typeParameter, exception, method);
}
}
break;
}
}
return null;
}
private static Pair<PsiType, ConstraintType> inferUncheckedException(PsiTypeParameter typeParameter,
PsiClassType exception,
PsiMethod method) {
final Project project = typeParameter.getProject();
final PsiClass runtimeException = JavaPsiFacade.getInstance(project).findClass(CommonClassNames.JAVA_LANG_RUNTIME_EXCEPTION, method.getResolveScope());
if (runtimeException != null) {
for (PsiType superType : exception.getSuperTypes()) {
if (!InheritanceUtil.isInheritorOrSelf(runtimeException, PsiUtil.resolveClassInType(superType), true)) {
return getFailedInferenceConstraint(typeParameter);
}
}
return Pair.<PsiType, ConstraintType>create(JavaPsiFacade.getElementFactory(project).createType(runtimeException, PsiSubstitutor.EMPTY), ConstraintType.EQUALS);
}
return null;
}
private static Pair<PsiType, ConstraintType> inferFromConditionalExpression(PsiElement parent,
PsiExpression methodCall,
PsiTypeParameter typeParameter,
PsiSubstitutor substitutor,
ParameterTypeInferencePolicy policy) {
Pair<PsiType, ConstraintType> pair =
inferMethodTypeParameterFromParent(PsiUtil.skipParenthesizedExprUp(parent.getParent()), (PsiExpression)parent, typeParameter, substitutor, policy);
if (pair == null) {
final PsiExpression thenExpression = ((PsiConditionalExpression)parent).getThenExpression();
final PsiExpression elseExpression = ((PsiConditionalExpression)parent).getElseExpression();
final PsiType[] paramTypes = {((PsiMethod)typeParameter.getOwner()).getReturnType()};
if (methodCall.equals(PsiUtil.skipParenthesizedExprDown(elseExpression)) && thenExpression != null) {
final PsiType thenType = ourGraphGuard.doPreventingRecursion(parent, true, new Computable<PsiType>() {
@Override
public PsiType compute() {
return thenExpression.getType();
}
});
if (thenType != null) {
pair = inferTypeForMethodTypeParameterInner(typeParameter, paramTypes, new PsiType[] {thenType}, substitutor, null, policy);
}
} else if (methodCall.equals(PsiUtil.skipParenthesizedExprDown(thenExpression)) && elseExpression != null) {
final PsiType elseType = ourGraphGuard.doPreventingRecursion(parent, true, new Computable<PsiType>() {
@Override
public PsiType compute() {
return elseExpression.getType();
}
});
if (elseType != null) {
pair = inferTypeForMethodTypeParameterInner(typeParameter, paramTypes, new PsiType[] {elseType}, substitutor, null, policy);
}
}
}
return pair;
}
private static final ProcessCandidateParameterTypeInferencePolicy GRAPH_INFERENCE_POLICY = new GraphInferencePolicy();
private static Pair<PsiType, ConstraintType> graphInferenceFromCallContext(@NotNull final PsiExpression methodCall,
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -70,12 +70,8 @@ public interface ElementType extends JavaTokenType, JavaDocTokenType, JavaElemen
WHILE_STATEMENT, FOR_STATEMENT, FOREACH_STATEMENT, DO_WHILE_STATEMENT, SWITCH_STATEMENT, SWITCH_LABEL_STATEMENT, BREAK_STATEMENT,
CONTINUE_STATEMENT, RETURN_STATEMENT, THROW_STATEMENT, SYNCHRONIZED_STATEMENT, TRY_STATEMENT, LABELED_STATEMENT, ASSERT_STATEMENT);
TokenSet TYPES_BIT_SET = TokenSet.create(TYPE);
TokenSet IMPORT_STATEMENT_BIT_SET = TokenSet.create(IMPORT_STATEMENT);
TokenSet IMPORT_STATIC_STATEMENT_BIT_SET = TokenSet.create(IMPORT_STATIC_STATEMENT);
TokenSet IMPORT_STATEMENT_BASE_BIT_SET = TokenSet.create(IMPORT_STATEMENT, IMPORT_STATIC_STATEMENT);
TokenSet CLASS_KEYWORD_BIT_SET = TokenSet.create(CLASS_KEYWORD, INTERFACE_KEYWORD, ENUM_KEYWORD);
TokenSet MEMBER_BIT_SET = TokenSet.create(CLASS, FIELD, ENUM_CONSTANT, METHOD, ANNOTATION_METHOD);
TokenSet FULL_MEMBER_BIT_SET = TokenSet.orSet(MEMBER_BIT_SET, TokenSet.create(CLASS_INITIALIZER));
TokenSet ANNOTATIONS = TokenSet.create(ANNOTATION);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -20,30 +20,67 @@ import com.intellij.lang.ASTNode;
import com.intellij.lang.LighterAST;
import com.intellij.lang.LighterASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.PsiManager;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.impl.source.DummyHolder;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.util.CharTable;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
public class SourceUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.SourceUtil");
private static final TokenSet REF_FILTER = TokenSet.orSet(
ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET, TokenSet.create(JavaElementType.ANNOTATION));
private SourceUtil() { }
public static String getTextSkipWhiteSpaceAndComments(final ASTNode element) {
@NotNull
public static String getReferenceText(@NotNull PsiJavaCodeReferenceElement ref) {
final StringBuilder buffer = new StringBuilder();
((TreeElement)ref.getNode()).acceptTree(new RecursiveTreeElementWalkingVisitor() {
@Override
public void visitLeaf(LeafElement leaf) {
if (!REF_FILTER.contains(leaf.getElementType())) {
buffer.append(leaf.getText());
}
}
@Override
public void visitComposite(CompositeElement composite) {
if (!REF_FILTER.contains(composite.getElementType())) {
super.visitComposite(composite);
}
}
});
return buffer.toString();
}
@NotNull
public static String getReferenceText(@NotNull LighterAST tree, @NotNull LighterASTNode node) {
return LightTreeUtil.toFilteredString(tree, node, REF_FILTER);
}
/** @deprecated use {@link AstBufferUtil#getTextSkippingWhitespaceComments(ASTNode)} (to remove in IDEA 13) */
@SuppressWarnings("UnusedDeclaration")
public static String getTextSkipWhiteSpaceAndComments(ASTNode element) {
return AstBufferUtil.getTextSkippingWhitespaceComments(element);
}
public static String getTextSkipWhiteSpaceAndComments(final LighterAST tree, final LighterASTNode node) {
/** @deprecated use {@link LightTreeUtil#toFilteredString(LighterAST, LighterASTNode, TokenSet)} (to remove in IDEA 13) */
@SuppressWarnings("UnusedDeclaration")
public static String getTextSkipWhiteSpaceAndComments(LighterAST tree, LighterASTNode node) {
return LightTreeUtil.toFilteredString(tree, node, ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET);
}
public static TreeElement addParenthToReplacedChild(final IElementType parenthType, TreeElement newChild, PsiManager manager) {
public static TreeElement addParenthToReplacedChild(@NotNull IElementType parenthType,
@NotNull TreeElement newChild,
@NotNull PsiManager manager) {
CompositeElement parenthExpr = ASTFactory.composite(parenthType);
TreeElement dummyExpr = (TreeElement)newChild.clone();
@@ -56,9 +93,8 @@ public class SourceUtil {
try {
CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(manager.getProject());
parenthExpr =
(CompositeElement)SourceTreeToPsiMap.psiElementToTree(
codeStyleManager.reformat(SourceTreeToPsiMap.treeElementToPsi(parenthExpr)));
PsiElement formatted = codeStyleManager.reformat(SourceTreeToPsiMap.treeToPsiNotNull(parenthExpr));
parenthExpr = (CompositeElement)SourceTreeToPsiMap.psiToTreeNotNull(formatted);
}
catch (IncorrectOperationException e) {
LOG.error(e); // should not happen
@@ -68,7 +104,7 @@ public class SourceUtil {
dummyExpr.rawReplaceWithList(newChild);
newChild = parenthExpr;
// TODO remove explicit caches drop since this should be ok if we will use ChangeUtil for the modification
// TODO remove explicit caches drop since this should be ok if we will use ChangeUtil for the modification
TreeUtil.clearCaches(TreeUtil.getFileElement(newChild));
return newChild;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -214,7 +214,7 @@ public class ClassElement extends CompositeElement implements Constants {
}
}
}
super.deleteChildInternal(child);
}
@@ -364,7 +364,7 @@ public class ClassElement extends CompositeElement implements Constants {
else if (i == JavaDocElementType.DOC_COMMENT) {
return getChildRole(child, ChildRole.DOC_COMMENT);
}
else if (i == C_STYLE_COMMENT || i == END_OF_LINE_COMMENT) {
else if (ElementType.JAVA_PLAIN_COMMENT_BIT_SET.contains(i)) {
return ChildRoleBase.NONE;
}
else if (i == MODIFIER_LIST) {
@@ -376,7 +376,7 @@ public class ClassElement extends CompositeElement implements Constants {
else if (i == IMPLEMENTS_LIST) {
return ChildRole.IMPLEMENTS_LIST;
}
else if (i == CLASS_KEYWORD || i == INTERFACE_KEYWORD || i == ENUM_KEYWORD) {
else if (ElementType.CLASS_KEYWORD_BIT_SET.contains(i)) {
return getChildRole(child, ChildRole.CLASS_OR_INTERFACE_KEYWORD);
}
else if (i == IDENTIFIER) {
@@ -403,5 +403,4 @@ public class ClassElement extends CompositeElement implements Constants {
protected boolean isVisibilitySupported() {
return true;
}
}
@@ -17,6 +17,7 @@ package com.intellij.psi.impl.source.tree.java;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Condition;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.DebugUtil;
@@ -27,19 +28,15 @@ import com.intellij.psi.impl.source.tree.ElementType;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.tree.ChildRoleBase;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
public class PsiMethodCallExpressionImpl extends ExpressionPsiElement implements PsiMethodCallExpression {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiMethodCallExpressionImpl");
@NonNls private static final String GET_CLASS_METHOD = "getClass";
public PsiMethodCallExpressionImpl() {
super(JavaElementType.METHOD_CALL_EXPRESSION);
@@ -174,39 +171,19 @@ public class PsiMethodCallExpressionImpl extends ExpressionPsiElement implements
private static PsiType getResultType(PsiExpression call, PsiReferenceExpression methodExpression, JavaResolveResult result) {
final PsiMethod method = (PsiMethod)result.getElement();
if (method == null) return null;
PsiManager manager = call.getManager();
final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(call);
boolean is15OrHigher = languageLevel.compareTo(LanguageLevel.JDK_1_5) >= 0;
//JLS3 15.8.2
if (is15OrHigher &&
GET_CLASS_METHOD.equals(method.getName()) &&
CommonClassNames.JAVA_LANG_OBJECT.equals(method.getContainingClass().getQualifiedName())) {
PsiExpression qualifier = methodExpression.getQualifierExpression();
PsiType qualifierType = null;
if (qualifier != null) {
qualifierType = TypeConversionUtil.erasure(qualifier.getType());
}
else {
ASTNode parent = call.getNode().getTreeParent();
while (parent != null && parent.getElementType() != JavaElementType.CLASS) parent = parent.getTreeParent();
if (parent != null) {
qualifierType = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createType((PsiClass)parent.getPsi());
}
}
if (qualifierType != null) {
PsiClass javaLangClass = JavaPsiFacade.getInstance(manager.getProject()).findClass("java.lang.Class", call.getResolveScope());
if (javaLangClass != null && javaLangClass.getTypeParameters().length == 1) {
Map<PsiTypeParameter, PsiType> map = new HashMap<PsiTypeParameter, PsiType>();
map.put(javaLangClass.getTypeParameters()[0], PsiWildcardType.createExtends(manager, qualifierType));
PsiSubstitutor substitutor = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createSubstitutor(map);
final PsiClassType classType = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory()
.createType(javaLangClass, substitutor, languageLevel);
final PsiElement parent = call.getParent();
return parent instanceof PsiReferenceExpression && parent.getParent() instanceof PsiMethodCallExpression
? PsiUtil.captureToplevelWildcards(classType, methodExpression) : classType;
}
}
final PsiType getClassReturnType = PsiTypesUtil.patchMethodGetClassReturnType(call, methodExpression, method,
new Condition<IElementType>() {
@Override
public boolean value(IElementType type) {
return type != JavaElementType.CLASS;
}
}, languageLevel);
if (getClassReturnType != null) {
return getClassReturnType;
}
PsiType ret = method.getReturnType();
@@ -292,15 +292,9 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
if (containingClass.getConstructors().length == 0 &&
!containingClass.isEnum() &&
!containingClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
boolean hasReceiver = false;
final PsiType[] parameterTypes = signature.getParameterTypes();
if (parameterTypes.length == 1 && PsiMethodReferenceUtil.isReceiverType(parameterTypes[0], containingClass, substitutor)) {
hasReceiver = true;
}
final boolean innerClassOuterClassReference = containingClass.getContainingClass() != null && !containingClass.hasModifierProperty(PsiModifier.STATIC);
ClassCandidateInfo candidateInfo = null;
if ((containingClass.getContainingClass() == null || !isLocatedInStaticContext(containingClass)) && parameterTypes.length == 0 || hasReceiver && innerClassOuterClassReference) {
if ((containingClass.getContainingClass() == null || !isLocatedInStaticContext(containingClass)) && signature.getParameterTypes().length == 0 ||
PsiMethodReferenceUtil.onArrayType(containingClass, signature)) {
candidateInfo = new ClassCandidateInfo(containingClass, substitutor);
}
return candidateInfo == null ? JavaResolveResult.EMPTY_ARRAY : new JavaResolveResult[]{candidateInfo};
@@ -427,7 +421,7 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
final boolean staticOrValidConstructorRef = psiMethod.hasModifierProperty(PsiModifier.STATIC) || validConstructorRef;
if ((parameterTypes.length == signatureParameterTypes2.length || varArgs) &&
(!myBeginsWithReferenceType || staticOrValidConstructorRef || (psiMethod.isConstructor() && conflict.isStaticsScopeCorrect()))) {
(!(myBeginsWithReferenceType ^ staticOrValidConstructorRef) || (psiMethod.isConstructor() && conflict.isStaticsScopeCorrect()))) {
boolean correct = true;
for (int i = 0; i < parameterTypes.length; i++) {
final PsiType type1 = subst.substitute(GenericsUtil.eliminateWildcards(parameterTypes[i]));
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 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,7 +18,6 @@ package com.intellij.psi.impl.source.tree.java;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.tree.*;
import com.intellij.psi.tree.ChildRoleBase;
import com.intellij.psi.tree.IElementType;
@@ -39,7 +38,7 @@ public class PsiPackageStatementImpl extends CompositePsiElement implements PsiP
@Override
public String getPackageName() {
PsiJavaCodeReferenceElement ref = getPackageReference();
return ref == null ? null : SourceUtil.getTextSkipWhiteSpaceAndComments(SourceTreeToPsiMap.psiElementToTree(ref));
return ref == null ? null : SourceUtil.getReferenceText(ref);
}
@Override
@@ -730,7 +730,7 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple
private String getCachedTextSkipWhiteSpaceAndComments() {
String whiteSpaceAndComments = myCachedTextSkipWhiteSpaceAndComments;
if (whiteSpaceAndComments == null) {
myCachedTextSkipWhiteSpaceAndComments = whiteSpaceAndComments = SourceUtil.getTextSkipWhiteSpaceAndComments(this);
myCachedTextSkipWhiteSpaceAndComments = whiteSpaceAndComments = SourceUtil.getReferenceText(this);
}
return whiteSpaceAndComments;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -38,7 +38,7 @@ public class PsiReferenceParameterListImpl extends CompositePsiElement implement
@Override
@NotNull
public PsiTypeElement[] getTypeParameterElements() {
return getChildrenAsPsiElements(ElementType.TYPES_BIT_SET, PsiTypeElement.ARRAY_FACTORY);
return getChildrenAsPsiElements(JavaElementType.TYPE, PsiTypeElement.ARRAY_FACTORY);
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -28,8 +28,6 @@ import com.intellij.psi.impl.java.stubs.PsiTypeParameterStub;
import com.intellij.psi.impl.light.LightEmptyImplementsList;
import com.intellij.psi.impl.meta.MetaRegistry;
import com.intellij.psi.impl.source.JavaStubPsiElement;
import com.intellij.psi.impl.source.tree.ChildRole;
import com.intellij.psi.impl.source.tree.ElementType;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.meta.PsiMetaData;
import com.intellij.psi.scope.PsiScopeProcessor;
@@ -44,7 +42,7 @@ import java.util.Collection;
import java.util.List;
/**
* @author dsl
* @author dsl
*/
public class PsiTypeParameterImpl extends JavaStubPsiElement<PsiTypeParameterStub> implements PsiTypeParameter {
private final LightEmptyImplementsList myLightEmptyImplementsList = new LightEmptyImplementsList(null) {
@@ -169,7 +167,7 @@ public class PsiTypeParameterImpl extends JavaStubPsiElement<PsiTypeParameterStu
return PsiTreeUtil.getParentOfType(this, PsiTypeParameterListOwner.class);
}
return (PsiTypeParameterListOwner) parentParent;
return (PsiTypeParameterListOwner)parentParent;
}
@@ -183,9 +181,10 @@ public class PsiTypeParameterImpl extends JavaStubPsiElement<PsiTypeParameterStu
int ret = 0;
PsiElement element = getPrevSibling();
while(element != null){
if(element instanceof PsiTypeParameter)
while (element != null) {
if (element instanceof PsiTypeParameter) {
ret++;
}
element = element.getPrevSibling();
}
return ret;
@@ -194,11 +193,14 @@ public class PsiTypeParameterImpl extends JavaStubPsiElement<PsiTypeParameterStu
@Override
@NotNull
public PsiIdentifier getNameIdentifier() {
return (PsiIdentifier) calcTreeElement().findChildByRole(ChildRole.NAME);
return PsiTreeUtil.getRequiredChildOfType(this, PsiIdentifier.class);
}
@Override
public boolean processDeclarations(@NotNull PsiScopeProcessor processor, @NotNull ResolveState state, PsiElement lastParent, @NotNull PsiElement place){
public boolean processDeclarations(@NotNull PsiScopeProcessor processor,
@NotNull ResolveState state,
PsiElement lastParent,
@NotNull PsiElement place) {
return PsiClassImplUtil.processDeclarationsInClass(this, processor, state, null, lastParent, place, false);
}
@@ -361,7 +363,7 @@ public class PsiTypeParameterImpl extends JavaStubPsiElement<PsiTypeParameterStu
return "PsiTypeParameter:" + getName();
}
public PsiMetaData getMetaData(){
public PsiMetaData getMetaData() {
return MetaRegistry.getMeta(this);
}
@@ -384,7 +386,7 @@ public class PsiTypeParameterImpl extends JavaStubPsiElement<PsiTypeParameterStu
@Override
@NotNull
public PsiAnnotation[] getAnnotations() {
return getStubOrPsiChildren(ElementType.ANNOTATIONS, PsiAnnotation.ARRAY_FACTORY);
return getStubOrPsiChildren(JavaStubElementTypes.ANNOTATION, PsiAnnotation.ARRAY_FACTORY);
}
@Override
@@ -397,6 +399,7 @@ public class PsiTypeParameterImpl extends JavaStubPsiElement<PsiTypeParameterStu
public PsiAnnotation addAnnotation(@NotNull @NonNls String qualifiedName) {
throw new IncorrectOperationException();
}
@Override
@NotNull
public PsiAnnotation[] getApplicableAnnotations() {
@@ -67,7 +67,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
checkSameSignatures(conflicts);
if (conflicts.size() == 1) return conflicts.get(0);
checkAccessLevels(conflicts);
checkAccessStaticLevels(conflicts, true);
if (conflicts.size() == 1) return conflicts.get(0);
checkParametersNumber(conflicts, myActualParameterTypes.length, false);
@@ -89,6 +89,9 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
checkPrimitiveVarargs(conflicts, myActualParameterTypes.length);
if (conflicts.size() == 1) return conflicts.get(0);
checkAccessStaticLevels(conflicts, false);
if (conflicts.size() == 1) return conflicts.get(0);
THashSet<CandidateInfo> uniques = new THashSet<CandidateInfo>(conflicts);
if (uniques.size() == 1) return uniques.iterator().next();
return null;
@@ -123,12 +126,9 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
}
}
}
LambdaUtil.checkMoreSpecificReturnType(conflicts, i);
}
else if (parameterType instanceof PsiMethodReferenceType) {
LambdaUtil.checkMoreSpecificReturnType(conflicts, i);
}
}
LambdaUtil.checkMoreSpecificReturnType(conflicts, myActualParameterTypes);
}
public void checkSpecifics(List<CandidateInfo> conflicts, @MethodCandidateInfo.ApplicabilityLevelConstant int applicabilityLevel) {
@@ -158,7 +158,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
}
}
private static void checkAccessLevels(List<CandidateInfo> conflicts) {
private static void checkAccessStaticLevels(List<CandidateInfo> conflicts, boolean checkAccessible) {
int conflictsCount = conflicts.size();
int maxCheckLevel = -1;
@@ -166,7 +166,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
int index = 0;
for (final CandidateInfo conflict : conflicts) {
final MethodCandidateInfo method = (MethodCandidateInfo)conflict;
final int level = getCheckLevel(method);
final int level = checkAccessible ? getCheckAccessLevel(method) : getCheckStaticLevel(method);
checkLevels[index++] = level;
maxCheckLevel = Math.max(maxCheckLevel, level);
}
@@ -379,11 +379,14 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
return level;
}
private static int getCheckLevel(MethodCandidateInfo method){
boolean visible = method.isAccessible();// && !method.myStaticProblem;
private static int getCheckAccessLevel(MethodCandidateInfo method){
boolean visible = method.isAccessible();
return visible ? 1 : 0;
}
private static int getCheckStaticLevel(MethodCandidateInfo method){
boolean available = method.isStaticsScopeCorrect();
return (visible ? 1 : 0) << 2 |
(available ? 1 : 0) << 1 |
return (available ? 1 : 0) << 1 |
(method.getCurrentFileResolveScope() instanceof PsiImportStaticStatement ? 0 : 1);
}
@@ -550,7 +553,9 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
}
if (isMoreSpecific == null) {
if (!JavaVersionService.getInstance().isAtLeast(myArgumentsList, JavaSdkVersion.JDK_1_7) ||
!MethodSignatureUtil.areParametersErasureEqual(method1, method2)) {
!MethodSignatureUtil.areParametersErasureEqual(method1, method2) ||
InheritanceUtil.isInheritorOrSelf(class1, class2, true) ||
InheritanceUtil.isInheritorOrSelf(class2, class1, true)) {
if (typeParameters1.length < typeParameters2.length) return Specifics.FIRST;
if (typeParameters1.length > typeParameters2.length) return Specifics.SECOND;
}
@@ -0,0 +1,5 @@
class Foo {
{
try<caret>
}
}
@@ -0,0 +1,8 @@
class Foo {
{
try
{
<caret>
}
}
}
@@ -0,0 +1,5 @@
class Foo {
{
do<caret>
}
}
@@ -0,0 +1,7 @@
class Foo {
{
do {
<caret>
}
}
}
@@ -0,0 +1,12 @@
public class Foo {
Zoo foo() {
return r<caret>
}
void rMethod() {}
}
enum Zoo {
LEFT, RIGHT
}
@@ -44,6 +44,6 @@ class UnsupportedFeatures {
}
interface I {
<error descr="Extension methods are not supported at this language level">void m() default { }</error>
<error descr="Extension methods are not supported at this language level">default void m() { }</error>
}
}
@@ -0,0 +1,11 @@
class Foo {
public void foo() {}
public static void foo(String... s){}
}
class A {
{
Foo.<error descr="Non-static method 'foo()' cannot be referenced from a static context">foo</error>();
}
}
@@ -0,0 +1,13 @@
package pck;
class A {
public void bar(I a, Class<Long> any) {
System.out.println(a.with(any));
}
interface I {
<error descr="'with(Class<T>)' clashes with 'with(Class<Long>)'; both methods have same erasure"><T> T with(Class<T> aClass)</error>;
long with(Class<Long> aClass);
}
}
@@ -0,0 +1,11 @@
class Test {
interface F<T extends Throwable> {
void _(T t) throws T;
}
<K extends Throwable> void foo(F<K> f) throws K { }
{
foo(<error descr="Cyclic inference">(t)->{}</error>);
<error descr="Unhandled exception: java.lang.ClassNotFoundException">foo((ClassNotFoundException t)->{});</error>
}
}

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